|
|
#include "priv.h"
#ifdef GADGET_ENABLE_GDIPLUS
using namespace DirectUI;
#include "Logon.h"
#include "Fx.h"
#include "Stub.h"
#include "Super.h"
const float flIGNORE = -10000.0f; const float flFadeOut = 0.50f;
#define ENABLE_USEVALUEFLOW 1
/***************************************************************************\
* * F2T * * F2T() converts from frames to time, using a constant. This allows easily * conversion from frames in Flash or Director to time used by DirectUser. * \***************************************************************************/
inline float F2T( IN int cFrames) { return cFrames / 30.0f; }
inline BYTE GetAlphaByte(float fl) { if (fl <= 0.0f) { return 0; } else if (fl >= 1.0f) { return 255; } else { return (BYTE) (fl * 255.0f); } }
inline float GetAlphaFloat(BYTE b) { return b * 255.0f; }
/***************************************************************************\
* * GetVPatternDelay * * GetVPatternDelay() computes the delay time for a standard "v-pattern" of * items that start from the middle and work outward. * \***************************************************************************/
inline float GetVPatternDelay( IN float flTimeLevel, IN EFadeDirection dir, IN int idxCur, IN int cItems) { float flBase = flTimeLevel * (float) (abs(cItems / 2 - idxCur));
switch (dir) { case fdIn: return flBase; case fdOut: return flTimeLevel * (abs(cItems / 2)) - flBase;
default: DUIAssertForce("Unknown direction"); return 0; } }
//------------------------------------------------------------------------------
HRESULT BuildLinearAlpha( OUT Sequence ** ppseq, OUT Interpolation ** ppip) { HRESULT hr = E_FAIL; LinearInterpolation * pip = NULL; #if ENABLE_USEVALUEFLOW
ValueFlow * pflow = NULL; #else
AlphaFlow * pflow = NULL; #endif
Sequence * pseq = NULL;
pip = LinearInterpolation::Build(); if (pip == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; } #if ENABLE_USEVALUEFLOW
ValueFlow::ValueFlowCI fci; ZeroMemory(&fci, sizeof(fci)); fci.cbSize = sizeof(fci);
pflow = ValueFlow::Build(&fci); #else
Flow::FlowCI fci; ZeroMemory(&fci, sizeof(fci)); fci.cbSize = sizeof(fci);
pflow = AlphaFlow::Build(&fci); #endif
if (pflow == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; } pseq = Sequence::Build(); if (pseq == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; } pseq->SetFlow(pflow); pflow->Release();
*ppseq = pseq; *ppip = pip; return S_OK;
ErrorExit: if (pseq != NULL) pseq->Release(); if (pflow != NULL) pflow->Release(); if (pip != NULL) pip->Release();
*ppseq = NULL; *ppip = NULL; return hr; }
/***************************************************************************\
* * class SyncVisible * * SyncVisible provides a mechansim to synchronize state between DirectUI and * DirectUser for the fading in / out effects. This allows an Element to be * marked as "visible" during the fade out and then become "not visible" when * the fade is done. * * This is important for several reasons, including not modifying the mouse * cursor when an Element becomes invisible. * \***************************************************************************/
class SyncVisible { public: static void Wait(Element * pel, EventGadget * pgeOperation, UINT nMsg) { SyncVisible * psv = new SyncVisible; if (psv != NULL) { psv->_pel = pel; if (SUCCEEDED(pgeOperation->AddHandlerD(nMsg, EVENT_DELEGATE(psv, EventProc)))) { // Successfully attached delegate
return; } delete psv; } // Unable to create a delegate, so set now
Sync(pel); }
static void Wait(Element * pel, EventGadget * pgeOperation, const GUID * pguid) { MSGID nMsg; if (FindGadgetMessages(&pguid, &nMsg, 1)) { SyncVisible * psv = new SyncVisible; if (psv != NULL) { psv->_nMsg = nMsg; psv->_pel = pel; psv->_pgeOperation = pgeOperation; if (SUCCEEDED(pgeOperation->AddHandlerD(nMsg, EVENT_DELEGATE(psv, EventProc)))) { // Successfully attached delegate
return; } delete psv; } } // Unable to create a delegate, so set now
Sync(pel); }
static void Sync(Element * pel) { HGADGET hgad = pel->GetDisplayNode(); bool fVisible = true; if (GetGadgetStyle(hgad) & GS_BUFFERED) { BUFFER_INFO bi; bi.cbSize = sizeof(bi); bi.nMask = GBIM_ALPHA; GetGadgetBufferInfo(hgad, &bi);
if (bi.bAlpha < 5) fVisible = false; } pel->SetVisible(fVisible); } protected: UINT CALLBACK EventProc(GMSG_EVENT * pmsg) { DUIAssert(GET_EVENT_DEST(pmsg) == GMF_EVENT, "Must be an event handler"); Animation::CompleteEvent * pmsgC = (Animation::CompleteEvent *) pmsg; if (pmsgC->fNormal) { Sync(_pel); } _pgeOperation->RemoveHandlerD(_nMsg, EVENT_DELEGATE(this, EventProc));
delete this; return GPR_NOTHANDLED; }
UINT _nMsg; Element * _pel; EventGadget * _pgeOperation; };
/***************************************************************************\
* * FxSetAlpha * * FxSetAlpha() provides a convenient mechanism to directly set the DirectUser * "alpha" state on a Visual Gadget without modifying the DirectUI "alpha" * property. * * NOTE: Eventually, we want to synchronize these, but for now, the DirectUI * "alpha" property doesn't work with DirectUser's new (improved!) Animations * infrastructure. * \***************************************************************************/
void FxSetAlpha( IN Element * pe, IN float flNewAlpha, IN float fSync) { #if ENABLE_USEVALUEFLOW
pe->SetAlpha(GetAlphaByte(flNewAlpha)); #else
HGADGET hgad = pe->GetDisplayNode(); if (flNewAlpha >= 0.97f) { // Turn off alpha
SetGadgetStyle(hgad, 0, GS_BUFFERED); } else { SetGadgetStyle(hgad, GS_BUFFERED | GS_OPAQUE, GS_BUFFERED | GS_OPAQUE); BUFFER_INFO bi; ZeroMemory(&bi, sizeof(bi)); bi.cbSize = sizeof(bi); bi.nMask = GBIM_ALPHA; bi.bAlpha = (BYTE) (flNewAlpha * 255.0f); SetGadgetBufferInfo(hgad, &bi); } #endif
if (fSync) { SyncVisible::Sync(pe); } }
/***************************************************************************\
* * FxPlayLinearAlpha * * FxPlayLinearAlpha() "plays" a linear, "simple" alpha-animation on a given * Element. * \***************************************************************************/
HRESULT FxPlayLinearAlpha( IN Element * pe, IN float flOldAlpha, IN float flNewAlpha, IN float flDuration, IN float flDelay) { HRESULT hr = E_FAIL; HGADGET hgad = pe->GetDisplayNode(); DUIAssert(hgad != NULL, "Must have valid Gadget"); Visual * pgvSubject = Visual::Cast(hgad);
pgvSubject->SetStyle(GS_OPAQUE, GS_OPAQUE);
//
// If an old alpha is specified, have it take place immediately. We can't
// use the Animation to do this because it will wait the delay.
//
if (flOldAlpha >= 0.0f) { FxSetAlpha(pe, flOldAlpha, false); }
LinearInterpolation * pip = NULL; #if ENABLE_USEVALUEFLOW
ValueFlow * pflow = NULL; ValueFlow::ValueKeyFrame kf; #else
AlphaFlow * pflow = NULL; AlphaFlow::AlphaKeyFrame kf; #endif
Animation * pani = NULL;
pip = LinearInterpolation::Build(); if (pip == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; } #if ENABLE_USEVALUEFLOW
ValueFlow::ValueFlowCI fci; ZeroMemory(&fci, sizeof(fci)); fci.cbSize = sizeof(fci); fci.pgvSubject = pgvSubject; fci.ppi = DirectUI::Element::AlphaProp; pflow = ValueFlow::Build(&fci); #else
Flow::FlowCI fci; ZeroMemory(&fci, sizeof(fci)); fci.cbSize = sizeof(fci); fci.pgvSubject = pgvSubject;
pflow = AlphaFlow::Build(&fci); #endif
if (pflow == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; } #if ENABLE_USEVALUEFLOW
kf.cbSize = sizeof(kf); kf.ppi = DirectUI::Element::AlphaProp; kf.rv.SetInt(GetAlphaByte(flNewAlpha)); #else
kf.cbSize = sizeof(kf);
kf.flAlpha = flNewAlpha; #endif
pflow->SetKeyFrame(Flow::tEnd, &kf);
Animation::AniCI aci; ZeroMemory(&aci, sizeof(aci)); aci.cbSize = sizeof(aci); aci.act.flDelay = flDelay; aci.act.flDuration = flDuration; aci.act.dwPause = (DWORD) -1; aci.pgvSubject = pgvSubject; aci.pipol = pip; aci.pgflow = pflow;
pani = Animation::Build(&aci); if (pani == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto ErrorExit; }
SyncVisible::Wait(pe, pani, &__uuidof(Animation::evComplete));
pani->Release(); pflow->Release(); pip->Release(); return S_OK;
ErrorExit: if (pani != NULL) pani->Release(); if (pflow != NULL) pflow->Release(); if (pip != NULL) pip->Release();
return hr; }
/***************************************************************************\
* * LogonFrame::FxFadeInAccounts * * FxFadeInAccounts() performs the first stage of animation: * - Fades in the user accounts * - Fades in the "options" in the bottom panel * \***************************************************************************/
HRESULT LogonFrame::FxStartup() { HRESULT hr = E_FAIL, hrT;
hrT = FxFadeAccounts(fdIn); if (FAILED(hrT)) hr = hrT;
//
// Fade in the "bottom pane" info
//
hrT = FxPlayLinearAlpha(_peOptions, 0.0f, 1.0f, F2T(16), F2T(32)); if (FAILED(hrT)) hr = hrT;
return hr; } /***************************************************************************\
* * LogonFrame::FxFadeAccounts * * FxFadeAccounts() fades the user accounts using a "v-delay" pattern * \***************************************************************************/
HRESULT LogonFrame::FxFadeAccounts( IN EFadeDirection dir, IN float flCommonDelay) { HRESULT hr = E_FAIL;
Element * peSelection = NULL; float flOldAlpha, flNewAlpha, flTimeLevel; switch (dir) { case fdIn: // Fading accounts in (startup)
flOldAlpha = 0.0f; flNewAlpha = 1.0f; flTimeLevel = F2T(5); break; case fdOut: // Fading accounts out (login)
flOldAlpha = flIGNORE; flNewAlpha = 0.0f; flTimeLevel = F2T(5); peSelection = _peAccountList->GetSelection(); break;
default: DUIAssertForce("Unknown direction"); return E_FAIL; }
Value* pvChildren; ElementList* peList = _peAccountList->GetChildren(&pvChildren); if (peList) { hr = S_OK; LogonAccount* peAccount; int cAccounts = peList->GetSize(); for (int i = 0; i < cAccounts; i++) { peAccount = (LogonAccount*)peList->GetItem(i);
//
// When fading out, we don't want to fade the selected item
//
if ((dir == fdOut) && (peAccount == peSelection)) { continue; }
float flDuration = F2T(15); float flDelay = GetVPatternDelay(flTimeLevel, dir, i, cAccounts) + flCommonDelay; HRESULT hrT = FxPlayLinearAlpha(peAccount, flOldAlpha, flNewAlpha, flDuration, flDelay); if (FAILED(hrT)) { hr = hrT; } } } pvChildren->Release(); return hr; }
/***************************************************************************\
* * LogonFrame::FxLogUserOn * * FxLogUserOn() performs the login stage of animation: * - Fade out Password field, "Type your password", "go" & "help" button * - WAIT * - Fade out scroll-bar * - WAIT * - Fade out other accounts (outside to selection), fade out "Click on your user..." * - WAIT * - Fade out of selection bitmap * - Scroll-up of Icon / Name * - Fade in "Logging in to Microsoft Windows" * - Fade out "Turn off..." and "To manage or change accounts..." * \***************************************************************************/
HRESULT LogonFrame::FxLogUserOn(LogonAccount * pla) { HRESULT hr = S_OK;
pla->FxLogUserOn(); FxFadeAccounts(fdOut);
// Fade out the "bottom pane" info
FxPlayLinearAlpha(_peOptions, flIGNORE, 0.0f, F2T(10), F2T(65));
GMA_ACTION act; ZeroMemory(&act, sizeof(act)); act.cbSize = sizeof(act); act.flDelay = F2T(50); act.pvData = this; act.pfnProc = OnLoginCenterStage;
CreateAction(&act);
return hr; }
/***************************************************************************\
* * LogonFrame::OnLoginCenterStage * * OnLoginCenterStage() is called after everything has faded away, and we * are in the final steps. * \***************************************************************************/
void CALLBACK LogonFrame::OnLoginCenterStage(GMA_ACTIONINFO * pmai) { if (!pmai->fFinished) { return; }
LogonFrame * plf = (LogonFrame *) pmai->pvData;
// Set keyfocus back to frame so it isn't pushed anywhere when controls are removed.
// This will also cause a remove of the password panel from the current account
plf->SetKeyFocus();
// Clear list of logon accounts except the one logging on
Value* pvChildren; ElementList* peList = plf->_peAccountList->GetChildren(&pvChildren); if (peList) { LogonAccount* peAccount; for (UINT i = 0; i < peList->GetSize(); i++) { peAccount = (LogonAccount*)peList->GetItem(i); if (peAccount->GetLogonState() == LS_Denied) { peAccount->SetLayoutPos(LP_None); } } } pvChildren->Release(); }
/***************************************************************************\
* * LogonAccount::FxLogUserOn * * FxLogUserOn() performs the login stage of animation for the selected * account. * - Fade out Password field, "Type your password", "go" & "help" button * \***************************************************************************/
HRESULT LogonAccount::FxLogUserOn() { HRESULT hr = S_OK; // Need to manually hide the edit control
HideEdit();
// Fade out the password panel
FxPlayLinearAlpha(_pePwdPanel, 1.0f, 0.0f, F2T(10));
return hr; }
/***************************************************************************\
* * LogonAccountList::FxMouseWithin * * FxMouseWithin() performs animations when the mouse enters or leaves the * account list. * \***************************************************************************/
HRESULT LogonAccountList::FxMouseWithin( IN EFadeDirection dir) { HRESULT hr = E_FAIL;
float flOldAlpha, flNewAlpha, flDuration; switch (dir) { case fdIn: // Entering list, so fade non-mouse-within accounts out
flOldAlpha = 1.00f; flNewAlpha = flFadeOut; flDuration = F2T(5); break; case fdOut: // Leaving list, so fade non-mouse-within accounts in
flOldAlpha = flIGNORE; flNewAlpha = 1.00f; flDuration = F2T(5); break;
default: DUIAssertForce("Unknown direction"); return E_FAIL; }
Value* pvChildren; ElementList* peList = GetChildren(&pvChildren); if (peList) { hr = S_OK; LogonAccount* peAccount; int cAccounts = peList->GetSize(); for (int i = 0; i < cAccounts; i++) { peAccount = (LogonAccount*)peList->GetItem(i); if (peAccount->GetLogonState() == LS_Pending) { //
// Animations to use before login
//
if (peAccount->GetMouseWithin()) { //
// Mouse is within this child. We need to special case this
// node since the list is notified of the MouseWithin property
// change AFTER the child itself is. If we didn't special case
// this, we would fade the MouseWithin child out with the rest
// of its siblings.
//
FxSetAlpha(peAccount, 1.0f, true); } else { //
// Mouse was not within this child, so apply the defaults
//
HRESULT hrT = FxPlayLinearAlpha(peAccount, flOldAlpha, flNewAlpha, flDuration); if (FAILED(hrT)) { hr = hrT; } } } } } pvChildren->Release();
return hr; }
/***************************************************************************\
* * LogonAccount::FxMouseWithin * * FxMouseWithin() performs animations when the mouse enters an individual * account item. * \***************************************************************************/
HRESULT LogonAccount::FxMouseWithin( IN EFadeDirection dir) { HRESULT hr = S_OK;
//
// Only apply fades when we are not actually logging in. This is important
// because we kick off an entire set of animations that could be overridden
// if we don't respect this. When we log in, we change each of the
// accounts from LS_Pending.
//
switch (dir) { case fdIn: // Entering account, so fade non-mouse-within accounts out
if (_fHasPwdPanel) ShowEdit();
if (GetLogonState() == LS_Pending) hr = FxPlayLinearAlpha(this, flIGNORE, 1.0f, F2T(3)); break; case fdOut: // Leaving account, so fade non-mouse-within accounts in
if (_fHasPwdPanel) HideEdit(); if (GetLogonState() == LS_Pending) hr = FxPlayLinearAlpha(this, flIGNORE, flFadeOut, F2T(10)); break;
default: DUIAssertForce("Unknown direction"); return E_FAIL; }
return hr; }
/***************************************************************************\
***************************************************************************** * * helper Compute() functions * ***************************************************************************** \***************************************************************************/
//------------------------------------------------------------------------------
inline int Round(float f) { return (int) (f + 0.5); }
//------------------------------------------------------------------------------
inline int Compute(Interpolation * pipol, float flProgress, int nStart, int nEnd) { return Round(pipol->Compute(flProgress, (float) nStart, (float) nEnd)); }
//------------------------------------------------------------------------------
inline bool Compute(Interpolation * pipol, float flProgress, bool fStart, bool fEnd) { return (pipol->Compute(flProgress, 0.0f, 1.0f) < 0.5f) ? fStart : fEnd; }
//------------------------------------------------------------------------------
POINT Compute(Interpolation * pipol, float flProgress, const POINT * pptStart, const POINT * pptEnd) { POINT pt; pt.x = Compute(pipol, flProgress, pptStart->x, pptEnd->x); pt.y = Compute(pipol, flProgress, pptStart->y, pptEnd->y); return pt; }
//------------------------------------------------------------------------------
SIZE Compute(Interpolation * pipol, float flProgress, const SIZE * psizeStart, const SIZE * psizeEnd) { SIZE size; size.cx = Compute(pipol, flProgress, psizeStart->cx, psizeEnd->cx); size.cy = Compute(pipol, flProgress, psizeStart->cy, psizeEnd->cy); return size; }
//------------------------------------------------------------------------------
RECT Compute(Interpolation * pipol, float flProgress, const RECT * prcStart, const RECT * prcEnd) { RECT rc; rc.left = Compute(pipol, flProgress, prcStart->left, prcEnd->left); rc.top = Compute(pipol, flProgress, prcStart->top, prcEnd->top); rc.right = Compute(pipol, flProgress, prcStart->right, prcEnd->right); rc.bottom = Compute(pipol, flProgress, prcStart->bottom, prcEnd->bottom); return rc; }
//------------------------------------------------------------------------------
COLORREF Compute(Interpolation * pipol, float flProgress, COLORREF crStart, COLORREF crEnd) { int nAlpha = Compute(pipol, flProgress, GetAValue(crStart), GetAValue(crEnd)); int nRed = Compute(pipol, flProgress, GetRValue(crStart), GetRValue(crEnd)); int nGreen = Compute(pipol, flProgress, GetGValue(crStart), GetGValue(crEnd)); int nBlue = Compute(pipol, flProgress, GetBValue(crStart), GetBValue(crEnd));
return ARGB(nAlpha, nRed, nGreen, nBlue); }
//------------------------------------------------------------------------------
DirectUI::Color Compute(Interpolation * pipol, float flProgress, const DirectUI::Color * pclrStart, const DirectUI::Color * pclrEnd) { DirectUI::Color clr; clr.dType = pclrStart->dType; clr.cr = Compute(pipol, flProgress, pclrStart->cr, pclrEnd->cr);
switch (clr.dType) { case COLORTYPE_TriHGradient: case COLORTYPE_TriVGradient: clr.cr3 = Compute(pipol, flProgress, pclrStart->cr, pclrEnd->cr); // Fall through
case COLORTYPE_HGradient: case COLORTYPE_VGradient: clr.cr2 = Compute(pipol, flProgress, pclrStart->cr, pclrEnd->cr); } return clr; }
//------------------------------------------------------------------------------
inline float Compute(Interpolation * pipol, float flProgress, float flStart, float flEnd) { return pipol->Compute(flProgress, flStart, flEnd); }
/***************************************************************************\
***************************************************************************** * * class DuiValueFlow * ***************************************************************************** \***************************************************************************/
class DuiValueFlow : public ValueFlowImpl<DuiValueFlow, SFlow> { // Construction
public: static HRESULT InitClass(); HRESULT PostBuild(DUser::Gadget::ConstructInfo * pci);
// Operations
public:
// Public API:
public: dapi PRID ApiGetPRID() { return s_prid; } dapi HRESULT ApiGetKeyFrame(Flow::ETime time, DUser::KeyFrame * pkf); dapi HRESULT ApiSetKeyFrame(Flow::ETime time, const DUser::KeyFrame * pkf);
dapi void ApiOnReset(Visual * pgvSubject); dapi void ApiOnAction(Visual * pgvSubject, Interpolation * pipol, float flProgress);
// Implementaton
protected: Element * GetElement(Visual * pgvSubject);
// Data
public: static PRID s_prid; protected: DirectUI::PropertyInfo* m_ppi; ValueFlow::RawValue m_rvStart; ValueFlow::RawValue m_rvEnd; };
/***************************************************************************\
***************************************************************************** * * class DuiValueFlow * ***************************************************************************** \***************************************************************************/
PRID DuiValueFlow::s_prid = 0; const GUID guidValueFlow = { 0xad9f0bd4, 0x1610, 0x47f3, { 0xba, 0xc9, 0x2c, 0x82, 0xe, 0x35, 0x2, 0xdf } }; // {AD9F0BD4-1610-47f3-BAC9-2C820E3502DF}
IMPLEMENT_GUTS_ValueFlow(DuiValueFlow, SFlow);
//------------------------------------------------------------------------------
HRESULT DuiValueFlow::InitClass() { s_prid = RegisterGadgetProperty(&guidValueFlow); return s_prid != 0 ? S_OK : (HRESULT) GetLastError(); }
//------------------------------------------------------------------------------
HRESULT DuiValueFlow::PostBuild( IN DUser::Gadget::ConstructInfo * pci) { //
// Get the information from the Gadget / Element
//
ValueFlow::ValueFlowCI * pDesc = static_cast<ValueFlow::ValueFlowCI *>(pci); DirectUI::Element * pel = GetElement(pDesc->pgvSubject);
if ((pDesc != NULL) && (pel != NULL)) { m_ppi = pDesc->ppi;
if (m_ppi != NULL) { DirectUI::Value * pvSrc = pel->GetValue(m_ppi, PI_Specified); DUIAssert(pvSrc != Value::pvUnset, "Value must be defined");
m_rvStart.SetValue(pvSrc); m_rvEnd = m_rvStart;
pvSrc->Release(); } }
#if DEBUG_TRACECREATION
TRACE("DuiValueFlow 0x%p on 0x%p initialized\n", pgvSubject, this); #endif // DEBUG_TRACECREATION
return S_OK; }
//------------------------------------------------------------------------------
HRESULT DuiValueFlow::ApiGetKeyFrame(Flow::ETime time, DUser::KeyFrame * pkf) { if (pkf->cbSize != sizeof(ValueFlow::ValueKeyFrame)) { return E_INVALIDARG; } ValueFlow::ValueKeyFrame * pkfV = static_cast<ValueFlow::ValueKeyFrame *>(pkf);
switch (time) { case Flow::tBegin: pkfV->ppi = m_ppi; pkfV->rv = m_rvStart; return S_OK;
case Flow::tEnd: pkfV->ppi = m_ppi; pkfV->rv = m_rvEnd; return S_OK;
default: return E_INVALIDARG; } }
//------------------------------------------------------------------------------
HRESULT DuiValueFlow::ApiSetKeyFrame(Flow::ETime time, const DUser::KeyFrame * pkf) { if (pkf->cbSize != sizeof(ValueFlow::ValueKeyFrame)) { return E_INVALIDARG; } const ValueFlow::ValueKeyFrame * pkfV = static_cast<const ValueFlow::ValueKeyFrame *>(pkf);
switch (time) { case Flow::tBegin: m_ppi = pkfV->ppi; m_rvStart = pkfV->rv; return S_OK;
case Flow::tEnd: m_ppi = pkfV->ppi; m_rvEnd = pkfV->rv; return S_OK;
default: return E_INVALIDARG; } }
//------------------------------------------------------------------------------
void DuiValueFlow::ApiOnReset(Visual * pgvSubject) { DirectUI::Element * pel; if ((m_ppi != NULL) && ((pel = GetElement(pgvSubject)) != NULL)) { DirectUI::Value * pvNew = NULL; if (SUCCEEDED(m_rvStart.GetValue(&pvNew))) { DUIAssert(pvNew != NULL, "Must have valid value"); pel->SetValue(m_ppi, PI_Local, pvNew); pvNew->Release(); } } }
//------------------------------------------------------------------------------
void DuiValueFlow::ApiOnAction(Visual * pgvSubject, Interpolation * pipol, float flProgress) { DirectUI::Element * pel; if ((m_ppi != NULL) && ((pel = GetElement(pgvSubject)) != NULL)) { if (m_rvStart.GetType() != m_rvEnd.GetType()) { DUITrace("DuiValueFlow: Start and end value types do not match\n"); } else { ValueFlow::RawValue rvCompute; BOOL fValid = TRUE; switch (m_rvStart.GetType()) { case DUIV_INT: rvCompute.SetInt(Compute(pipol, flProgress, m_rvStart.GetInt(), m_rvEnd.GetInt())); break; case DUIV_BOOL: rvCompute.SetBool(Compute(pipol, flProgress, m_rvStart.GetBool(), m_rvEnd.GetBool())); break; case DUIV_POINT: rvCompute.SetPoint(Compute(pipol, flProgress, m_rvStart.GetPoint(), m_rvEnd.GetPoint())); break; case DUIV_SIZE: rvCompute.SetSize(Compute(pipol, flProgress, m_rvStart.GetSize(), m_rvEnd.GetSize())); break; case DUIV_RECT: rvCompute.SetRect(Compute(pipol, flProgress, m_rvStart.GetRect(), m_rvEnd.GetRect())); break; case DUIV_COLOR: rvCompute.SetColor(Compute(pipol, flProgress, m_rvStart.GetColor(), m_rvEnd.GetColor())); break; default: ASSERT(0 && "Unknown value type"); fValid = FALSE; }
if (fValid) { DirectUI::Value * pvNew = NULL; if (SUCCEEDED(rvCompute.GetValue(&pvNew))) { DUIAssert(pvNew != NULL, "Must have valid value"); pel->SetValue(m_ppi, PI_Local, pvNew); pvNew->Release(); } } } } }
//------------------------------------------------------------------------------
Element * DuiValueFlow::GetElement(Visual * pgvSubject) { Element * pel = NULL; if (pgvSubject != NULL) { HGADGET hgadSubject = pgvSubject->GetHandle(); DUIAssert(hgadSubject != NULL, "Must have valid handle"); pel = DirectUI::ElementFromGadget(hgadSubject); DUIAssert(pel != NULL, "Must have a valid DirectUI Element"); }
return pel; }
//------------------------------------------------------------------------------
HRESULT FxInitGuts() { if (!DuiValueFlow::InitValueFlow()) { return E_OUTOFMEMORY; }
return S_OK; }
#endif // GADGET_ENABLE_GDIPLUS
|