Make animation of combo-popdown optional.

Replace wxMiniSleep() + wxYield() implemenation
    by wxTimer based one.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42470 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
2006-10-26 20:35:57 +00:00
parent 470402b996
commit 30be036c6d
6 changed files with 195 additions and 69 deletions

View File

@@ -295,6 +295,14 @@ In this case, \helpref{AnimateShow}{wxcomboctrlanimateshow} must return \false.}
\end{twocollist} \end{twocollist}
\membersection{wxComboCtrl::EnablePopupAnimation}\label{wxcomboctrlenablepopupanimation}
\func{void}{EnablePopupAnimation}{\param{bool }{enable = true}}
Enables or disables popup animation, if any, depending on the value of
the argument.
\membersection{wxComboCtrl::GetBitmapDisabled}\label{wxcomboctrlgetbitmapdisabled} \membersection{wxComboCtrl::GetBitmapDisabled}\label{wxcomboctrlgetbitmapdisabled}
\constfunc{const wxBitmap\&}{GetBitmapDisabled}{\void} \constfunc{const wxBitmap\&}{GetBitmapDisabled}{\void}

View File

@@ -85,7 +85,9 @@ enum
// Internal use: Set wxTAB_TRAVERSAL to parent when popup is dismissed // Internal use: Set wxTAB_TRAVERSAL to parent when popup is dismissed
wxCC_IFLAG_PARENT_TAB_TRAVERSAL = 0x0800, wxCC_IFLAG_PARENT_TAB_TRAVERSAL = 0x0800,
// Internal use: Secondary popup window type should be used (if available). // Internal use: Secondary popup window type should be used (if available).
wxCC_IFLAG_USE_ALT_POPUP = 0x1000 wxCC_IFLAG_USE_ALT_POPUP = 0x1000,
// Internal use: Skip popup animation.
wxCC_IFLAG_DISABLE_POPUP_ANIM = 0x2000
}; };
@@ -322,6 +324,15 @@ public:
m_iFlags &= ~wxCC_IFLAG_USE_ALT_POPUP; m_iFlags &= ~wxCC_IFLAG_USE_ALT_POPUP;
} }
// Call with false to disable popup animation, if any.
void EnablePopupAnimation( bool enable = true )
{
if ( enable )
m_iFlags &= ~wxCC_IFLAG_DISABLE_POPUP_ANIM;
else
m_iFlags |= wxCC_IFLAG_DISABLE_POPUP_ANIM;
}
// //
// Utilies needed by the popups or native implementations // Utilies needed by the popups or native implementations
// //

View File

@@ -18,6 +18,14 @@
#if wxUSE_COMBOCTRL #if wxUSE_COMBOCTRL
#if !defined(__WXWINCE__) && wxUSE_TIMER
#include "wx/timer.h"
#define wxUSE_COMBOCTRL_POPUP_ANIMATION 1
#else
#define wxUSE_COMBOCTRL_POPUP_ANIMATION 0
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Native wxComboCtrl // Native wxComboCtrl
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -60,11 +68,15 @@ public:
virtual ~wxComboCtrl(); virtual ~wxComboCtrl();
virtual void PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const; virtual void PrepareBackground( wxDC& dc, const wxRect& rect, int flags ) const;
virtual bool AnimateShow( const wxRect& rect, int flags );
virtual bool IsKeyPopupToggle(const wxKeyEvent& event) const; virtual bool IsKeyPopupToggle(const wxKeyEvent& event) const;
static int GetFeatures() { return wxComboCtrlFeatures::All; } static int GetFeatures() { return wxComboCtrlFeatures::All; }
#if wxUSE_COMBOCTRL_POPUP_ANIMATION
virtual bool AnimateShow( const wxRect& rect, int flags );
void OnTimerEvent( wxTimerEvent& event );
#endif
protected: protected:
// customization // customization
@@ -79,6 +91,14 @@ protected:
private: private:
void Init(); void Init();
#if wxUSE_COMBOCTRL_POPUP_ANIMATION
// Popup animation related
wxLongLong m_animStart;
wxTimer m_animTimer;
wxRect m_animRect;
int m_animFlags;
#endif
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
DECLARE_DYNAMIC_CLASS(wxComboCtrl) DECLARE_DYNAMIC_CLASS(wxComboCtrl)

