FIX: Intercept IDLE event in DropDown to fix various problems on MacOS
Change-Id: Ia9aa96c90f1b7c3f6c33b7325dc28a4f780969c3
This commit is contained in:
parent
ace72ecdbc
commit
646934953c
|
@ -317,25 +317,14 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
|
||||||
c_editor->SetSelection(atoi(data.GetText().c_str()) - 1);
|
c_editor->SetSelection(atoi(data.GetText().c_str()) - 1);
|
||||||
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifdef __linux__
|
||||||
c_editor->Bind(wxEVT_COMBOBOX, [this, c_editor](wxCommandEvent& evt) {
|
c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
|
||||||
// to avoid event propagation to other sidebar items
|
// to avoid event propagation to other sidebar items
|
||||||
evt.StopPropagation();
|
evt.StopPropagation();
|
||||||
// FinishEditing grabs new selection and triggers config update. We better call
|
// FinishEditing grabs new selection and triggers config update. We better call
|
||||||
// it explicitly, automatic update on KILL_FOCUS didn't work on Linux.
|
// it explicitly, automatic update on KILL_FOCUS didn't work on Linux.
|
||||||
c_editor->SetClientData(this);
|
|
||||||
this->FinishEditing();
|
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
|
#else
|
||||||
// to avoid event propagation to other sidebar items
|
// to avoid event propagation to other sidebar items
|
||||||
c_editor->Bind(wxEVT_COMBOBOX, [](wxCommandEvent& evt) { evt.StopPropagation(); });
|
c_editor->Bind(wxEVT_COMBOBOX, [](wxCommandEvent& evt) { evt.StopPropagation(); });
|
||||||
|
|
|
@ -4741,9 +4741,7 @@ void ObjectList::OnEditingStarted(wxDataViewEvent &event)
|
||||||
auto item = event.GetItem();
|
auto item = event.GetItem();
|
||||||
if (!renderer->GetEditorCtrl()) {
|
if (!renderer->GetEditorCtrl()) {
|
||||||
renderer->StartEditing(item, GetItemRect(item, column));
|
renderer->StartEditing(item, GetItemRect(item, column));
|
||||||
if (col == colFilament) // TODO: not handle KILL_FOCUS from ComboBox
|
if (col == colName) // TODO: for colName editing, disable shortcuts
|
||||||
renderer->GetEditorCtrl()->PopEventHandler();
|
|
||||||
else if (col == colName) // TODO: for colName editing, disable shortcuts
|
|
||||||
SetAcceleratorTable(wxNullAcceleratorTable);
|
SetAcceleratorTable(wxNullAcceleratorTable);
|
||||||
}
|
}
|
||||||
#endif //__WXMSW__
|
#endif //__WXMSW__
|
||||||
|
|
|
@ -26,13 +26,14 @@ ComboBox::ComboBox(wxWindow * parent,
|
||||||
int n,
|
int n,
|
||||||
const wxString choices[],
|
const wxString choices[],
|
||||||
long style)
|
long style)
|
||||||
: drop(this, texts, icons, style & DD_STYLE_MASK)
|
: drop(texts, icons)
|
||||||
{
|
{
|
||||||
if (style & wxCB_READONLY)
|
if (style & wxCB_READONLY)
|
||||||
style |= wxRIGHT;
|
style |= wxRIGHT;
|
||||||
text_off = style & CB_NO_TEXT;
|
text_off = style & CB_NO_TEXT;
|
||||||
TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size,
|
TextInput::Create(parent, "", value, (style & CB_NO_DROP_ICON) ? "" : "drop_down", pos, size,
|
||||||
style | wxTE_PROCESS_ENTER);
|
style | wxTE_PROCESS_ENTER);
|
||||||
|
drop.Create(this, style & DD_STYLE_MASK);
|
||||||
|
|
||||||
if (style & wxCB_READONLY) {
|
if (style & wxCB_READONLY) {
|
||||||
GetTextCtrl()->Hide();
|
GetTextCtrl()->Hide();
|
||||||
|
@ -52,16 +53,12 @@ ComboBox::ComboBox(wxWindow * parent,
|
||||||
SetSelection(e.GetInt());
|
SetSelection(e.GetInt());
|
||||||
e.SetEventObject(this);
|
e.SetEventObject(this);
|
||||||
e.SetId(GetId());
|
e.SetId(GetId());
|
||||||
wxMouseEvent e1;
|
|
||||||
mouseDown(e1);
|
|
||||||
GetEventHandler()->ProcessEvent(e);
|
GetEventHandler()->ProcessEvent(e);
|
||||||
});
|
});
|
||||||
drop.Bind(wxEVT_SHOW, [this](auto &e) {
|
drop.Bind(EVT_DISMISS, [this](auto &) {
|
||||||
if (!e.IsShown()) {
|
drop_down = false;
|
||||||
drop_down = false;
|
wxCommandEvent e(wxEVT_COMBOBOX_CLOSEUP);
|
||||||
wxCommandEvent e(wxEVT_COMBOBOX_CLOSEUP);
|
GetEventHandler()->ProcessEvent(e);
|
||||||
GetEventHandler()->ProcessEvent(e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
for (int i = 0; i < n; ++i) Append(choices[i]);
|
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)
|
void ComboBox::mouseDown(wxMouseEvent &event)
|
||||||
{
|
{
|
||||||
SetFocus();
|
//SetFocus();
|
||||||
if (drop_down) {
|
if (drop_down) {
|
||||||
drop.Hide();
|
drop.Hide();
|
||||||
} else if (drop.HasDismissLongTime()) {
|
} else if (drop.HasDismissLongTime()) {
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <wx/dcgraph.h>
|
#include <wx/dcgraph.h>
|
||||||
|
|
||||||
|
wxDEFINE_EVENT(EVT_DISMISS, wxCommandEvent);
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(DropDown, wxPopupTransientWindow)
|
BEGIN_EVENT_TABLE(DropDown, wxPopupTransientWindow)
|
||||||
|
|
||||||
EVT_LEFT_DOWN(DropDown::mouseDown)
|
EVT_LEFT_DOWN(DropDown::mouseDown)
|
||||||
|
@ -21,12 +23,9 @@ END_EVENT_TABLE()
|
||||||
* calling Refresh()/Update().
|
* calling Refresh()/Update().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DropDown::DropDown(wxWindow * parent,
|
DropDown::DropDown(std::vector<wxString> &texts,
|
||||||
std::vector<wxString> &texts,
|
std::vector<wxBitmap> &icons)
|
||||||
std::vector<wxBitmap> &icons,
|
: texts(texts)
|
||||||
long style)
|
|
||||||
: wxPopupTransientWindow(parent)
|
|
||||||
, texts(texts)
|
|
||||||
, icons(icons)
|
, icons(icons)
|
||||||
, state_handler(this)
|
, state_handler(this)
|
||||||
, border_color(0xDBDBDB)
|
, border_color(0xDBDBDB)
|
||||||
|
@ -36,6 +35,21 @@ DropDown::DropDown(wxWindow * parent,
|
||||||
, selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked),
|
, selector_background_color(std::make_pair(0xEDFAF2, (int) StateColor::Checked),
|
||||||
std::make_pair(*wxWHITE, (int) StateColor::Normal))
|
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);
|
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||||
SetBackgroundColour(*wxWHITE);
|
SetBackgroundColour(*wxWHITE);
|
||||||
state_handler.attach({&border_color, &text_color, &selector_border_color, &selector_background_color});
|
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
|
// BBS set default font
|
||||||
SetFont(Label::Body_14);
|
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)
|
void DropDown::Invalidate(bool clear)
|
||||||
|
@ -352,27 +371,31 @@ void DropDown::autoPosition()
|
||||||
|
|
||||||
void DropDown::mouseDown(wxMouseEvent& event)
|
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;
|
pressedDown = true;
|
||||||
CaptureMouse();
|
|
||||||
dragStart = event.GetPosition();
|
dragStart = event.GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropDown::mouseReleased(wxMouseEvent& event)
|
void DropDown::mouseReleased(wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
if (pressedDown) {
|
if (pressedDown) {
|
||||||
ReleaseMouse();
|
|
||||||
dragStart = wxPoint();
|
dragStart = wxPoint();
|
||||||
pressedDown = false;
|
pressedDown = false;
|
||||||
if (hover_item >= 0) // not moved
|
if (hover_item >= 0) { // not moved
|
||||||
sendDropDownEvent();
|
sendDropDownEvent();
|
||||||
DismissAndNotify();
|
DismissAndNotify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropDown::mouseMove(wxMouseEvent &event)
|
void DropDown::mouseMove(wxMouseEvent &event)
|
||||||
{
|
{
|
||||||
|
wxPoint pt = event.GetPosition();
|
||||||
if (pressedDown) {
|
if (pressedDown) {
|
||||||
wxPoint pt = event.GetPosition();
|
|
||||||
wxPoint pt2 = offset + pt - dragStart;
|
wxPoint pt2 = offset + pt - dragStart;
|
||||||
dragStart = pt;
|
dragStart = pt;
|
||||||
if (pt2.y > 0)
|
if (pt2.y > 0)
|
||||||
|
@ -387,7 +410,7 @@ void DropDown::mouseMove(wxMouseEvent &event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!pressedDown || hover_item >= 0) {
|
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 >= (int) texts.size()) hover = -1;
|
||||||
if (hover == hover_item) return;
|
if (hover == hover_item) return;
|
||||||
hover_item = hover;
|
hover_item = hover;
|
||||||
|
@ -434,4 +457,6 @@ void DropDown::OnDismiss()
|
||||||
{
|
{
|
||||||
dismissTime = boost::posix_time::microsec_clock::universal_time();
|
dismissTime = boost::posix_time::microsec_clock::universal_time();
|
||||||
hover_item = -1;
|
hover_item = -1;
|
||||||
|
wxCommandEvent e(EVT_DISMISS);
|
||||||
|
GetEventHandler()->ProcessEvent(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#define DD_NO_TEXT 0x2000000
|
#define DD_NO_TEXT 0x2000000
|
||||||
#define DD_STYLE_MASK 0x3000000
|
#define DD_STYLE_MASK 0x3000000
|
||||||
|
|
||||||
|
wxDECLARE_EVENT(EVT_DISMISS, wxCommandEvent);
|
||||||
|
|
||||||
class DropDown : public wxPopupTransientWindow
|
class DropDown : public wxPopupTransientWindow
|
||||||
{
|
{
|
||||||
std::vector<wxString> & texts;
|
std::vector<wxString> & texts;
|
||||||
|
@ -39,11 +41,17 @@ class DropDown : public wxPopupTransientWindow
|
||||||
wxPoint dragStart;
|
wxPoint dragStart;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
DropDown(std::vector<wxString> &texts,
|
||||||
|
std::vector<wxBitmap> &icons);
|
||||||
|
|
||||||
DropDown(wxWindow * parent,
|
DropDown(wxWindow * parent,
|
||||||
std::vector<wxString> &texts,
|
std::vector<wxString> &texts,
|
||||||
std::vector<wxBitmap> &icons,
|
std::vector<wxBitmap> &icons,
|
||||||
long style = 0);
|
long style = 0);
|
||||||
|
|
||||||
|
void Create(wxWindow * parent,
|
||||||
|
long style = 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Invalidate(bool clear = false);
|
void Invalidate(bool clear = false);
|
||||||
|
|
||||||
|
@ -73,6 +81,9 @@ public:
|
||||||
void Rescale();
|
void Rescale();
|
||||||
|
|
||||||
bool HasDismissLongTime();
|
bool HasDismissLongTime();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void OnDismiss() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paintEvent(wxPaintEvent& evt);
|
void paintEvent(wxPaintEvent& evt);
|
||||||
|
@ -92,7 +103,6 @@ private:
|
||||||
|
|
||||||
void sendDropDownEvent();
|
void sendDropDownEvent();
|
||||||
|
|
||||||
void OnDismiss() override;
|
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue