1231 lines
53 KiB
C++
1231 lines
53 KiB
C++
/*
|
|
* Element
|
|
*/
|
|
|
|
#ifndef DUI_CORE_ELEMENT_H_INCLUDED
|
|
#define DUI_CORE_ELEMENT_H_INCLUDED
|
|
|
|
#pragma once
|
|
|
|
#include "duivalue.h"
|
|
#include "duievent.h"
|
|
#include "duisheet.h"
|
|
#include "duilayout.h"
|
|
|
|
struct IAccessible;
|
|
|
|
namespace DirectUI
|
|
{
|
|
|
|
#if DBG
|
|
extern UINT g_cGetDep;
|
|
extern UINT g_cGetVal;
|
|
extern UINT g_cOnPropChg;
|
|
#endif
|
|
|
|
class DuiAccessible;
|
|
|
|
// TODO: Switch DUI listeners to use DirectUser MessageHandlers
|
|
|
|
/*
|
|
* Element Properties
|
|
*
|
|
* Element provides default behavior for Get/SetValue based on the flags used in PropertyInfo.
|
|
* The Flags also define what indicies are available during property operations.
|
|
*
|
|
* Get/SetValue cannot be overridden. Rather, a default implemention is supplied for GetValue's
|
|
* on all properties. By default, Get's on the Specified and Computed index are handled by a
|
|
* built-in Value Expression (VE) while Get's on Local query a local store (see below for exact
|
|
* default behavior). However, various system properties override this default behavior with
|
|
* different unchangable Value Expressions (implicit VEs) in the Local and Computed indicies.
|
|
*
|
|
* End users will use Normal properties and may occasionally use LocalOnly properties. Although
|
|
* available to derived classes, TriLevel property functionaly is only useful by the system.
|
|
*
|
|
* All property value must be available generically through GetValue.
|
|
*
|
|
* Flags supported (default behavior):
|
|
*
|
|
* "LocalOnly"
|
|
* Indicies: Local
|
|
* Get: Retrieve local value from Element. If none is set, 'Unset' returned.
|
|
* Set: Stores value locally on the Element.
|
|
* Dependents: None
|
|
* Modifiers: Readonly: Disallow Set
|
|
*
|
|
* "Normal"
|
|
* Indicies: Local, Specified (implicit VE)
|
|
* Get: Local: Retrieve local value from Element. If none is set, 'Unset' returned.
|
|
* Specified: Does a Get on the Local value. If 'Unset', return Property Sheet value
|
|
* if Cascade modifier is set. If 'Unset', return parent's value if Inherit
|
|
* modifier is set. If 'Unset' return property's Default value.
|
|
* Automatically evaulate value expressions before return.
|
|
* Set: Local: Stores value locally on the Element.
|
|
* Specified: Unsupported.
|
|
* Dependents: Specified is dependent on Local.
|
|
* Modifiers: Readonly: Disallow Set for Local.
|
|
* Cascade: Used with Specified Get (see Get description).
|
|
* Inherit: Used with Specified Get (see Get description).
|
|
*
|
|
* "TriLevel"
|
|
* Indicies: Local, Specified (implicit VE), Computed (implicit VE)
|
|
* Get: Local: Retrieve local value from Element. If none is set, 'Unset' returned.
|
|
* Specified: Does a Get on the Local value. If 'Unset', return Property Sheet value
|
|
* if Cascade modifier is set. If 'Unset', return parent's value if Inherit
|
|
* modifier is set. If 'Unset' return property's Default value.
|
|
* Automatically evaulate value expressions before return.
|
|
* Computed: Does a get of the Specified value.
|
|
* Set: Local: Stores value locally on the Element.
|
|
* Specified: Unsupported.
|
|
* Computed: Unsupported.
|
|
* Dependents: Computed is dependent on Specified. Specified is dependent on Local.
|
|
* Modifiers: Readonly: Disallow Set for Local.
|
|
* Cascade: Used with Specified Get (see Get description).
|
|
* Inherit: Used with Specified Get (see Get description).
|
|
*
|
|
* SetValue must always be used by derived classes. However, SetValue is sometimes bypassed and
|
|
* Pre/PostSourceChange is called directly in the case of LocalOnly properties that are ReadOnly
|
|
* and are cached directly on the Element (optimization). All other ReadOnly sets use
|
|
* _SetValue since generic storage (of Values) is used. SetValue is used in all other cases.
|
|
*
|
|
* For ReadOnly values, if storing the value is cheap (i.e. bools) and interit and style sheet
|
|
* functionality is not required, it is best to not use generic storage (_SetValue). Rather,
|
|
* write the value directly and call Pre/PostSourceChange directly ("LocalOnly property).
|
|
* Otherwise, if a ReadOnly value requires inheritance and/or sheet lookups, or the value is
|
|
* seldom different than a default value, use _SetValue (generic storage, "Normal" property).
|
|
*
|
|
* For Normal/ReadOnly, use SetValue, For LocalOnly/ReadOnly, use _SetValue,
|
|
* For internal LocalOnly/ReadOnly, set and store manually (no generic storage)
|
|
*
|
|
* All property values must be settable generically via SetValue except ReadOnly properties.
|
|
* Any "LocalOnly" property that doesn't use generic storage must initialize their members
|
|
* at construction to the property's default value. "Normal" properties will choose the
|
|
* default value automatically when queried. All derived classes (external) will use "Normal"
|
|
* properties.
|
|
*
|
|
* SetValue only accepts the PI_Local index. ReadOnly sets do not fire OnPropertyChanging.
|
|
* All value sets must result in a PreSourceChange, followed by the store update (in which GetValue
|
|
* will retrieve values from), followed by a PostSourceChange. OnPropertyChange and old value
|
|
* compare are optional.
|
|
*
|
|
* Set values are updated immediately (i.e. an immediate GetValue after will produce the updated
|
|
* result). Location and Extent are updated after the defer cycle ends (EndDefer, SetValues are internal).
|
|
*/
|
|
|
|
/*
|
|
* Element Multithreading
|
|
*
|
|
* Elements have context affinity. A single thread is allowed per context. This thread
|
|
* is owned by the context. Only that thread may be allowed to access objects in its
|
|
* context. This requirement is not enforced in this library. The caller application
|
|
* must ensure access to objects in a context happens via the owned thread.
|
|
*
|
|
* A Proxy class is provided to invoke methods on objects from an out-of-context thread.
|
|
*
|
|
* The library supports multiple instances in the same process. This would happen by
|
|
* linking the library to multiple process modules. The only restriction is a thread
|
|
* must access a set of objects consistantly with the same instance of the library code.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Error Reporting
|
|
*
|
|
* Conditions that would affect the stability of DirectUI are reported. Some conditions are
|
|
* only reported in Debug builds, and other in both Release and Debug
|
|
*
|
|
* Debug time reporting:
|
|
* Erroneous states are reported in Debug (checked) builds. An erroneous state arises
|
|
* when a programming error is found or when invalid arguments are passed to a method.
|
|
* Erroneous states cause raising of asserts
|
|
*
|
|
* Release time reporting:
|
|
* Abnormal states (such as out of memory or resources) that result in a serious condition
|
|
* (crash or very irregular state) are reported via HRESULTs. Any DUI API that can fail due to
|
|
* these types of abnormal states returns an HRESULT. If a method fails, it will recover.
|
|
* Some methods (such as object creation methods) will recover by freeing any memory or
|
|
* resources allocated within that method (resulting of a complete undo of all the work it
|
|
* accomplished up to the point of the failure). Other methods (such as rendering and the defer
|
|
* cycle) will do as much work as possible. Upon a failure, they will return an 'incomplete'
|
|
* error, however, they would have not completed. Failures do not result in crashes or irregular
|
|
* state. Failures are ignored in callbacks
|
|
*/
|
|
|
|
typedef int (__cdecl *CompareCallback)(const void*, const void*);
|
|
|
|
// Property indicies
|
|
#define PI_Local 1
|
|
#define PI_Specified 2
|
|
#define PI_Computed 3
|
|
|
|
// Property flags
|
|
#define PF_LocalOnly 0x01
|
|
#define PF_Normal 0x02
|
|
#define PF_TriLevel 0x03
|
|
#define PF_Cascade 0x04
|
|
#define PF_Inherit 0x08
|
|
#define PF_ReadOnly 0x10
|
|
|
|
#define PF_TypeBits 0x03 // Map out for LocalOnly, Normal, or Trilevel
|
|
|
|
// For use in OnPropertyChanged, mask out non-retrieval index property changes
|
|
#define IsProp(p) ((p##Prop == ppi) && ((ppi->fFlags&PF_TypeBits) == iIndex))
|
|
#define RetIdx(p) (p->fFlags&PF_TypeBits)
|
|
|
|
// Property groups
|
|
#define PG_AffectsDesiredSize 0x00000001 // Normal priority
|
|
#define PG_AffectsParentDesiredSize 0x00000002
|
|
#define PG_AffectsLayout 0x00000004
|
|
#define PG_AffectsParentLayout 0x00000008
|
|
#define PG_AffectsBounds 0x00010000 // Low priority
|
|
#define PG_AffectsDisplay 0x00020000
|
|
|
|
#define PG_NormalPriMask 0x0000FFFF
|
|
#define PG_LowPriMask 0xFFFF0000
|
|
|
|
// Layout cycle queue modes
|
|
#define LC_Pass 0
|
|
#define LC_Normal 1
|
|
#define LC_Optimize 2
|
|
|
|
// todo: get these from accessibility
|
|
#define GA_NOTHANDLED ((Element*) -1)
|
|
|
|
// to be internal
|
|
#define NAV_LOGICAL 0x00000001 // unset == directional
|
|
#define NAV_FORWARD 0x00000002 // unset == backward
|
|
#define NAV_VERTICAL 0x00000004 // unset == horizontal
|
|
#define NAV_RELATIVE 0x00000008 // unset == absolute
|
|
|
|
// to be exposed
|
|
#define NAV_FIRST (NAV_FORWARD | NAV_LOGICAL)
|
|
#define NAV_LAST (NAV_LOGICAL)
|
|
#define NAV_UP (NAV_RELATIVE | NAV_VERTICAL)
|
|
#define NAV_DOWN (NAV_RELATIVE | NAV_VERTICAL | NAV_FORWARD)
|
|
#define NAV_LEFT (NAV_RELATIVE)
|
|
#define NAV_RIGHT (NAV_RELATIVE | NAV_FORWARD)
|
|
#define NAV_NEXT (NAV_RELATIVE | NAV_FORWARD | NAV_LOGICAL)
|
|
#define NAV_PREV (NAV_RELATIVE | NAV_LOGICAL)
|
|
|
|
// to be exposed
|
|
#define DIRECTION_LTR 0
|
|
#define DIRECTION_RTL 1
|
|
|
|
// Asynchronous destroy message (must be async to ensure outstanding
|
|
// defer pointers are cleared)
|
|
#define GM_DUIASYNCDESTROY GM_USER - 1
|
|
|
|
|
|
////////////////////////////////////////////////////////
|
|
// PropertyInfo
|
|
|
|
struct IClassInfo;
|
|
|
|
struct EnumMap
|
|
{
|
|
LPCWSTR pszEnum;
|
|
int nEnum;
|
|
};
|
|
|
|
struct PropertyInfo
|
|
{
|
|
WCHAR szName[81];
|
|
int fFlags;
|
|
int fGroups;
|
|
int* pValidValues;
|
|
EnumMap* pEnumMaps;
|
|
Value* pvDefault;
|
|
int _iIndex; // Class-wide unique id (zero-based consecutive, set by ClassInfo)
|
|
int _iGlobalIndex; // Process-wide unique id (zero-based consecutive, set by ClassInfo (manually set for Element))
|
|
IClassInfo* _pciOwner; // Class that this property is defined on (direct owner, not inherited-by)
|
|
};
|
|
|
|
class Element;
|
|
|
|
////////////////////////////////////////////////////////
|
|
// UpdateCache
|
|
|
|
struct UpdateCache
|
|
{
|
|
Element* peSrc;
|
|
PropertyInfo* ppiSrc;
|
|
int iIndexSrc;
|
|
Value* pvOldSrc;
|
|
Value* pvNewSrc;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Dependencies
|
|
|
|
struct Dependency
|
|
{
|
|
Element* pe;
|
|
PropertyInfo* ppi;
|
|
int iIndex;
|
|
};
|
|
|
|
// Track dependency records in PC list
|
|
struct DepRecs
|
|
{
|
|
int iDepPos;
|
|
int cDepCnt;
|
|
};
|
|
|
|
struct NavReference
|
|
{
|
|
void Init(Element* pe, RECT* prc);
|
|
|
|
UINT cbSize;
|
|
Element* pe;
|
|
RECT* prc;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Class information interface
|
|
|
|
// Used so that a class will not be linked out if a class is not referred to
|
|
// (and is only referred by the parser)
|
|
#define UsingDUIClass(classn) static IClassInfo* _DUI__pCI##classn = ##classn::Class
|
|
|
|
struct IClassInfo
|
|
{
|
|
virtual HRESULT CreateInstance(OUT Element** ppElement) = 0;
|
|
virtual PropertyInfo* EnumPropertyInfo(UINT nEnum) = 0; // Includes base classes
|
|
virtual UINT GetPICount() = 0; // Includes base classes
|
|
virtual UINT GetGlobalIndex() = 0;
|
|
virtual IClassInfo* GetBaseClass() = 0;
|
|
virtual LPCWSTR GetName() = 0;
|
|
virtual bool IsValidProperty(PropertyInfo* ppi) = 0;
|
|
virtual bool IsSubclassOf(IClassInfo* pci) = 0;
|
|
virtual void Destroy() = 0;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Element Listener interface
|
|
struct IElementListener
|
|
{
|
|
virtual void OnListenerAttach(Element* peFrom) = 0;
|
|
virtual void OnListenerDetach(Element* peFrom) = 0;
|
|
virtual bool OnListenedPropertyChanging(Element* peFrom, PropertyInfo* ppi, int iIndex, Value* pvOld, Value* pvNew) = 0;
|
|
virtual void OnListenedPropertyChanged(Element* peFrom, PropertyInfo* ppi, int iIndex, Value* pvOld, Value* pvNew) = 0;
|
|
virtual void OnListenedInput(Element* peFrom, InputEvent* pInput) = 0;
|
|
virtual void OnListenedEvent(Element* peFrom, Event* pEvent) = 0;
|
|
};
|
|
|
|
#if DBG
|
|
////////////////////////////////////////////////////////
|
|
// Track "owner" context of this instance to validation that threads that don't
|
|
// belong to the context don't access the object.
|
|
//
|
|
// For side-by-side library support, also store the TLS slot of the instance
|
|
// of the library in the process that created this object. This will ensure the
|
|
// thread is using the correct library instance to access the object.
|
|
|
|
struct Owner
|
|
{
|
|
HDCONTEXT hCtx;
|
|
DWORD dwTLSSlot;
|
|
};
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Element
|
|
|
|
typedef DynamicArray<Element*> ElementList;
|
|
class DeferCycle;
|
|
struct PCRecord;
|
|
|
|
#define EC_NoGadgetCreate 0x1 // Do not create DisplayNode, must be created within constructor override
|
|
#define EC_SelfLayout 0x2 // Element will lay out children (via self layout callbacks)
|
|
|
|
class Element
|
|
{
|
|
public:
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Construction / destruction
|
|
|
|
static HRESULT Create(UINT nCreate, OUT Element** ppe);
|
|
HRESULT Destroy(bool fDelayed = true); // Destroy self
|
|
HRESULT DestroyAll(); // Destroy all children
|
|
|
|
Element() { }
|
|
virtual ~Element();
|
|
HRESULT Initialize(UINT nCreate);
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Properties (impl in property.cpp)
|
|
|
|
// Accessors
|
|
Value* GetValue(PropertyInfo* ppi, int iIndex, UpdateCache* puc = NULL);
|
|
HRESULT SetValue(PropertyInfo* ppi, int iIndex, Value* pv);
|
|
|
|
// Additional property methods
|
|
HRESULT RemoveLocalValue(PropertyInfo* ppi);
|
|
|
|
// Deferring
|
|
static void StartDefer();
|
|
static void EndDefer();
|
|
|
|
// Checks
|
|
inline bool IsValidAccessor(PropertyInfo* ppi, int iIndex, bool bSetting);
|
|
static bool IsValidValue(PropertyInfo* ppi, Value* pv);
|
|
bool IsRTL() { return (GetDirection() == DIRECTION_RTL);}
|
|
|
|
// System event callbacks
|
|
virtual bool OnPropertyChanging(PropertyInfo* ppi, int iIndex, Value* pvOld, Value* pvNew); // Direct
|
|
virtual void OnPropertyChanged(PropertyInfo* ppi, int iIndex, Value* pvOld, Value* pvNew); // Direct
|
|
virtual void OnGroupChanged(int fGroups, bool bLowPri); // Direct
|
|
virtual void OnInput(InputEvent* pInput); // Direct and bubbled
|
|
virtual void OnKeyFocusMoved(Element* peFrom, Element* peTo); // Direct and bubbled
|
|
virtual void OnMouseFocusMoved(Element* peFrom, Element* peTo); // Direct and bubbled
|
|
virtual void OnDestroy(); // Direct
|
|
// ContainerCleanup: OnLoadedFromResource(dictionary)
|
|
|
|
// Generic eventing and callback (pointer is only guaranteed good for the lifetime of the call)
|
|
void FireEvent(Event* pEvent, bool fFull = true);
|
|
virtual void OnEvent(Event* pEvent);
|
|
|
|
// Rendering callbacks
|
|
virtual void Paint(HDC hDC, const RECT* prcBounds, const RECT* prcInvalid, RECT* prcSkipBorder, RECT* prcSkipContent);
|
|
#ifdef GADGET_ENABLE_GDIPLUS
|
|
virtual void Paint(Gdiplus::Graphics* pgpgr, const Gdiplus::RectF* prcBounds, const Gdiplus::RectF* prcInvalid, Gdiplus::RectF* prSkipBorder, Gdiplus::RectF* prSkipContent);
|
|
#endif
|
|
virtual SIZE GetContentSize(int dConstW, int dConstH, Surface* psrf);
|
|
float GetTreeAlphaLevel();
|
|
|
|
// Hierarchy
|
|
HRESULT Add(Element* pe);
|
|
virtual HRESULT Add(Element** ppe, UINT cCount);
|
|
HRESULT Insert(Element* pe, UINT iInsertIdx);
|
|
virtual HRESULT Insert(Element** ppe, UINT cCount, UINT iInsertIdx);
|
|
|
|
HRESULT Add(Element* pe, CompareCallback lpfnCompare);
|
|
HRESULT SortChildren(CompareCallback lpfnCompare);
|
|
|
|
HRESULT Remove(Element* peFrom);
|
|
HRESULT RemoveAll();
|
|
virtual HRESULT Remove(Element** ppe, UINT cCount);
|
|
|
|
// Mapping and navigation
|
|
Element* FindDescendent(ATOM atomID);
|
|
void MapElementPoint(Element* peFrom, const POINT* pptFrom, POINT* pptTo);
|
|
Element* GetImmediateChild(Element* peFrom);
|
|
bool IsDescendent(Element* pe);
|
|
virtual Element* GetAdjacent(Element* peFrom, int iNavDir, NavReference const* pnr, bool bKeyable);
|
|
Element* GetKeyWithinChild();
|
|
Element* GetMouseWithinChild();
|
|
bool EnsureVisible();
|
|
bool EnsureVisible(UINT uChild);
|
|
virtual bool EnsureVisible(int x, int y, int cx, int cy);
|
|
virtual void SetKeyFocus();
|
|
|
|
// Element Listeners
|
|
HRESULT AddListener(IElementListener* pel);
|
|
void RemoveListener(IElementListener* pel);
|
|
|
|
// Effects, animate display node to match current Element state
|
|
void InvokeAnimation(int dAni, UINT nTypeMask);
|
|
void InvokeAnimation(UINT nTypes, UINT nInterpol, float flDuration, float flDelay, bool fPushToChildren = false);
|
|
void StopAnimation(UINT nTypes);
|
|
|
|
// Display node callback extension
|
|
virtual UINT MessageCallback(GMSG* pGMsg);
|
|
|
|
// Internal defer cycle and Layout-only callbacks
|
|
SIZE _UpdateDesiredSize(int dConstW, int dConstH, Surface* psrf);
|
|
void _UpdateLayoutPosition(int dX, int dY);
|
|
void _UpdateLayoutSize(int dWidth, int dHeight);
|
|
|
|
// Use in DoLayout on children where one or more properties will be changed which will
|
|
// cause a Layout GPC to be queued. This will cancel the layout GPCs and force the child
|
|
// to be included in the current layout cycle
|
|
void _StartOptimizedLayoutQ() { DUIAssertNoMsg(_fBit.fNeedsLayout != LC_Optimize); _fBit.fNeedsLayout = LC_Optimize; }
|
|
void _EndOptimizedLayoutQ() { _fBit.fNeedsLayout = LC_Normal; }
|
|
|
|
// Internal defer cycle and PropertySheet-only callbacks
|
|
static void _AddDependency(Element* pe, PropertyInfo* ppi, int iIndex, DepRecs* pdr, DeferCycle* pdc, HRESULT* phr);
|
|
|
|
// Internal DirectUser interop
|
|
static HRESULT CALLBACK _DisplayNodeCallback(HGADGET hgadCur, void * pvCur, EventMsg * pGMsg);
|
|
|
|
// Internal IUnknown interface impl
|
|
long __stdcall QueryInterface(REFIID iid, void** pvObj) { UNREFERENCED_PARAMETER(iid); UNREFERENCED_PARAMETER(pvObj); return E_NOTIMPL; }
|
|
ULONG __stdcall AddRef() { return 1; }
|
|
ULONG __stdcall Release() { return 1; }
|
|
|
|
private:
|
|
|
|
// Value update
|
|
HRESULT _GetDependencies(PropertyInfo* ppi, int iIndex, DepRecs* pdr, int iPCSrcRoot, DeferCycle* pdc);
|
|
static void _VoidPCNotifyTree(int iPCPos, DeferCycle* pdc);
|
|
|
|
// Defer cycle
|
|
static void _FlushDS(Element* pe, DeferCycle* pdc);
|
|
static void _FlushLayout(Element* pe, DeferCycle* pdc);
|
|
|
|
// Value Update
|
|
HRESULT _PreSourceChange(PropertyInfo* ppi, int iIndex, Value* pvOld, Value* pvNew);
|
|
HRESULT _PostSourceChange();
|
|
|
|
protected:
|
|
|
|
// EC_SelfLayout flag at creation activates these methods. No external layouts are used for layout,
|
|
// rather, Element is responsible for layout (use when layout is specific and hierarchy is known)
|
|
virtual void _SelfLayoutDoLayout(int dWidth, int dHeight);
|
|
virtual SIZE _SelfLayoutUpdateDesiredSize(int dConstW, int dConstH, Surface* psrf);
|
|
|
|
// Internal Set and Remove
|
|
HRESULT _SetValue(PropertyInfo* ppi, int iIndex, Value* pv, bool fInternalCall = true);
|
|
HRESULT _RemoveLocalValue(PropertyInfo* ppi, bool fInternalCall = true);
|
|
|
|
// Natvie hosting system event callbacks and retrieval
|
|
virtual void OnHosted(Element* peNewHost); // Direct
|
|
virtual void OnUnHosted(Element* peOldHost); // Direct
|
|
void MarkHosted() { _fBit.bHosted = true; }
|
|
|
|
public:
|
|
|
|
inline void DoubleBuffered(bool fEnabled = true)
|
|
{
|
|
if (_hgDisplayNode)
|
|
SetGadgetStyle(_hgDisplayNode, (fEnabled) ? GS_BUFFERED : 0, GS_BUFFERED);
|
|
}
|
|
|
|
inline BOOL IsRoot()
|
|
{
|
|
return IsHosted() && (GetParent() == NULL);
|
|
}
|
|
|
|
// Return if being hosted by a native root
|
|
inline Element* GetRoot()
|
|
{
|
|
if (!IsHosted())
|
|
return NULL;
|
|
|
|
Element * peCur = this;
|
|
while (peCur->GetParent() != NULL)
|
|
{
|
|
peCur = peCur->GetParent();
|
|
}
|
|
|
|
return peCur;
|
|
}
|
|
|
|
static BTreeLookup<IClassInfo*>* pciMap;
|
|
|
|
// Event types
|
|
static UID KeyboardNavigate;
|
|
|
|
// Property definitions
|
|
static PropertyInfo* ParentProp; // 00
|
|
static PropertyInfo* ChildrenProp; // 01
|
|
static PropertyInfo* VisibleProp; // 02
|
|
static PropertyInfo* WidthProp; // 03
|
|
static PropertyInfo* HeightProp; // 04
|
|
static PropertyInfo* LocationProp; // 05
|
|
static PropertyInfo* ExtentProp; // 06
|
|
static PropertyInfo* XProp; // 07
|
|
static PropertyInfo* YProp; // 08
|
|
static PropertyInfo* PosInLayoutProp; // 09
|
|
static PropertyInfo* SizeInLayoutProp; // 10
|
|
static PropertyInfo* DesiredSizeProp; // 11
|
|
static PropertyInfo* LastDSConstProp; // 12
|
|
static PropertyInfo* LayoutProp; // 13
|
|
static PropertyInfo* LayoutPosProp; // 14
|
|
static PropertyInfo* BorderThicknessProp; // 15
|
|
static PropertyInfo* BorderStyleProp; // 16
|
|
static PropertyInfo* BorderColorProp; // 17
|
|
static PropertyInfo* PaddingProp; // 18
|
|
static PropertyInfo* MarginProp; // 19
|
|
static PropertyInfo* ForegroundProp; // 20
|
|
static PropertyInfo* BackgroundProp; // 21
|
|
static PropertyInfo* ContentProp; // 22
|
|
static PropertyInfo* FontFaceProp; // 23
|
|
static PropertyInfo* FontSizeProp; // 24
|
|
static PropertyInfo* FontWeightProp; // 25
|
|
static PropertyInfo* FontStyleProp; // 26
|
|
static PropertyInfo* ActiveProp; // 27
|
|
static PropertyInfo* ContentAlignProp; // 28
|
|
static PropertyInfo* KeyFocusedProp; // 29
|
|
static PropertyInfo* KeyWithinProp; // 30
|
|
static PropertyInfo* MouseFocusedProp; // 31
|
|
static PropertyInfo* MouseWithinProp; // 32
|
|
static PropertyInfo* ClassProp; // 33
|
|
static PropertyInfo* IDProp; // 34
|
|
static PropertyInfo* SheetProp; // 35
|
|
static PropertyInfo* SelectedProp; // 36
|
|
static PropertyInfo* AlphaProp; // 37
|
|
static PropertyInfo* AnimationProp; // 38
|
|
static PropertyInfo* CursorProp; // 39
|
|
static PropertyInfo* DirectionProp; // 40
|
|
static PropertyInfo* AccessibleProp; // 41
|
|
static PropertyInfo* AccRoleProp; // 42
|
|
static PropertyInfo* AccStateProp; // 43
|
|
static PropertyInfo* AccNameProp; // 44
|
|
static PropertyInfo* AccDescProp; // 45
|
|
static PropertyInfo* AccValueProp; // 46
|
|
static PropertyInfo* AccDefActionProp; // 47
|
|
static PropertyInfo* ShortcutProp; // 48
|
|
static PropertyInfo* EnabledProp; // 49
|
|
|
|
#if DBG
|
|
Owner owner;
|
|
#endif
|
|
|
|
protected:
|
|
|
|
HGADGET _hgDisplayNode;
|
|
|
|
private:
|
|
|
|
int _iIndex;
|
|
|
|
BTreeLookup<Value*>* _pvmLocal;
|
|
|
|
int _iGCSlot;
|
|
int _iGCLPSlot;
|
|
int _iPCTail;
|
|
|
|
IElementListener** _ppel;
|
|
|
|
// All "cached" values are caching resulting values from the Specified and Computed IVEs.
|
|
// All local (loc) values are for ReadOnly properties. These values are updated directly
|
|
// since it is not required to go generically through SetValue because they are ReadOnly.
|
|
// They are used often or are cheap to store (bools), so they do not use generic
|
|
// storage (via _SetValue).
|
|
|
|
// Cached and local values
|
|
Element* _peLocParent; // Parent local
|
|
POINT _ptLocPosInLayt; // Position in layout local
|
|
SIZE _sizeLocSizeInLayt; // Size in layout local
|
|
SIZE _sizeLocLastDSConst; // Last desired size constraint local
|
|
SIZE _sizeLocDesiredSize; // Desired size local
|
|
|
|
int _dSpecLayoutPos; // Cached layout position
|
|
Value* _pvSpecSheet; // Cached property sheet specified (Value cached due to destruction)
|
|
ATOM _atomSpecID; // Cached id specified
|
|
int _dSpecAlpha; // Cached alpha value
|
|
|
|
struct _BitMap
|
|
{
|
|
// Local values
|
|
bool bLocKeyWithin : 1; // 0 Keyboard within local
|
|
bool bLocMouseWithin : 1; // 1 Mouse within local
|
|
|
|
// Direct VE cache
|
|
bool bCmpVisible : 1; // 2 Cached visible computed
|
|
bool bSpecVisible : 1; // 3 Cached visible specified
|
|
UINT fSpecActive : 2; // 4 Cached active state specified
|
|
bool bSpecSelected : 1; // 5 Cached selected state specified
|
|
bool bSpecKeyFocused : 1; // 6 Cached keyboard focused state specified
|
|
bool bSpecMouseFocused : 1; // 7 Cached mouse focused state specified
|
|
UINT nSpecDirection : 1; // 8 Cached direction specified
|
|
bool bSpecAccessible : 1; // 9 Cached accessible specified
|
|
bool bSpecEnabled : 1; // 10 Cached enabled specified
|
|
|
|
// Indirect VE cache (cache if default value)
|
|
bool bHasChildren : 1; // 11 Cached children state (likely to be default value, no full cache)
|
|
bool bHasLayout : 1; // 12 Cached layout state (likely to be default value, no full cache)
|
|
bool bHasBorder : 1; // 13 Cached border state (likely to be default value, no full cache)
|
|
bool bHasPadding : 1; // 14 Cached padding state (likely to be default value, no full cache)
|
|
bool bHasMargin : 1; // 15 Cached margin state (likely to be default value, no full cache)
|
|
bool bHasContent : 1; // 16 Cached content state (likely to be default value, no full cache)
|
|
bool bDefaultCAlign : 1; // 17 Cached content align state (likely to be default value, no full cache)
|
|
bool bWordWrap : 1; // 18 Cached content align state (likely to be default value, no full cache)
|
|
bool bHasAnimation : 1; // 19 Cached animation state (likely to be default value, no full cache)
|
|
bool bDefaultCursor : 1; // 20 Cached cursor state (likely to be default value, no full cache)
|
|
bool bDefaultBorderColor : 1; // 21 Cached border color state (likely to be default value, no full cache)
|
|
bool bDefaultForeground : 1; // 22 Cached foreground state (likely to be default value, no full cache)
|
|
bool bDefaultFontWeight : 1; // 23 Cached font weight state (likely to be default value, no full cache)
|
|
bool bDefaultFontStyle : 1; // 24 Cached font style state (likely to be default value, no full cache)
|
|
|
|
// Layout and UDS flags
|
|
bool bSelfLayout : 1; // 25 Element is laying out itself (callbacks active, external layout set is undefined)
|
|
bool bNeedsDSUpdate : 1; // 26
|
|
UINT fNeedsLayout : 2; // 27
|
|
|
|
// Lifetime flags
|
|
bool bDestroyed : 1; // 28
|
|
|
|
// Hosting flags
|
|
bool bHosted : 1; // 29 Initially set by host Element directly
|
|
|
|
} _fBit;
|
|
|
|
public:
|
|
|
|
// Element DisplayNode and Index access
|
|
HGADGET GetDisplayNode() { return _hgDisplayNode; }
|
|
int GetIndex() { return _iIndex; }
|
|
bool IsDestroyed() { return _fBit.bDestroyed; }
|
|
bool IsHosted() { return _fBit.bHosted; }
|
|
|
|
// Cache state for faster property value lookup
|
|
bool IsSelfLayout() { return _fBit.bSelfLayout; }
|
|
bool HasChildren() { return _fBit.bHasChildren; } // Quick check before doing lookup
|
|
bool HasLayout() { return _fBit.bHasLayout; } // Quick check before doing lookup
|
|
bool HasBorder() { return _fBit.bHasBorder; } // Quick check before doing lookup
|
|
bool HasPadding() { return _fBit.bHasPadding; } // Quick check before doing lookup
|
|
bool HasMargin() { return _fBit.bHasMargin; } // Quick check before doing lookup
|
|
bool HasContent() { return _fBit.bHasContent; } // Quick check before doing lookup
|
|
bool IsDefaultCAlign() { return _fBit.bDefaultCAlign; } // Quick check before doing lookup
|
|
bool IsWordWrap() { return _fBit.bWordWrap; } // Quick check before doing lookup
|
|
bool HasAnimation() { return _fBit.bHasAnimation; } // Quick check before doing lookup
|
|
bool IsDefaultCursor() { return _fBit.bDefaultCursor; } // Quick check before doing lookup
|
|
|
|
// Quick property accessors (since system has knowledge of its unchangable value expressions, use cached values
|
|
// directly were possible to bypass GetValue value lookup). Quick accessors are only used during non-cache
|
|
// gets. (PostSourceChange requires GetValue directly (with update-cache flag) for cache updates.)
|
|
// All derived classes do accessors normally (no direct cache lookups)
|
|
|
|
#define DUIQuickGetter(t, gv, p, i) { Value* pv; t v = (pv = GetValue(p##Prop, PI_##i))->gv; pv->Release(); return v; }
|
|
#define DUIQuickGetterInd(gv, p, i) { return (*ppv = GetValue(p##Prop, PI_##i))->gv; }
|
|
#define DUIQuickSetter(cv, p) { Value* pv = Value::cv; if (!pv) return E_OUTOFMEMORY; HRESULT hr = SetValue(p##Prop, PI_Local, pv); pv->Release(); return hr; }
|
|
|
|
Element* GetParent() { return _peLocParent; }
|
|
bool GetVisible() { return _fBit.bCmpVisible; }
|
|
int GetWidth() DUIQuickGetter(int, GetInt(), Width, Specified)
|
|
int GetHeight() DUIQuickGetter(int, GetInt(), Height, Specified)
|
|
ElementList* GetChildren(Value** ppv) { return (*ppv = (HasChildren() ? GetValue(ChildrenProp, PI_Specified) : ChildrenProp->pvDefault))->GetElementList(); }
|
|
int GetX() DUIQuickGetter(int, GetInt(), X, Specified)
|
|
int GetY() DUIQuickGetter(int, GetInt(), Y, Specified)
|
|
Layout* GetLayout(Value** ppv) { return (*ppv = (HasLayout() ? GetValue(LayoutProp, PI_Specified) : LayoutProp->pvDefault))->GetLayout(); }
|
|
int GetLayoutPos() { return _dSpecLayoutPos; }
|
|
const RECT* GetBorderThickness(Value** ppv) { return (*ppv = (HasBorder() ? GetValue(BorderThicknessProp, PI_Specified) : BorderThicknessProp->pvDefault))->GetRect(); }
|
|
int GetBorderStyle() DUIQuickGetter(int, GetInt(), BorderStyle, Specified)
|
|
int GetBorderStdColor() DUIQuickGetter(int, GetInt(), BorderColor, Specified)
|
|
const Fill* GetBorderColor(Value** ppv) DUIQuickGetterInd(GetFill(), BorderColor, Specified)
|
|
const RECT* GetPadding(Value** ppv) { return (*ppv = (HasPadding() ? GetValue(PaddingProp, PI_Specified) : PaddingProp->pvDefault))->GetRect(); }
|
|
const RECT* GetMargin(Value** ppv) { return (*ppv = (HasMargin() ? GetValue(MarginProp, PI_Specified) : MarginProp->pvDefault))->GetRect(); }
|
|
const POINT* GetLocation(Value** ppv) DUIQuickGetterInd(GetPoint(), Location, Local)
|
|
const SIZE* GetExtent(Value** ppv) DUIQuickGetterInd(GetSize(), Extent, Local)
|
|
const SIZE* GetDesiredSize() { return &_sizeLocDesiredSize; }
|
|
int GetForegroundStdColor() DUIQuickGetter(int, GetInt(), Foreground, Specified)
|
|
const Fill* GetForegroundColor(Value** ppv) DUIQuickGetterInd(GetFill(), Foreground, Specified)
|
|
int GetBackgroundStdColor() DUIQuickGetter(int, GetInt(), Background, Specified)
|
|
const LPWSTR GetContentString(Value** ppv) { return (*ppv = (HasContent() ? GetValue(ContentProp, PI_Specified) : Value::pvStringNull))->GetString(); }
|
|
const LPWSTR GetFontFace(Value** ppv) DUIQuickGetterInd(GetString(), FontFace, Specified)
|
|
int GetFontSize() DUIQuickGetter(int, GetInt(), FontSize, Specified)
|
|
int GetFontWeight() DUIQuickGetter(int, GetInt(), FontWeight, Specified)
|
|
int GetFontStyle() DUIQuickGetter(int, GetInt(), FontStyle, Specified)
|
|
int GetActive() { return _fBit.fSpecActive; }
|
|
int GetContentAlign() { Value* pv; int v = (pv = (!IsDefaultCAlign() ? GetValue(ContentAlignProp, PI_Specified) : Value::pvIntZero))->GetInt(); pv->Release(); return v; }
|
|
bool GetKeyFocused() { return _fBit.bSpecKeyFocused; }
|
|
bool GetKeyWithin() { return _fBit.bLocKeyWithin; }
|
|
bool GetMouseFocused() { return _fBit.bSpecMouseFocused; }
|
|
bool GetMouseWithin() { return _fBit.bLocMouseWithin; }
|
|
const LPWSTR GetClass(Value** ppv) DUIQuickGetterInd(GetString(), Class, Specified)
|
|
ATOM GetID() { return _atomSpecID; }
|
|
PropertySheet* GetSheet() { return _pvSpecSheet->GetPropertySheet(); }
|
|
bool GetSelected() { return _fBit.bSpecSelected; }
|
|
int GetAlpha() { return _dSpecAlpha; }
|
|
int GetAnimation() DUIQuickGetter(int, GetInt(), Animation, Specified)
|
|
int GetDirection() DUIQuickGetter(int, GetInt(), Direction, Specified)
|
|
bool GetAccessible() { return _fBit.bSpecAccessible; }
|
|
int GetAccRole() DUIQuickGetter(int, GetInt(), AccRole, Specified)
|
|
int GetAccState() DUIQuickGetter(int, GetInt(), AccState, Specified)
|
|
const LPWSTR GetAccName(Value** ppv) DUIQuickGetterInd(GetString(), AccName, Specified)
|
|
const LPWSTR GetAccDesc(Value** ppv) DUIQuickGetterInd(GetString(), AccDesc, Specified)
|
|
const LPWSTR GetAccValue(Value** ppv) DUIQuickGetterInd(GetString(), AccValue, Specified)
|
|
const LPWSTR GetAccDefAction(Value** ppv) DUIQuickGetterInd(GetString(), AccDefAction, Specified)
|
|
int GetShortcut() DUIQuickGetter(int, GetInt(), Shortcut, Specified)
|
|
bool GetEnabled() { return _fBit.bSpecEnabled; }
|
|
|
|
HRESULT SetVisible(bool v) DUIQuickSetter(CreateBool(v), Visible)
|
|
HRESULT SetWidth(int v) DUIQuickSetter(CreateInt(v), Width)
|
|
HRESULT SetHeight(int v) DUIQuickSetter(CreateInt(v), Height)
|
|
HRESULT SetX(int v) DUIQuickSetter(CreateInt(v), X)
|
|
HRESULT SetY(int v) DUIQuickSetter(CreateInt(v), Y)
|
|
HRESULT SetLayout(Layout* v) DUIQuickSetter(CreateLayout(v), Layout)
|
|
HRESULT SetLayoutPos(int v) DUIQuickSetter(CreateInt(v), LayoutPos)
|
|
HRESULT SetBorderThickness(int l, int t, int r, int b) DUIQuickSetter(CreateRect(l, t, r, b), BorderThickness)
|
|
HRESULT SetBorderStyle(int v) DUIQuickSetter(CreateInt(v), BorderStyle)
|
|
HRESULT SetBorderStdColor(int v) DUIQuickSetter(CreateInt(v), BorderColor)
|
|
HRESULT SetBorderColor(COLORREF cr) DUIQuickSetter(CreateColor(cr), BorderColor)
|
|
HRESULT SetBorderGradientColor(COLORREF cr0,
|
|
COLORREF cr1, BYTE dType = FILLTYPE_HGradient) DUIQuickSetter(CreateColor(cr0, cr1, dType), BorderColor)
|
|
HRESULT SetPadding(int l, int t, int r, int b) DUIQuickSetter(CreateRect(l, t, r, b), Padding)
|
|
HRESULT SetMargin(int l, int t, int r, int b) DUIQuickSetter(CreateRect(l, t, r, b), Margin)
|
|
HRESULT SetForegroundStdColor(int v) DUIQuickSetter(CreateInt(v), Foreground)
|
|
HRESULT SetForegroundColor(COLORREF cr) DUIQuickSetter(CreateColor(cr), Foreground)
|
|
HRESULT SetForegroundColor(COLORREF cr0, COLORREF cr1,
|
|
BYTE dType = FILLTYPE_HGradient) DUIQuickSetter(CreateColor(cr0, cr1, dType), Foreground)
|
|
HRESULT SetForegroundColor(COLORREF cr0, COLORREF cr1, COLORREF cr2,
|
|
BYTE dType = FILLTYPE_TriHGradient) DUIQuickSetter(CreateColor(cr0, cr1, cr2, dType), Foreground)
|
|
HRESULT SetBackgroundStdColor(int v) DUIQuickSetter(CreateInt(v), Background)
|
|
HRESULT SetBackgroundColor(COLORREF cr) DUIQuickSetter(CreateColor(cr), Background)
|
|
HRESULT SetBackgroundColor(COLORREF cr0, COLORREF cr1,
|
|
BYTE dType = FILLTYPE_HGradient) DUIQuickSetter(CreateColor(cr0, cr1, dType), Background)
|
|
HRESULT SetBackgroundColor(COLORREF cr0, COLORREF cr1, COLORREF cr2,
|
|
BYTE dType = FILLTYPE_TriHGradient) DUIQuickSetter(CreateColor(cr0, cr1, cr2, dType), Background)
|
|
HRESULT SetContentString(LPCWSTR v) DUIQuickSetter(CreateString(v), Content)
|
|
HRESULT SetContentGraphic(LPCWSTR v,
|
|
BYTE dBlendMode = GRAPHIC_NoBlend,
|
|
UINT dBlendValue = 0) DUIQuickSetter(CreateGraphic(v, dBlendMode, dBlendValue), Content)
|
|
HRESULT SetContentGraphic(LPCWSTR v, USHORT cxDesired,
|
|
USHORT cyDesired) DUIQuickSetter(CreateGraphic(v, cxDesired, cyDesired), Content)
|
|
HRESULT SetFontFace(LPCWSTR v) DUIQuickSetter(CreateString(v), FontFace)
|
|
HRESULT SetFontSize(int v) DUIQuickSetter(CreateInt(v), FontSize)
|
|
HRESULT SetFontWeight(int v) DUIQuickSetter(CreateInt(v), FontWeight)
|
|
HRESULT SetFontStyle(int v) DUIQuickSetter(CreateInt(v), FontStyle)
|
|
HRESULT SetActive(int v) DUIQuickSetter(CreateInt(v), Active)
|
|
HRESULT SetContentAlign(int v) DUIQuickSetter(CreateInt(v), ContentAlign)
|
|
HRESULT SetClass(LPCWSTR v) DUIQuickSetter(CreateString(v), Class)
|
|
HRESULT SetID(LPCWSTR v) DUIQuickSetter(CreateAtom(v), ID)
|
|
HRESULT SetSheet(PropertySheet* v) DUIQuickSetter(CreatePropertySheet(v), Sheet)
|
|
HRESULT SetSelected(bool v) DUIQuickSetter(CreateBool(v), Selected)
|
|
HRESULT SetAlpha(int v) DUIQuickSetter(CreateInt(v), Alpha)
|
|
HRESULT SetAnimation(int v) DUIQuickSetter(CreateInt(v), Animation)
|
|
HRESULT SetStdCursor(int v) DUIQuickSetter(CreateInt(v), Cursor)
|
|
HRESULT SetCursor(LPCWSTR v) DUIQuickSetter(CreateCursor(v), Cursor)
|
|
HRESULT SetDirection(int v) DUIQuickSetter(CreateInt(v), Direction)
|
|
HRESULT SetAccessible(bool v) DUIQuickSetter(CreateBool(v), Accessible)
|
|
HRESULT SetAccRole(int v) DUIQuickSetter(CreateInt(v), AccRole)
|
|
HRESULT SetAccState(int v) DUIQuickSetter(CreateInt(v), AccState)
|
|
HRESULT SetAccName(LPCWSTR v) DUIQuickSetter(CreateString(v), AccName)
|
|
HRESULT SetAccDesc(LPCWSTR v) DUIQuickSetter(CreateString(v), AccDesc)
|
|
HRESULT SetAccValue(LPCWSTR v) DUIQuickSetter(CreateString(v), AccValue)
|
|
HRESULT SetAccDefAction(LPCWSTR v) DUIQuickSetter(CreateString(v), AccDefAction)
|
|
HRESULT SetShortcut(int v) DUIQuickSetter(CreateInt(v), Shortcut)
|
|
HRESULT SetEnabled(bool v) DUIQuickSetter(CreateBool(v), Enabled)
|
|
|
|
////////////////////////////////////////////////////////
|
|
// ClassInfo accessors (static and virtual instance-based)
|
|
|
|
static IClassInfo* Class;
|
|
virtual IClassInfo* GetClassInfo() { return Class; }
|
|
static HRESULT Register();
|
|
|
|
///////////////////////////////////////////////////////
|
|
// Accessibility support
|
|
|
|
DuiAccessible * _pDuiAccessible;
|
|
virtual HRESULT GetAccessibleImpl(IAccessible ** ppAccessible);
|
|
HRESULT QueueDefaultAction();
|
|
virtual HRESULT DefaultAction();
|
|
};
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Element helpers
|
|
|
|
Element* ElementFromGadget(HGADGET hGadget);
|
|
void QueryDetails(Element* pe, HWND hParent);
|
|
|
|
////////////////////////////////////////////////////////
|
|
// DeferCycle: Per-thread deferring information
|
|
|
|
// Group notifications: deferred until EndDefer and coalesced
|
|
struct GCRecord
|
|
{
|
|
Element* pe;
|
|
int fGroups;
|
|
};
|
|
|
|
// Property notifications: deferred until source's dependency
|
|
// graph is searched (within SetValue call), not coalesced
|
|
struct PCRecord
|
|
{
|
|
bool fVoid;
|
|
Element* pe;
|
|
PropertyInfo* ppi;
|
|
int iIndex;
|
|
Value* pvOld;
|
|
Value* pvNew;
|
|
DepRecs dr;
|
|
int iPrevElRec;
|
|
};
|
|
|
|
class DeferCycle
|
|
{
|
|
public:
|
|
static HRESULT Create(DeferCycle** ppDC);
|
|
void Destroy() { HDelete<DeferCycle>(this); }
|
|
|
|
void Reset();
|
|
|
|
DynamicArray<GCRecord>* pdaGC; // Group changed database
|
|
DynamicArray<GCRecord>* pdaGCLP; // Low priority group changed database
|
|
DynamicArray<PCRecord>* pdaPC; // Property changed database
|
|
ValueMap<Element*,BYTE>* pvmLayoutRoot; // Layout trees pending
|
|
ValueMap<Element*,BYTE>* pvmUpdateDSRoot; // Update desired size trees pending
|
|
|
|
int cEnter;
|
|
bool fFiring;
|
|
int iGCPtr;
|
|
int iGCLPPtr;
|
|
int iPCPtr;
|
|
int iPCSSUpdate;
|
|
int cPCEnter;
|
|
|
|
DeferCycle() { }
|
|
HRESULT Initialize();
|
|
virtual ~DeferCycle();
|
|
};
|
|
|
|
#if DBG
|
|
// Process-wide element count
|
|
extern LONG g_cElement;
|
|
#endif
|
|
|
|
// Per-thread Element slot
|
|
extern DWORD g_dwElSlot;
|
|
|
|
struct ElTls
|
|
{
|
|
HDCONTEXT hCtx; // DirectUser thread context
|
|
int cRef;
|
|
SBAlloc* psba;
|
|
DeferCycle* pdc;
|
|
FontCache* pfc;
|
|
bool fCoInitialized;
|
|
int dEnableAnimations;
|
|
#if DBG
|
|
int cDNCBEnter; // Track when _DisplayNodeCallback is entered
|
|
#endif
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Per-Context object access
|
|
|
|
inline bool IsAnimationsEnabled()
|
|
{
|
|
ElTls* petls = (ElTls*)TlsGetValue(g_dwElSlot);
|
|
if (!petls)
|
|
return false;
|
|
return (petls->dEnableAnimations == 0);
|
|
}
|
|
|
|
inline void EnableAnimations()
|
|
{
|
|
ElTls* petls = (ElTls*)TlsGetValue(g_dwElSlot);
|
|
if (!petls)
|
|
return;
|
|
petls->dEnableAnimations++;
|
|
}
|
|
|
|
inline void DisableAnimations()
|
|
{
|
|
ElTls* petls = (ElTls*)TlsGetValue(g_dwElSlot);
|
|
if (!petls)
|
|
return;
|
|
petls->dEnableAnimations--;
|
|
}
|
|
|
|
inline HDCONTEXT GetContext()
|
|
{
|
|
ElTls* petls = (ElTls*)TlsGetValue(g_dwElSlot);
|
|
if (!petls)
|
|
return NULL;
|
|
return petls->hCtx;
|
|
}
|
|
|
|
inline DeferCycle* GetDeferObject()
|
|
{
|
|
ElTls* petls = (ElTls*)TlsGetValue(g_dwElSlot);
|
|
if (!petls)
|
|
return NULL;
|
|
return petls->pdc;
|
|
}
|
|
|
|
inline FontCache* GetFontCache()
|
|
{
|
|
ElTls* petls = (ElTls*)TlsGetValue(g_dwElSlot);
|
|
if (!petls)
|
|
return NULL;
|
|
return petls->pfc;
|
|
}
|
|
|
|
inline SBAlloc* GetSBAllocator()
|
|
{
|
|
#if 0
|
|
ElTls* petls = (ElTls*)TlsGetValue(g_dwElSlot);
|
|
if (!petls)
|
|
return NULL;
|
|
return petls->psba;
|
|
#else
|
|
ElTls* petls = (ElTls*)TlsGetValue(g_dwElSlot);
|
|
DUIAssert(petls != NULL, "Must have valid SBAllocator");
|
|
return petls->psba;
|
|
#endif
|
|
}
|
|
|
|
// Use to check if Element may be accessed via the current thread
|
|
#if DBG
|
|
inline void ContextCheck(Element* pe)
|
|
{
|
|
DUIAssert(pe->owner.dwTLSSlot == g_dwElSlot, "Element being accessed out of side-by-side instance");
|
|
DUIAssert(pe->owner.hCtx == GetContext(), "Element being accessed out of context");
|
|
}
|
|
#define DUIContextAssert(pe) ContextCheck(pe)
|
|
#else
|
|
#define DUIContextAssert(pe)
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Property enumerations
|
|
|
|
// ActiveProp
|
|
#define AE_Inactive 0x00000000
|
|
#define AE_Mouse 0x00000001
|
|
#define AE_Keyboard 0x00000002
|
|
#define AE_MouseAndKeyboard (AE_Mouse | AE_Keyboard)
|
|
|
|
// BorderStyleProp
|
|
#define BDS_Solid 0
|
|
#define BDS_Raised 1
|
|
#define BDS_Sunken 2
|
|
#define BDS_Rounded 3
|
|
|
|
// FontStyleProp
|
|
#define FS_None 0x00000000
|
|
#define FS_Italic 0x00000001
|
|
#define FS_Underline 0x00000002
|
|
#define FS_StrikeOut 0x00000004
|
|
#define FS_Shadow 0x00000008
|
|
|
|
// FontWeightProp
|
|
#define FW_DontCare 0
|
|
#define FW_Thin 100
|
|
#define FW_ExtraLight 200
|
|
#define FW_Light 300
|
|
#define FW_Normal 400
|
|
#define FW_Medium 500
|
|
#define FW_SemiBold 600
|
|
#define FW_Bold 700
|
|
#define FW_ExtraBold 800
|
|
#define FW_Heavy 900
|
|
|
|
// ContentAlignProp (CAE_XY, Y=bits 0-1, X=bits 2-3)
|
|
#define CA_TopLeft 0x00000000 // (0,0)
|
|
#define CA_TopCenter 0x00000001 // (0,1)
|
|
#define CA_TopRight 0x00000002 // (0,2)
|
|
#define CA_MiddleLeft 0x00000004 // (1,0)
|
|
#define CA_MiddleCenter 0x00000005 // (1,1)
|
|
#define CA_MiddleRight 0x00000006 // (1,2)
|
|
#define CA_BottomLeft 0x00000008 // (2,0)
|
|
#define CA_BottomCenter 0x00000009 // (2,1)
|
|
#define CA_BottomRight 0x0000000A // (2,2)
|
|
#define CA_WrapLeft 0x0000000C // (3,0)
|
|
#define CA_WrapCenter 0x0000000D // (3,1)
|
|
#define CA_WrapRight 0x0000000E // (3,2)
|
|
|
|
#define CA_EndEllipsis 0x00000010
|
|
#define CA_FocusRect 0x00000020
|
|
|
|
// AnimationProp (Interpolation | CatType [ | CatType | ... ] | Speed)
|
|
#define ANI_InterpolMask 0x0000000F
|
|
#define ANI_DelayMask 0x000000F0
|
|
#define ANI_TypeMask 0x0FFFFF00
|
|
#define ANI_SpeedMask 0xF0000000
|
|
|
|
#define ANI_DefaultInterpol 0x00000000
|
|
#define ANI_Linear 0x00000001 // INTERPOLATION_LINEAR
|
|
#define ANI_Log 0x00000002 // INTERPOLATION_LOG
|
|
#define ANI_Exp 0x00000003 // INTERPOLATION_EXP
|
|
#define ANI_S 0x00000004 // INTERPOLATION_S
|
|
|
|
#define ANI_DelayNone 0x00000000
|
|
#define ANI_DelayShort 0x00000010
|
|
#define ANI_DelayMedium 0x00000020
|
|
#define ANI_DelayLong 0x00000030
|
|
|
|
#define ANI_AlphaType 0x00000F00
|
|
#define ANI_BoundsType 0x0000F000
|
|
#define ANI_XFormType 0x000F0000
|
|
|
|
#define ANI_None 0x00000000
|
|
#define ANI_Alpha 0x00000100
|
|
#define ANI_Position 0x00001000
|
|
#define ANI_Size 0x00002000
|
|
#define ANI_SizeH 0x00003000
|
|
#define ANI_SizeV 0x00004000
|
|
#define ANI_Rect 0x00005000
|
|
#define ANI_RectH 0x00006000
|
|
#define ANI_RectV 0x00007000
|
|
#define ANI_Scale 0x00010000
|
|
|
|
#define ANI_DefaultSpeed 0x00000000
|
|
#define ANI_VeryFast 0x10000000
|
|
#define ANI_Fast 0x20000000
|
|
#define ANI_MediumFast 0x30000000
|
|
#define ANI_Medium 0x40000000
|
|
#define ANI_MediumSlow 0x50000000
|
|
#define ANI_Slow 0x60000000
|
|
#define ANI_VerySlow 0x70000000
|
|
|
|
// CursorProp
|
|
#define CUR_Arrow 0
|
|
#define CUR_Hand 1
|
|
#define CUR_Help 2
|
|
#define CUR_No 3
|
|
#define CUR_Wait 4
|
|
#define CUR_SizeAll 5
|
|
#define CUR_SizeNESW 6
|
|
#define CUR_SizeNS 7
|
|
#define CUR_SizeNWSE 8
|
|
#define CUR_SizeWE 9
|
|
#define CUR_Total 10
|
|
|
|
// Internal property indicies for property compares. Must match up one to one
|
|
// with Element property definitions
|
|
#define _PIDX_Parent 0
|
|
#define _PIDX_PosInLayout 1
|
|
#define _PIDX_SizeInLayout 2
|
|
#define _PIDX_DesiredSize 3
|
|
#define _PIDX_LastDSConst 4
|
|
#define _PIDX_Location 5
|
|
#define _PIDX_Extent 6
|
|
#define _PIDX_LayoutPos 7
|
|
#define _PIDX_Active 8
|
|
#define _PIDX_Children 9
|
|
#define _PIDX_Layout 10
|
|
#define _PIDX_BorderThickness 11
|
|
#define _PIDX_Padding 12
|
|
#define _PIDX_Margin 13
|
|
#define _PIDX_Visible 14
|
|
#define _PIDX_X 15
|
|
#define _PIDX_Y 16
|
|
#define _PIDX_ContentAlign 17
|
|
#define _PIDX_KeyFocused 18
|
|
#define _PIDX_KeyWithin 19
|
|
#define _PIDX_MouseFocused 20
|
|
#define _PIDX_MouseWithin 21
|
|
#define _PIDX_Content 22
|
|
#define _PIDX_Sheet 23
|
|
#define _PIDX_Width 24
|
|
#define _PIDX_Height 25
|
|
#define _PIDX_BorderStyle 26
|
|
#define _PIDX_BorderColor 27
|
|
#define _PIDX_Foreground 28
|
|
#define _PIDX_Background 29
|
|
#define _PIDX_FontFace 30
|
|
#define _PIDX_FontSize 31
|
|
#define _PIDX_FontWeight 32
|
|
#define _PIDX_FontStyle 33
|
|
#define _PIDX_Class 34
|
|
#define _PIDX_ID 35
|
|
#define _PIDX_Selected 36
|
|
#define _PIDX_Alpha 37
|
|
#define _PIDX_Animation 38
|
|
#define _PIDX_Cursor 39
|
|
#define _PIDX_Direction 40
|
|
#define _PIDX_Accessible 41
|
|
#define _PIDX_AccRole 42
|
|
#define _PIDX_AccState 43
|
|
#define _PIDX_AccName 44
|
|
#define _PIDX_AccDesc 45
|
|
#define _PIDX_AccValue 46
|
|
#define _PIDX_AccDefAction 47
|
|
#define _PIDX_Shortcut 48
|
|
#define _PIDX_Enabled 49
|
|
|
|
#define _PIDX_TOTAL 50
|
|
|
|
////////////////////////////////////////////////////////
|
|
// Class information template
|
|
|
|
// All classes that derive from Element must create a global instance of this class.
|
|
// It maintains a list of the class properties (provides enumeration) and creation method
|
|
// C = Class, B = Base class
|
|
|
|
// Defined in Element.cpp
|
|
extern UINT g_iGlobalCI;
|
|
extern UINT g_iGlobalPI;
|
|
|
|
template <typename C, typename B> class ClassInfo : public IClassInfo
|
|
{
|
|
public:
|
|
// Registration (cannot unregister -- will be registered until UnInitProcess is called)
|
|
static HRESULT Register(LPCWSTR pszName, PropertyInfo** ppPI, UINT cPI)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// If class mapping doesn't exist, registration fails
|
|
if (!Element::pciMap)
|
|
return E_FAIL;
|
|
|
|
// Check for entry in mapping, if exists, ignore registration
|
|
if (!Element::pciMap->GetItem((void*)pszName))
|
|
{
|
|
// Never been registered, create class info entry
|
|
hr = Create(pszName, ppPI, cPI, &C::Class);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = Element::pciMap->SetItem((void*)pszName, C::Class);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// Construction
|
|
static HRESULT Create(LPCWSTR pszName, PropertyInfo** ppPI, UINT cPI, IClassInfo** ppCI)
|
|
{
|
|
*ppCI = NULL;
|
|
|
|
// Element map must already exist
|
|
if (!Element::pciMap)
|
|
return E_FAIL;
|
|
|
|
ClassInfo* pci = HNew<ClassInfo>();
|
|
if (!pci)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// Setup state
|
|
pci->_ppPI = ppPI;
|
|
pci->_cPI = cPI;
|
|
pci->_pszName = pszName;
|
|
|
|
// Set global index
|
|
pci->_iGlobalIndex = g_iGlobalCI++;
|
|
|
|
// Setup property ownership
|
|
for (UINT i = 0; i < cPI; i++)
|
|
{
|
|
ppPI[i]->_iIndex = i;
|
|
ppPI[i]->_iGlobalIndex = g_iGlobalPI++;
|
|
ppPI[i]->_pciOwner = pci;
|
|
}
|
|
|
|
#if DBG
|
|
// Call string conversion method directly since can't assume Util library is available for header
|
|
CHAR szNameA[101];
|
|
ZeroMemory(szNameA, sizeof(szNameA));
|
|
WideCharToMultiByte(CP_ACP, 0, pszName, -1, szNameA, (sizeof(szNameA) / sizeof(CHAR)) - 1, NULL, NULL);
|
|
//DUITrace("RegDUIClass[%d]: '%s', %d ClassProps\n", pci->_iGlobalIndex, szNameA, cPI);
|
|
#endif
|
|
|
|
*ppCI = pci;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void Destroy() { HDelete<ClassInfo>(this); }
|
|
|
|
public:
|
|
HRESULT CreateInstance(OUT Element** ppElement) { return C::Create(ppElement); }
|
|
PropertyInfo* EnumPropertyInfo(UINT nEnum) { return (nEnum < _cPI) ? _ppPI[nEnum] : B::Class->EnumPropertyInfo(nEnum - _cPI); }
|
|
UINT GetPICount() { return _cPI + B::Class->GetPICount(); }
|
|
UINT GetGlobalIndex() { return _iGlobalIndex; }
|
|
IClassInfo* GetBaseClass() { return B::Class; }
|
|
LPCWSTR GetName() { return _pszName; }
|
|
bool IsValidProperty(PropertyInfo* ppi) { return (ppi->_pciOwner == this) ? true : B::Class->IsValidProperty(ppi); }
|
|
bool IsSubclassOf(IClassInfo* pci) { return (pci == this) ? true : B::Class->IsSubclassOf(pci); }
|
|
|
|
ClassInfo() { }
|
|
virtual ~ClassInfo() { }
|
|
|
|
private:
|
|
PropertyInfo** _ppPI; // Array of properties for this class (C)
|
|
UINT _cPI; // Count of properties for this class (C)
|
|
UINT _iGlobalIndex; // Zero-based unique contiguous class id
|
|
LPCWSTR _pszName; // Class name
|
|
};
|
|
|
|
} // namespace DirectUI
|
|
|
|
#endif // DUI_CORE_ELEMENT_H_INCLUDED
|