View File

@@ -494,31 +494,72 @@ BEGIN_EVENT_TABLE(TreeCtrlComboPopup, wxTreeCtrl)
END_EVENT_TABLE() END_EVENT_TABLE()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxComboCtrl with custom popup animation // wxComboCtrl with custom popup animation. We use EVT_TIMER, which is quite
// safe, but requires much more can than doing it in a single function (ie.
// AnimateShow) and using combination of wxSleep and wxSafeYield.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#if wxUSE_TIMER
#define CUSTOM_COMBOBOX_ANIMATION_DURATION 200 // In milliseconds
#include "wx/timer.h"
class wxComboCtrlWithCustomPopupAnim : public wxComboCtrl class wxComboCtrlWithCustomPopupAnim : public wxComboCtrl
{ {
public: public:
virtual bool AnimateShow( const wxRect& rect, int WXUNUSED(flags) ) virtual bool AnimateShow( const wxRect& rect, int flags )
{ {
MyFrame* myFrame = (MyFrame*) ::wxGetTopLevelParent(this); MyFrame* myFrame = (MyFrame*) ::wxGetTopLevelParent(this);
if ( !myFrame->m_cbUseAnim->GetValue() ) if ( !myFrame->m_cbUseAnim->GetValue() )
return true; return true;
m_animStart = ::wxGetLocalTimeMillis();
m_animRect = rect;
m_animFlags = flags;
wxScreenDC dc;
wxBitmap bitmap( rect.width, rect.height, -1 );
wxMemoryDC memdc( bitmap );
memdc.Blit( 0, 0, rect.width, rect.height, &dc, rect.x, rect.y );
memdc.SelectObject(wxNullBitmap);
m_animBackBitmap = bitmap;
m_animTimer.SetOwner( this, wxID_ANY );
m_animTimer.Start( 10, wxTIMER_CONTINUOUS );
OnTimerEvent(*((wxTimerEvent*)NULL)); // Event is never used, so we can give NULL
return false;
}
void OnTimerEvent( wxTimerEvent& WXUNUSED(event) )
{
bool stopTimer = false;
wxWindow* popup = GetPopupControl()->GetControl();
wxScreenDC dc;
const wxRect& rect = m_animRect;
// Popup was hidden before it was fully shown?
if ( IsPopupWindowState(Hidden) )
{
stopTimer = true;
}
else
{
wxLongLong t = ::wxGetLocalTimeMillis();
int pos = (int) (t-m_animStart).GetLo();
if ( pos < CUSTOM_COMBOBOX_ANIMATION_DURATION )
{
//
// Actual animation happens here
//
int width = rect.width; int width = rect.width;
int height = rect.height; int height = rect.height;
wxBitmap bitmap( width, height, -1 );
wxScreenDC dc;
wxMemoryDC memdc( bitmap );
memdc.Blit( 0, 0, width, height, &dc, rect.x, rect.y );
memdc.SelectObject(wxNullBitmap);
wxLongLong tStart = ::wxGetLocalTimeMillis();
const int delay = 300;
const int resolution = 10;
int center_x = rect.x + (width/2); int center_x = rect.x + (width/2);
int center_y = rect.y + (height/2); int center_y = rect.y + (height/2);
@@ -527,32 +568,52 @@ public:
dc.SetPen( *wxBLACK_PEN ); dc.SetPen( *wxBLACK_PEN );
dc.SetBrush( *wxTRANSPARENT_BRUSH ); dc.SetBrush( *wxTRANSPARENT_BRUSH );
for (;;)
{
wxLongLong t = ::wxGetLocalTimeMillis();
int pos = (int) (t-tStart).GetLo();
if ( pos > delay )
break;
int w = (((pos*256)/delay)*width)/256; int w = (((pos*256)/CUSTOM_COMBOBOX_ANIMATION_DURATION)*width)/256;
double ratio = ((double)w / (double)width); double ratio = ((double)w / (double)width);
int h = (int)(d_height * ratio); int h = (int)(d_height * ratio);
dc.DrawBitmap( m_animBackBitmap, rect.x, rect.y );
dc.DrawRectangle( center_x - w/2, center_y - h/2, w, h ); dc.DrawRectangle( center_x - w/2, center_y - h/2, w, h );
wxMilliSleep( resolution ); }
wxYield(); else
dc.DrawBitmap( bitmap, rect.x, rect.y ); {
stopTimer = true;
if ( IsPopupWindowState(Hidden) ) }
return true;
} }
return true; if ( stopTimer )
{
dc.DrawBitmap( m_animBackBitmap, rect.x, rect.y );
popup->Move( 0, 0 );
m_animTimer.Stop();
DoShowPopup( m_animRect, m_animFlags );
}
} }
protected: protected:
// Popup animation related
wxLongLong m_animStart;
wxTimer m_animTimer;
wxRect m_animRect;
wxBitmap m_animBackBitmap;
int m_animFlags;
private:
DECLARE_EVENT_TABLE()
}; };
BEGIN_EVENT_TABLE(wxComboCtrlWithCustomPopupAnim, wxComboCtrl)
EVT_TIMER(wxID_ANY, wxComboCtrlWithCustomPopupAnim::OnTimerEvent)
END_EVENT_TABLE()
#else
#define wxComboCtrlWithCustomPopupAnim wxComboCtrl
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxComboCtrl with entirely custom button action (opens file dialog) // wxComboCtrl with entirely custom button action (opens file dialog)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -1870,7 +1870,8 @@ void wxComboCtrlBase::ShowPopup()
wxRect popupWinRect( popupX, popupY, szp.x, szp.y ); wxRect popupWinRect( popupX, popupY, szp.x, szp.y );
m_popup = popup; m_popup = popup;
if ( AnimateShow( popupWinRect, showFlags ) ) if ( (m_iFlags & wxCC_IFLAG_DISABLE_POPUP_ANIM) ||
AnimateShow( popupWinRect, showFlags ) )
{ {
DoShowPopup( popupWinRect, showFlags ); DoShowPopup( popupWinRect, showFlags );
} }

