[ 1584680 ] wxComboCtrl Popup Animation
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42407 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -44,10 +44,6 @@
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Milliseconds to wait for two mouse-ups after focus inorder
|
||||
// to trigger a double-click.
|
||||
#define DOUBLE_CLICK_CONVERSION_TRESHOLD 500
|
||||
|
||||
#define DEFAULT_DROPBUTTON_WIDTH 19
|
||||
|
||||
#define BMP_BUTTON_MARGIN 4
|
||||
@@ -344,20 +340,50 @@ public:
|
||||
style)
|
||||
#endif
|
||||
{
|
||||
m_inShow = 0;
|
||||
}
|
||||
|
||||
#if USES_WXPOPUPTRANSIENTWINDOW
|
||||
virtual bool Show( bool show );
|
||||
virtual bool ProcessLeftDown(wxMouseEvent& event);
|
||||
virtual void OnDismiss();
|
||||
#endif
|
||||
|
||||
private:
|
||||
wxByte m_inShow;
|
||||
};
|
||||
|
||||
|
||||
#if USES_WXPOPUPTRANSIENTWINDOW
|
||||
bool wxComboPopupWindow::ProcessLeftDown(wxMouseEvent& event )
|
||||
bool wxComboPopupWindow::Show( bool show )
|
||||
{
|
||||
return wxComboPopupWindowBase::ProcessLeftDown(event);
|
||||
// Guard against recursion
|
||||
if ( m_inShow )
|
||||
return wxComboPopupWindowBase::Show(show);
|
||||
|
||||
m_inShow++;
|
||||
|
||||
wxASSERT( IsKindOf(CLASSINFO(wxPopupTransientWindow)) );
|
||||
|
||||
wxPopupTransientWindow* ptw = (wxPopupTransientWindow*) this;
|
||||
wxComboCtrlBase* combo = (wxComboCtrlBase*) GetParent();
|
||||
|
||||
if ( show != ptw->IsShown() )
|
||||
{
|
||||
if ( show )
|
||||
ptw->Popup(combo->GetPopupControl()->GetControl());
|
||||
else
|
||||
ptw->Dismiss();
|
||||
}
|
||||
|
||||
m_inShow--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxComboPopupWindow::ProcessLeftDown(wxMouseEvent& event)
|
||||
{
|
||||
return wxPopupTransientWindow::ProcessLeftDown(event);
|
||||
}
|
||||
|
||||
// First thing that happens when a transient popup closes is that this method gets called.
|
||||
@@ -387,6 +413,7 @@ public:
|
||||
m_combo = parent;
|
||||
}
|
||||
|
||||
void OnSizeEvent( wxSizeEvent& event );
|
||||
void OnKeyEvent(wxKeyEvent& event);
|
||||
#if USES_WXDIALOG
|
||||
void OnActivate( wxActivateEvent& event );
|
||||
@@ -405,9 +432,15 @@ BEGIN_EVENT_TABLE(wxComboPopupWindowEvtHandler, wxEvtHandler)
|
||||
#if USES_WXDIALOG
|
||||
EVT_ACTIVATE(wxComboPopupWindowEvtHandler::OnActivate)
|
||||
#endif
|
||||
EVT_SIZE(wxComboPopupWindowEvtHandler::OnSizeEvent)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
void wxComboPopupWindowEvtHandler::OnSizeEvent( wxSizeEvent& WXUNUSED(event) )
|
||||
{
|
||||
// Block the event so that the popup control does not get auto-resized.
|
||||
}
|
||||
|
||||
void wxComboPopupWindowEvtHandler::OnKeyEvent( wxKeyEvent& event )
|
||||
{
|
||||
// Relay keyboard event to the main child controls
|
||||
@@ -621,7 +654,7 @@ void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event )
|
||||
evtType == wxEVT_RIGHT_DOWN )
|
||||
{
|
||||
// Block motion and click events outside the popup
|
||||
if ( !isInside )
|
||||
if ( !isInside || !m_combo->IsPopupShown() )
|
||||
{
|
||||
event.Skip(false);
|
||||
return;
|
||||
@@ -629,11 +662,10 @@ void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event )
|
||||
}
|
||||
else if ( evtType == wxEVT_LEFT_UP )
|
||||
{
|
||||
// Don't let left-down events in if outside
|
||||
if ( evtType == wxEVT_LEFT_DOWN )
|
||||
if ( !m_combo->IsPopupShown() )
|
||||
{
|
||||
if ( !isInside )
|
||||
return;
|
||||
event.Skip(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_beenInside )
|
||||
@@ -688,7 +720,7 @@ void wxComboCtrlBase::Init()
|
||||
{
|
||||
m_winPopup = (wxWindow *)NULL;
|
||||
m_popup = (wxWindow *)NULL;
|
||||
m_isPopupShown = false;
|
||||
m_popupWinState = Hidden;
|
||||
m_btn = (wxWindow*) NULL;
|
||||
m_text = (wxTextCtrl*) NULL;
|
||||
m_popupInterface = (wxComboPopup*) NULL;
|
||||
@@ -1212,7 +1244,7 @@ void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, bool paintBg )
|
||||
int drawState = m_btnState;
|
||||
|
||||
#ifdef __WXGTK__
|
||||
if ( m_isPopupShown )
|
||||
if ( GetPopupWindowState() >= Animating )
|
||||
drawState |= wxCONTROL_PRESSED;
|
||||
#endif
|
||||
|
||||
@@ -1365,7 +1397,7 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event,
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
else if ( type == wxEVT_LEFT_DOWN )
|
||||
else if ( type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_DCLICK )
|
||||
{
|
||||
if ( flags & (wxCC_MF_ON_CLICK_AREA|wxCC_MF_ON_BUTTON) )
|
||||
{
|
||||
@@ -1406,7 +1438,7 @@ bool wxComboCtrlBase::HandleButtonMouseEvent( wxMouseEvent& event,
|
||||
m_btnState &= ~(wxCONTROL_CURRENT);
|
||||
|
||||
// Mouse hover ends
|
||||
if ( !m_isPopupShown )
|
||||
if ( IsPopupWindowState(Hidden) )
|
||||
{
|
||||
m_btnState &= ~(wxCONTROL_PRESSED);
|
||||
Refresh();
|
||||
@@ -1429,7 +1461,7 @@ bool wxComboCtrlBase::PreprocessMouseEvent( wxMouseEvent& event,
|
||||
#if USES_WXPOPUPWINDOW || USES_WXDIALOG
|
||||
if ( m_popupWinType != POPUPWIN_WXPOPUPTRANSIENTWINDOW )
|
||||
{
|
||||
if ( m_isPopupShown &&
|
||||
if ( IsPopupWindowState(Visible) &&
|
||||
( evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_RIGHT_DOWN ) )
|
||||
{
|
||||
HidePopup();
|
||||
@@ -1455,7 +1487,7 @@ void wxComboCtrlBase::HandleNormalMouseEvent( wxMouseEvent& event )
|
||||
if ( (evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_LEFT_DCLICK) &&
|
||||
(m_windowStyle & wxCB_READONLY) )
|
||||
{
|
||||
if ( m_isPopupShown )
|
||||
if ( GetPopupWindowState() >= Animating )
|
||||
{
|
||||
#if USES_WXPOPUPWINDOW
|
||||
// Click here always hides the popup.
|
||||
@@ -1481,7 +1513,7 @@ void wxComboCtrlBase::HandleNormalMouseEvent( wxMouseEvent& event )
|
||||
}
|
||||
}
|
||||
else
|
||||
if ( m_isPopupShown )
|
||||
if ( IsPopupShown() )
|
||||
{
|
||||
// relay (some) mouse events to the popup
|
||||
if ( evtType == wxEVT_MOUSEWHEEL )
|
||||
@@ -1677,7 +1709,10 @@ void wxComboCtrlBase::OnButtonClick()
|
||||
void wxComboCtrlBase::ShowPopup()
|
||||
{
|
||||
EnsurePopupControl();
|
||||
wxCHECK_RET( !IsPopupShown(), wxT("popup window already shown") );
|
||||
wxCHECK_RET( !IsPopupWindowState(Visible), wxT("popup window already shown") );
|
||||
|
||||
if ( IsPopupWindowState(Animating) )
|
||||
return;
|
||||
|
||||
SetFocus();
|
||||
|
||||
@@ -1793,22 +1828,27 @@ void wxComboCtrlBase::ShowPopup()
|
||||
else
|
||||
popupX = 0;
|
||||
|
||||
int showFlags = CanDeferShow;
|
||||
|
||||
if ( spaceBelow < szp.y )
|
||||
{
|
||||
popupY = scrPos.y - szp.y;
|
||||
showFlags |= ShowAbove;
|
||||
}
|
||||
|
||||
// Move to position
|
||||
//wxLogDebug(wxT("popup scheduled position1: %i,%i"),ptp.x,ptp.y);
|
||||
//wxLogDebug(wxT("popup position1: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y);
|
||||
#if INSTALL_TOPLEV_HANDLER
|
||||
// Put top level window event handler into place
|
||||
if ( m_popupWinType == POPUPWIN_WXPOPUPWINDOW )
|
||||
{
|
||||
if ( !m_toplevEvtHandler )
|
||||
m_toplevEvtHandler = new wxComboFrameEventHandler(this);
|
||||
|
||||
// Some platforms (GTK) may need these two to be separate
|
||||
winPopup->SetSize( szp.x, szp.y );
|
||||
winPopup->Move( popupX, popupY );
|
||||
|
||||
//wxLogDebug(wxT("popup position2: %i,%i"),winPopup->GetPosition().x,winPopup->GetPosition().y);
|
||||
|
||||
m_popup = popup;
|
||||
wxWindow* toplev = ::wxGetTopLevelParent( this );
|
||||
wxASSERT( toplev );
|
||||
((wxComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup();
|
||||
toplev->PushEventHandler( m_toplevEvtHandler );
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set string selection (must be this way instead of SetStringSelection)
|
||||
if ( m_text )
|
||||
@@ -1825,51 +1865,68 @@ void wxComboCtrlBase::ShowPopup()
|
||||
}
|
||||
|
||||
// This must be after SetStringValue
|
||||
m_isPopupShown = true;
|
||||
m_popupWinState = Animating;
|
||||
|
||||
wxRect popupWinRect( popupX, popupY, szp.x, szp.y );
|
||||
|
||||
m_popup = popup;
|
||||
if ( AnimateShow( popupWinRect, showFlags ) )
|
||||
{
|
||||
DoShowPopup( popupWinRect, showFlags );
|
||||
}
|
||||
}
|
||||
|
||||
bool wxComboCtrlBase::AnimateShow( const wxRect& WXUNUSED(rect), int WXUNUSED(flags) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxComboCtrlBase::DoShowPopup( const wxRect& rect, int WXUNUSED(flags) )
|
||||
{
|
||||
wxWindow* winPopup = m_winPopup;
|
||||
|
||||
if ( IsPopupWindowState(Animating) )
|
||||
{
|
||||
// Make sure the popup window is shown in the right position.
|
||||
// Should not matter even if animation already did this.
|
||||
|
||||
// Some platforms (GTK) may like SetSize and Move to be separate
|
||||
// (though the bug was probably fixed).
|
||||
winPopup->SetSize( rect );
|
||||
|
||||
// Show it
|
||||
#if USES_WXPOPUPTRANSIENTWINDOW
|
||||
if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW )
|
||||
((wxPopupTransientWindow*)winPopup)->Popup(popup);
|
||||
else
|
||||
#endif
|
||||
winPopup->Show();
|
||||
|
||||
#if INSTALL_TOPLEV_HANDLER
|
||||
// Put top level window event handler into place
|
||||
if ( m_popupWinType == POPUPWIN_WXPOPUPWINDOW )
|
||||
{
|
||||
if ( !m_toplevEvtHandler )
|
||||
m_toplevEvtHandler = new wxComboFrameEventHandler(this);
|
||||
|
||||
wxWindow* toplev = ::wxGetTopLevelParent( this );
|
||||
wxASSERT( toplev );
|
||||
((wxComboFrameEventHandler*)m_toplevEvtHandler)->OnPopup();
|
||||
toplev->PushEventHandler( m_toplevEvtHandler );
|
||||
m_popupWinState = Visible;
|
||||
}
|
||||
#endif
|
||||
else if ( IsPopupWindowState(Hidden) )
|
||||
{
|
||||
// Animation was aborted
|
||||
|
||||
wxASSERT( !winPopup->IsShown() );
|
||||
|
||||
m_popupWinState = Hidden;
|
||||
}
|
||||
}
|
||||
|
||||
void wxComboCtrlBase::OnPopupDismiss()
|
||||
{
|
||||
{
|
||||
// Just in case, avoid double dismiss
|
||||
if ( !m_isPopupShown )
|
||||
if ( IsPopupWindowState(Hidden) )
|
||||
return;
|
||||
|
||||
// NB: Focus setting is really funny, atleast on wxMSW. First of all,
|
||||
// we need to have SetFocus at the end. Otherwise wxTextCtrl may
|
||||
// freeze until focus goes somewhere else. Second, wxTreeCtrl as
|
||||
// popup, when dismissing, "steals" focus back to itself unless
|
||||
// SetFocus is called also here, exactly before m_isPopupShown
|
||||
// SetFocus is called also here, exactly before m_popupWinState
|
||||
// is set to false. Which is truly weird since SetFocus is just
|
||||
// wxWindowMSW method and does not call event handler or anything like
|
||||
// that (ie. does not care about m_isPopupShown).
|
||||
// that (ie. does not care about m_popupWinState).
|
||||
|
||||
SetFocus();
|
||||
|
||||
// This should preferably be set before focus.
|
||||
m_isPopupShown = false;
|
||||
m_popupWinState = Hidden;
|
||||
|
||||
// Inform popup control itself
|
||||
m_popupInterface->OnDismiss();
|
||||
@@ -1887,7 +1944,10 @@ void wxComboCtrlBase::OnPopupDismiss()
|
||||
}
|
||||
#endif
|
||||
|
||||
m_timeCanAcceptClick = ::wxGetLocalTimeMillis() + 150;
|
||||
m_timeCanAcceptClick = ::wxGetLocalTimeMillis();
|
||||
|
||||
if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW )
|
||||
m_timeCanAcceptClick += 150;
|
||||
|
||||
// If cursor not on dropdown button, then clear its state
|
||||
// (technically not required by all ports, but do it for all just in case)
|
||||
@@ -1912,19 +1972,14 @@ void wxComboCtrlBase::OnPopupDismiss()
|
||||
void wxComboCtrlBase::HidePopup()
|
||||
{
|
||||
// Should be able to call this without popup interface
|
||||
//wxCHECK_RET( m_popupInterface, _T("no popup interface") );
|
||||
if ( !m_isPopupShown )
|
||||
if ( IsPopupWindowState(Hidden) )
|
||||
return;
|
||||
|
||||
// transfer value and show it in textctrl, if any
|
||||
SetValue( m_popupInterface->GetStringValue() );
|
||||
if ( !IsPopupWindowState(Animating) )
|
||||
SetValue( m_popupInterface->GetStringValue() );
|
||||
|
||||
#if USES_WXPOPUPTRANSIENTWINDOW
|
||||
if ( m_popupWinType == POPUPWIN_WXPOPUPTRANSIENTWINDOW )
|
||||
((wxPopupTransientWindow*)m_winPopup)->Dismiss();
|
||||
else
|
||||
#endif
|
||||
m_winPopup->Hide();
|
||||
m_winPopup->Hide();
|
||||
|
||||
OnPopupDismiss();
|
||||
}
|
||||
|
Reference in New Issue
Block a user