View File

@@ -70,8 +70,13 @@
#define TEXTCTRLXADJUST_CLASSIC 1 #define TEXTCTRLXADJUST_CLASSIC 1
#define TEXTCTRLYADJUST_CLASSIC 2 #define TEXTCTRLYADJUST_CLASSIC 2
#define COMBOBOX_ANIMATION_RESOLUTION 10
#define COMBOBOX_ANIMATION_DURATION 200 // In milliseconds #define COMBOBOX_ANIMATION_DURATION 200 // In milliseconds
#define wxMSW_DESKTOP_USERPREFERENCESMASK_COMBOBOXANIM (1<<26)
// ============================================================================ // ============================================================================
// implementation // implementation
// ============================================================================ // ============================================================================
@@ -80,6 +85,7 @@
BEGIN_EVENT_TABLE(wxComboCtrl, wxComboCtrlBase) BEGIN_EVENT_TABLE(wxComboCtrl, wxComboCtrlBase)
EVT_PAINT(wxComboCtrl::OnPaintEvent) EVT_PAINT(wxComboCtrl::OnPaintEvent)
EVT_MOUSE_EVENTS(wxComboCtrl::OnMouseEvent) EVT_MOUSE_EVENTS(wxComboCtrl::OnMouseEvent)
EVT_TIMER(wxID_ANY, wxComboCtrl::OnTimerEvent)
END_EVENT_TABLE() END_EVENT_TABLE()
@@ -530,7 +536,7 @@ void wxComboCtrl::OnMouseEvent( wxMouseEvent& event )
} }
#if !defined(__WXWINCE__) #if wxUSE_COMBOCTRL_POPUP_ANIMATION
static wxUint32 GetUserPreferencesMask() static wxUint32 GetUserPreferencesMask()
{ {
static wxUint32 userPreferencesMask = 0; static wxUint32 userPreferencesMask = 0;
@@ -559,64 +565,83 @@ static wxUint32 GetUserPreferencesMask()
} }
#endif #endif
bool wxComboCtrl::AnimateShow( const wxRect& rect, int flags ) #if wxUSE_COMBOCTRL_POPUP_ANIMATION
void wxComboCtrl::OnTimerEvent( wxTimerEvent& WXUNUSED(event) )
{ {
#if !defined(__WXWINCE__) bool stopTimer = false;
if ( GetUserPreferencesMask() & (1<<26) )
{
wxLongLong tStart = ::wxGetLocalTimeMillis();
int height = rect.height;
wxWindow* win = GetPopupWindow();
wxWindow* popup = GetPopupControl()->GetControl(); wxWindow* popup = GetPopupControl()->GetControl();
const int delay = COMBOBOX_ANIMATION_DURATION; // Popup was hidden before it was fully shown?
const int resolution = 10; if ( IsPopupWindowState(Hidden) )
int h0 = popup->GetSize().y; {
stopTimer = true;
win->SetSize( rect.x, rect.y, rect.width, 0 ); }
win->Show(); else
for (;;)
{ {
wxLongLong t = ::wxGetLocalTimeMillis(); wxLongLong t = ::wxGetLocalTimeMillis();
int pos = (int) (t-tStart).GetLo(); const wxRect& rect = m_animRect;
if ( pos > delay ) wxWindow* win = GetPopupWindow();
break;
int h = (((pos*256)/delay)*height)/256; int pos = (int) (t-m_animStart).GetLo();
int y = (h0 - h); if ( pos < COMBOBOX_ANIMATION_DURATION )
{
int height = rect.height;
//int h0 = rect.height;
int h = (((pos*256)/COMBOBOX_ANIMATION_DURATION)*height)/256;
int y = (height - h);
if ( y < 0 ) if ( y < 0 )
y = 0; y = 0;
if ( flags & ShowAbove ) if ( m_animFlags & ShowAbove )
{ {
win->SetSize( rect.x, rect.y + h0 - h, rect.width, h ); win->SetSize( rect.x, rect.y + height - h, rect.width, h );
} }
else else
{ {
popup->Move( 0, -y ); popup->Move( 0, -y );
win->SetSize( rect.x, rect.y, rect.width, h ); win->SetSize( rect.x, rect.y, rect.width, h );
} }
}
wxMilliSleep( resolution ); else
wxYield(); {
stopTimer = true;
// Popup was hidden before it was fully shown? }
if ( IsPopupWindowState(Hidden) )
return true;
} }
if ( stopTimer )
{
popup->Move( 0, 0 ); popup->Move( 0, 0 );
m_animTimer.Stop();
DoShowPopup( m_animRect, m_animFlags );
}
} }
#else
wxUnusedVar(rect);
wxUnusedVar(flags);
#endif #endif
#if wxUSE_COMBOCTRL_POPUP_ANIMATION
bool wxComboCtrl::AnimateShow( const wxRect& rect, int flags )
{
if ( GetUserPreferencesMask() & wxMSW_DESKTOP_USERPREFERENCESMASK_COMBOBOXANIM )
{
m_animStart = ::wxGetLocalTimeMillis();
m_animRect = rect;
m_animFlags = flags;
wxWindow* win = GetPopupWindow();
win->SetSize( rect.x, rect.y, rect.width, 0 );
win->Show();
m_animTimer.SetOwner( this, wxID_ANY );
m_animTimer.Start( COMBOBOX_ANIMATION_RESOLUTION, wxTIMER_CONTINUOUS );
OnTimerEvent(*((wxTimerEvent*)NULL)); // Event is never used, so we can give NULL
return false;
}
return true; return true;
} }
#endif
wxCoord wxComboCtrl::GetNativeTextIndent() const wxCoord wxComboCtrl::GetNativeTextIndent() const
{ {