Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

8024 lines
254 KiB

  1. //=========== Copyright Valve Corporation, All rights reserved. ===============//
  2. //
  3. // Purpose:
  4. //=============================================================================//
  5. #ifndef STYLEPROPERTIES_H
  6. #define STYLEPROPERTIES_H
  7. #ifdef _WIN32
  8. #pragma once
  9. #endif
  10. #include "layout/stylesymbol.h"
  11. #include "layout/csshelpers.h"
  12. #include "tier1/utlptrarray.h"
  13. #include "tier1/utlhashmap.h"
  14. #include "iuipanelstyle.h"
  15. #include "panoramatypes.h"
  16. namespace panorama
  17. {
  18. // Helper for getting actual size of parent, which will expand up to window size if top level
  19. void GetParentSizeAvailable( IUIPanel *pPanel, float &flParentWidth, float &flParentHeight, float &flParentPerspective );
  20. void GetAnimationCurveControlPoints( EAnimationTimingFunction eTransitionEffect, Vector2D vecPoints[4] );
  21. //-----------------------------------------------------------------------------
  22. // Purpose: Information on a property in the middle of a transition
  23. //-----------------------------------------------------------------------------
  24. struct PropertyInTransition_t
  25. {
  26. PropertyInTransition_t() { m_pStyleProperty = NULL; }
  27. ~PropertyInTransition_t()
  28. {
  29. if( m_pStyleProperty )
  30. UIEngine()->UIStyleFactory()->FreeStyleProperty( m_pStyleProperty );
  31. }
  32. TransitionProperty_t m_transitionData;
  33. double m_flTransitionStartTime;
  34. CStyleProperty *m_pStyleProperty;
  35. #ifdef DBGFLAG_VALIDATE
  36. void Validate( CValidator &validator, const tchar *pchName );
  37. #endif
  38. private:
  39. PropertyInTransition_t( const PropertyInTransition_t & );
  40. PropertyInTransition_t &operator=(const PropertyInTransition_t &rhs);
  41. };
  42. //-----------------------------------------------------------------------------
  43. // Purpose: Individual animation property data
  44. //-----------------------------------------------------------------------------
  45. struct AnimationProperty_t
  46. {
  47. CPanoramaSymbol m_symName; // keyframe name
  48. double m_flDuration;
  49. EAnimationTimingFunction m_eTimingFunction;
  50. CCubicBezierCurve< Vector2D > m_CubicBezier;
  51. float m_flIteration; // value or infinite
  52. EAnimationDirection m_eAnimationDirection;
  53. double m_flDelay;
  54. bool operator==(const AnimationProperty_t &rhs) const
  55. {
  56. return (m_symName == rhs.m_symName && m_flDuration == rhs.m_flDuration && m_eTimingFunction == rhs.m_eTimingFunction &&
  57. (m_eTimingFunction != k_EAnimationCustomBezier ||
  58. (m_CubicBezier.ControlPoint( 0 ) == rhs.m_CubicBezier.ControlPoint( 0 ) &&
  59. m_CubicBezier.ControlPoint( 1 ) == rhs.m_CubicBezier.ControlPoint( 1 ) &&
  60. m_CubicBezier.ControlPoint( 2 ) == rhs.m_CubicBezier.ControlPoint( 2 ) &&
  61. m_CubicBezier.ControlPoint( 3 ) == rhs.m_CubicBezier.ControlPoint( 3 )
  62. )
  63. ) &&
  64. m_flIteration == rhs.m_flIteration && m_eAnimationDirection == rhs.m_eAnimationDirection && m_flDelay == rhs.m_flDelay);
  65. }
  66. bool operator!=(const AnimationProperty_t &rhs) const
  67. {
  68. return !(*this == rhs);
  69. }
  70. };
  71. //-----------------------------------------------------------------------------
  72. // Purpose: Information on a property in the middle of a transition
  73. //-----------------------------------------------------------------------------
  74. class CActiveAnimation
  75. {
  76. public:
  77. CActiveAnimation( float flAnimationStart, AnimationProperty_t &animationProperty );
  78. ~CActiveAnimation();
  79. CPanoramaSymbol GetName() const { return m_animationData.m_symName; }
  80. const AnimationProperty_t &GetAnimationData() const { return m_animationData; }
  81. void AddFrameData( float flPercent, EAnimationTimingFunction eTimingFunction, const CCubicBezierCurve<Vector2D> &cubicBezier, CStyleProperty *pProperty, float flUIScaleFactor );
  82. bool BHasFrameDataForProperty( CStyleSymbol symStyleProperty );
  83. double GetStartTime() const { return m_flAnimationStartTime; }
  84. double GetStartTimeWithDelay() const { return m_flAnimationStartTime + m_animationData.m_flDelay; }
  85. float CalculateAnimationEndTime() const;
  86. void Reset();
  87. void GetAffectedPanelLayoutFlags( CPanelStyle *pPanelStyle, bool *pbAffectsSize, bool *pbAffectsPosition );
  88. bool BAffectsCompositionOnly();
  89. bool BAffectsPanelLayoutFlags( CPanelStyle *pPanelStyle );
  90. void UpdateUIScaleFactor( float flOldScaleFactor, float flNewScaleFactor );
  91. // keyframe data
  92. struct PropertyFrameData_t
  93. {
  94. float m_flPercent; // percent into animation when styles apply.
  95. EAnimationTimingFunction m_eTimingFunction; // timing function can be overridden per keyframe
  96. CCubicBezierCurve< Vector2D > m_CubicBezier;
  97. CStyleProperty *m_pStyleProperty; // property to apply
  98. };
  99. typedef CUtlVector< PropertyFrameData_t > VecPropertyFrameData_t;
  100. const VecPropertyFrameData_t *GetFrameData( CStyleSymbol symProperty );
  101. #ifdef DBGFLAG_VALIDATE
  102. virtual void Validate( CValidator &validator, const tchar *pchName );
  103. #endif
  104. private:
  105. CActiveAnimation();
  106. CActiveAnimation( const CActiveAnimation & );
  107. CActiveAnimation &operator=(const CActiveAnimation &rhs);
  108. AnimationProperty_t m_animationData;
  109. double m_flAnimationStartTime;
  110. CUtlMap< CStyleSymbol, VecPropertyFrameData_t *, short, CDefLess< CStyleSymbol > > m_mapFrameData;
  111. };
  112. //-----------------------------------------------------------------------------
  113. // Purpose: Represents all components that can be included in an individual CSS selector
  114. //-----------------------------------------------------------------------------
  115. class CStyleSelector
  116. {
  117. public:
  118. CStyleSelector()
  119. {
  120. m_pchID = NULL;
  121. m_eStyleFlags = k_EStyleFlagNone;
  122. m_unSelectorFlags = 0;
  123. }
  124. ~CStyleSelector()
  125. {
  126. ClearID();
  127. }
  128. void SetID( const char *pchID )
  129. {
  130. ClearID();
  131. m_pchID = strdup( pchID );
  132. }
  133. void ClearID()
  134. {
  135. if( m_pchID )
  136. {
  137. free( (void*)m_pchID );
  138. m_pchID = NULL;
  139. }
  140. }
  141. const char *GetID() const { return m_pchID; }
  142. void SetPanelType( CPanoramaSymbol symType ) { m_symPanelType = symType; }
  143. CPanoramaSymbol GetPanelType() const { return m_symPanelType; }
  144. void SetClasses( CPanoramaSymbol *pSymbols, int cSymbols ) { m_classes.Copy( pSymbols, cSymbols ); }
  145. const CUtlPtrArray< CPanoramaSymbol > &GetClasses() const { return m_classes; }
  146. void SetStyleFlags( EStyleFlags eFlags ) { m_eStyleFlags = eFlags; }
  147. EStyleFlags GetStyleFlags() const { return m_eStyleFlags; }
  148. // allows setting an ID w/o allocating for searching. Skips memory management
  149. void SetIDForSearch( const char *pchID )
  150. {
  151. m_pchID = pchID;
  152. }
  153. // allows setting classes w/o allocationg for searching. Skips memory management
  154. void SetClassesForSearch( CPanoramaSymbol *pSymbols, int cSymbols )
  155. {
  156. if( pSymbols )
  157. m_classes.TakeOwnership( pSymbols, cSymbols );
  158. else
  159. m_classes.DetatchAndClear();
  160. }
  161. void SetChildMatchesNextStyle()
  162. {
  163. m_unSelectorFlags |= k_ESelectorFlagsChildCombinator;
  164. }
  165. bool BChildMatchesNextStyle() const
  166. {
  167. return ((m_unSelectorFlags & k_ESelectorFlagsChildCombinator) != 0);
  168. }
  169. #ifdef DBGFLAG_VALIDATE
  170. void Validate( CValidator &validator, const tchar *pchName )
  171. {
  172. VALIDATE_SCOPE();
  173. validator.ClaimMemory( (void *)m_pchID );
  174. ValidateObj( m_classes );
  175. }
  176. #endif
  177. private:
  178. enum ESelectorFlags
  179. {
  180. k_ESelectorFlagsNone = 0,
  181. k_ESelectorFlagsChildCombinator = 1, // next selector must match child of panel that matched this style (.A > .B)
  182. };
  183. CStyleSelector( CStyleSelector const& ) { Assert( 0 ); }
  184. // id is a char pointer instead of CUtlString so we can do searches w/o allocations
  185. const char *m_pchID; // not empty if an ID is required
  186. CPanoramaSymbol m_symPanelType; // if invalid, applies to all panels
  187. CUtlPtrArray< CPanoramaSymbol > m_classes; // can be empty if id or panel type are set
  188. EStyleFlags m_eStyleFlags; // required style flags
  189. uint32 m_unSelectorFlags; // ESelectorFlags
  190. };
  191. //-----------------------------------------------------------------------------
  192. // Purpose: Base class for every style property, they all have a symbol for a name.
  193. //-----------------------------------------------------------------------------
  194. class CStyleProperty
  195. {
  196. public:
  197. CStyleProperty( CStyleSymbol symPropertyName )
  198. {
  199. m_symPropertyName = symPropertyName;
  200. m_bDisallowTransition = false;
  201. }
  202. virtual ~CStyleProperty() {}
  203. bool operator < (const CStyleProperty &rhs) const
  204. {
  205. return m_symPropertyName < rhs.m_symPropertyName;
  206. }
  207. CStyleSymbol GetPropertySymbol() const { return m_symPropertyName; }
  208. // Merges data to the target, this will only overwrite unset properties, and shouldn't clobber
  209. // already set ones.
  210. virtual void MergeTo( CStyleProperty *pTarget ) const
  211. {
  212. if( m_bDisallowTransition )
  213. pTarget->m_bDisallowTransition = true;
  214. }
  215. // Can this property support animation?
  216. virtual bool BCanTransition() = 0;
  217. // Interpolation func for animation of this property, must implement if you override BCanTransition to return true.
  218. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) = 0;
  219. // Parses string and sets value
  220. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString ) = 0;
  221. // Gets string representation of property
  222. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const = 0;
  223. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  224. // by looking at lower weight styles
  225. // Example: For margin, if we have only seen margin-length, should return false until top, bottom, right are set
  226. virtual bool BFullySet() { return true; }
  227. // called when applied to a panel before comparing with set values. Gives the style an opportunity to change any unset values to defaults
  228. virtual void ResolveDefaultValues() {}
  229. // called when we are ready to apply any scaling factor to the values
  230. virtual void ApplyUIScaleFactor( float flScaleFactor ) {}
  231. // called when applied to a panel after comparing with set values
  232. virtual void OnAppliedToPanel( IUIPanel *pPanel ) {}
  233. // Return a description for this property which will be shown in the debugger
  234. virtual const char *GetDescription( CStyleSymbol symProperty ) { return "&lt;Needs a description&gt;"; }
  235. // Does this property only affecting compositing when rendering, or does it affect drawing within the composition
  236. // layer for the panel it is applied to?
  237. virtual bool BAffectsCompositionOnly() { return false; }
  238. // Get suggested values based on current text for style property value
  239. virtual void GetSuggestedValues( CStyleSymbol symAlias, const char *pchTextSoFar, CUtlVector< CUtlString > &vecSuggestions ) { }
  240. // Comparison function
  241. virtual bool operator==(const CStyleProperty &rhs) const = 0;
  242. bool operator!=(const CStyleProperty &rhs) const { return !(*this == rhs); }
  243. // What layout attributes can be invalidated when the property is applied to a panel (compared to prior value)
  244. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const = 0;
  245. // Layout pieces that can be invalidated when the property is applied to a panel
  246. inline bool BInvalidatesSizeAndPosition( CStyleProperty *pCompareProperty ) const { return (GetInvalidateLayout( pCompareProperty ) == k_EStyleInvalidateLayoutSizeAndPosition); }
  247. inline bool BInvalidatesPosition( CStyleProperty *pCompareProperty ) const { return (GetInvalidateLayout( pCompareProperty ) == k_EStyleInvalidateLayoutPosition); }
  248. // If the style supports transition (BCanTransition), it may still be that this style instance disables transition and forces immediate apply, this controls that
  249. void SetDisallowTransition( bool bDisallowTransition ) { m_bDisallowTransition = bDisallowTransition; }
  250. // If the style supports transition (BCanTransition), it may still be that this style instance disables transition and forces immediate apply, this checks that
  251. bool BDisallowTransition() { return m_bDisallowTransition; }
  252. #ifdef DBGFLAG_VALIDATE
  253. virtual void Validate( CValidator &validator, const tchar *pchName );
  254. #endif
  255. // CLANG requires delete to be visible to derived classes even if new is not
  256. protected:
  257. #if !defined( SOURCE2_PANORAMA )
  258. #include "tier0/memdbgoff.h"
  259. #endif
  260. void *operator new(size_t size) throw(){ return NULL; }
  261. void *operator new(size_t size, int nBlockUse, const char *pFileName, int nLine) throw(){ return NULL; }
  262. void operator delete(void* p) { Assert( false ); }
  263. void operator delete(void* p, int nBlockUse, const char *pFileName, int nLine) { Assert( false ); }
  264. #if !defined( SOURCE2_PANORAMA )
  265. #include "tier0/memdbgon.h"
  266. #endif
  267. private:
  268. CStyleSymbol m_symPropertyName;
  269. bool m_bDisallowTransition;
  270. };
  271. typedef CUtlHashMap< panorama::CStyleSymbol, panorama::CStyleProperty *, CDefEquals< panorama::CStyleSymbol > > StylePropertyHash_t;
  272. //-----------------------------------------------------------------------------
  273. // Purpose: Represents a style's properties and position in a file
  274. //-----------------------------------------------------------------------------
  275. struct StyleFromFile_t
  276. {
  277. StyleFromFile_t()
  278. {
  279. m_pProperties = NULL;
  280. m_unFileLocation = 0;
  281. m_pNext = NULL;
  282. }
  283. ~StyleFromFile_t()
  284. {
  285. if( m_pProperties )
  286. {
  287. FOR_EACH_RBTREE_FAST( *m_pProperties, i )
  288. {
  289. UIEngine()->UIStyleFactory()->FreeStyleProperty( m_pProperties->Element( i ) );
  290. }
  291. SAFE_DELETE( m_pProperties );
  292. }
  293. SAFE_DELETE( m_pNext );
  294. }
  295. const CStyleProperty *GetProperty( CStyleSymbol symProperty ) const
  296. {
  297. if( !m_pProperties )
  298. return NULL;
  299. short i = m_pProperties->Find( symProperty );
  300. if( i == m_pProperties->InvalidIndex() )
  301. return NULL;
  302. return m_pProperties->Element( i );
  303. }
  304. #ifdef DBGFLAG_VALIDATE
  305. void Validate( CValidator &validator, const tchar *pchName )
  306. {
  307. VALIDATE_SCOPE();
  308. ValidateObj( m_selector );
  309. ValidateObj( m_parentSelectors );
  310. FOR_EACH_PTR_ARRAY( m_parentSelectors, i )
  311. {
  312. ValidateObj( m_parentSelectors[i] );
  313. }
  314. ValidatePtr( m_pProperties );
  315. // Don't validate individual properties, they are pooled and we validate the pools elsewhere. Do have
  316. // them validate their own members.
  317. FOR_EACH_MAP_FAST( *m_pProperties, i )
  318. {
  319. m_pProperties->Element( i )->Validate( validator, "CStyleProperty" );
  320. }
  321. if( m_pNext )
  322. ValidatePtr( m_pNext );
  323. }
  324. #endif
  325. CStyleSelector m_selector; // selector for this element
  326. CUtlPtrArray< CStyleSelector > m_parentSelectors; // selectors for parents, ordered farthest to our closest parent
  327. StylePropertyHash_t *m_pProperties; // list of parsed properties
  328. uint m_unFileLocation; // style offset into the file (Nth style, higher value means defined later and takes priority when determining
  329. // cascading order (CSS2 TR 6.4.1)
  330. StyleFromFile_t *m_pNext; // allows chaining of objects with the same same symbol in CStyleFile
  331. };
  332. //-----------------------------------------------------------------------------
  333. // Purpose: Represents a single keyframe
  334. //-----------------------------------------------------------------------------
  335. class CStyleKeyFrame
  336. {
  337. public:
  338. CStyleKeyFrame( float flPercent, EAnimationTimingFunction eTimingFunc, const CCubicBezierCurve<Vector2D> &cubicBezier, StylePropertyHash_t *pProperties )
  339. {
  340. m_flPercent = flPercent;
  341. m_eTimingFunction = eTimingFunc;
  342. m_CubicBezier = cubicBezier;
  343. m_pProperties = pProperties;
  344. }
  345. ~CStyleKeyFrame()
  346. {
  347. if( m_pProperties )
  348. {
  349. FOR_EACH_HASHMAP( *m_pProperties, i )
  350. {
  351. CStyleProperty *pProperty = m_pProperties->Element( i );
  352. if( pProperty )
  353. UIEngine()->UIStyleFactory()->FreeStyleProperty( pProperty );
  354. }
  355. SAFE_DELETE( m_pProperties );
  356. }
  357. }
  358. float GetPercent() const { return m_flPercent; }
  359. EAnimationTimingFunction GetTimingFunction() const { return m_eTimingFunction; }
  360. const CCubicBezierCurve< Vector2D >& GetCubicBezier() const { return m_CubicBezier; }
  361. StylePropertyHash_t *GetProperties() const { return m_pProperties; }
  362. // ordered by percent
  363. bool operator<(const CStyleKeyFrame &rhs) const { return m_flPercent < rhs.m_flPercent; }
  364. #ifdef DBGFLAG_VALIDATE
  365. void Validate( CValidator &validator, const tchar *pchName )
  366. {
  367. VALIDATE_SCOPE();
  368. ValidatePtr( m_pProperties );
  369. // Don't validate each individual property, they are pooled and the pool is validated elsewhere
  370. FOR_EACH_MAP_FAST( *m_pProperties, i )
  371. {
  372. (*m_pProperties)[i]->Validate( validator, "CStyleProperty" );
  373. }
  374. }
  375. #endif
  376. private:
  377. CStyleKeyFrame();
  378. CStyleKeyFrame( const CStyleKeyFrame &rhs );
  379. CStyleKeyFrame& operator=(const CStyleKeyFrame &rhs) const;
  380. float m_flPercent;
  381. EAnimationTimingFunction m_eTimingFunction; // each keyframe can override the timing funciton
  382. CCubicBezierCurve<Vector2D> m_CubicBezier;
  383. StylePropertyHash_t *m_pProperties;
  384. };
  385. typedef CStyleKeyFrame* CStyleKeyFramePtr;
  386. bool StyleKeyFrameLessPtr( const CStyleKeyFramePtr &lhs, const CStyleKeyFramePtr &rhs, void *pCtx );
  387. #if defined( SOURCE2_PANORAMA )
  388. class CUtlSortVectorCStyleKeyFramePtrLess
  389. {
  390. public:
  391. bool Less( const CStyleKeyFramePtr& lhs, const CStyleKeyFramePtr& rhs, void * )
  392. {
  393. return *lhs < *rhs;
  394. }
  395. };
  396. typedef CUtlSortVector< CStyleKeyFrame*, CUtlSortVectorCStyleKeyFramePtrLess > VecKeyFrames_t;
  397. #else
  398. typedef CUtlSortVector< CStyleKeyFrame* > VecKeyFrames_t;
  399. #endif
  400. //-----------------------------------------------------------------------------
  401. // Purpose: Represents an animation
  402. //-----------------------------------------------------------------------------
  403. class CStyleAnimation
  404. {
  405. public:
  406. CStyleAnimation( CPanoramaSymbol symName, CPanoramaSymbol symStyleFile, uint unFileLocation )
  407. #if !defined( SOURCE2_PANORAMA )
  408. : m_vecKeyFrames( StyleKeyFrameLessPtr )
  409. #endif
  410. {
  411. m_symName = symName;
  412. m_symStyleFile = symStyleFile;
  413. m_unFileLocation = unFileLocation;
  414. }
  415. ~CStyleAnimation()
  416. {
  417. ClearFrames();
  418. }
  419. void ClearFrames()
  420. {
  421. m_vecKeyFrames.PurgeAndDeleteElements();
  422. }
  423. void InsertFrame( CStyleKeyFrame *pFrame )
  424. {
  425. int iVec = m_vecKeyFrames.Find( pFrame );
  426. if( iVec != m_vecKeyFrames.InvalidIndex() )
  427. {
  428. delete m_vecKeyFrames.Element( iVec );
  429. m_vecKeyFrames.Remove( iVec );
  430. }
  431. m_vecKeyFrames.Insert( pFrame );
  432. }
  433. CPanoramaSymbol GetName() const { return m_symName; }
  434. CPanoramaSymbol GetStyleFile() const { return m_symStyleFile; }
  435. uint GetFileLocation() const { return m_unFileLocation; }
  436. const VecKeyFrames_t &GetFrames() const { return m_vecKeyFrames; }
  437. #ifdef DBGFLAG_VALIDATE
  438. void Validate( CValidator &validator, const tchar *pchName )
  439. {
  440. VALIDATE_SCOPE();
  441. ValidateObj( m_vecKeyFrames );
  442. FOR_EACH_VEC( m_vecKeyFrames, i )
  443. {
  444. ValidatePtr( m_vecKeyFrames[i] );
  445. }
  446. }
  447. #endif
  448. private:
  449. CStyleAnimation();
  450. CStyleAnimation( const CStyleAnimation &rhs );
  451. CStyleAnimation& operator=(const CStyleAnimation &rhs) const;
  452. CPanoramaSymbol m_symName; // name of animation
  453. CPanoramaSymbol m_symStyleFile; // path to style file this animation was created from
  454. uint m_unFileLocation; // location within style file for this animation
  455. VecKeyFrames_t m_vecKeyFrames; // frames for animation
  456. };
  457. //-----------------------------------------------------------------------------
  458. // Purpose: Position property
  459. //-----------------------------------------------------------------------------
  460. class CStylePropertyPosition : public CStyleProperty
  461. {
  462. public:
  463. static const CStyleSymbol symbol;
  464. static const CStyleSymbol symbolX;
  465. static const CStyleSymbol symbolY;
  466. static const CStyleSymbol symbolZ;
  467. CStylePropertyPosition() : CStyleProperty( CStylePropertyPosition::symbol )
  468. {
  469. }
  470. virtual void MergeTo( CStyleProperty *pTarget ) const
  471. {
  472. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  473. {
  474. AssertMsg( false, "Mismatched types to CStylePropertyPosition::MergeTo" );
  475. return;
  476. }
  477. CStyleProperty::MergeTo( pTarget );
  478. CStylePropertyPosition *p = (CStylePropertyPosition *)pTarget;
  479. if( !p->x.IsSet() )
  480. p->x = x;
  481. if( !p->y.IsSet() )
  482. p->y = y;
  483. if( !p->z.IsSet() )
  484. p->z = z;
  485. }
  486. // Can this property support animation?
  487. virtual bool BCanTransition() { return true; }
  488. // Interpolation func for animation of this property
  489. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  490. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  491. virtual bool BAffectsCompositionOnly() { return true; }
  492. // Parses string and sets value
  493. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  494. {
  495. bool bSuccess = false;
  496. if( symParsedName == symbol )
  497. {
  498. bSuccess = CSSHelpers::BParseIntoUILength( &x, pchString, &pchString ) &&
  499. CSSHelpers::BParseIntoUILength( &y, pchString, &pchString ) &&
  500. CSSHelpers::BParseIntoUILength( &z, pchString, &pchString );
  501. }
  502. else if( symParsedName == symbolX )
  503. {
  504. bSuccess = CSSHelpers::BParseIntoUILength( &x, pchString, &pchString );
  505. }
  506. else if( symParsedName == symbolY )
  507. {
  508. bSuccess = CSSHelpers::BParseIntoUILength( &y, pchString, &pchString );
  509. }
  510. else if( symParsedName == symbolZ )
  511. {
  512. bSuccess = CSSHelpers::BParseIntoUILength( &z, pchString, &pchString );
  513. }
  514. return bSuccess;
  515. }
  516. // called when we are ready to apply any scaling factor to the values
  517. virtual void ApplyUIScaleFactor( float flScaleFactor )
  518. {
  519. x.ScaleLengthValue( flScaleFactor );
  520. y.ScaleLengthValue( flScaleFactor );
  521. z.ScaleLengthValue( flScaleFactor );
  522. }
  523. // Gets string representation of property
  524. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  525. {
  526. CSSHelpers::AppendUILength( pfmtBuffer, x );
  527. pfmtBuffer->Append( " " );
  528. CSSHelpers::AppendUILength( pfmtBuffer, y );
  529. pfmtBuffer->Append( " " );
  530. CSSHelpers::AppendUILength( pfmtBuffer, z );
  531. }
  532. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found by looking at lower weight styles
  533. virtual bool BFullySet()
  534. {
  535. return (x.IsSet() && y.IsSet() && z.IsSet());
  536. }
  537. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  538. virtual void ResolveDefaultValues()
  539. {
  540. if( !x.IsSet() )
  541. x.SetLength( 0.0f );
  542. if( !y.IsSet() )
  543. y.SetLength( 0.0f );
  544. if( !z.IsSet() )
  545. z.SetLength( 0.0f );
  546. }
  547. // Return a description for this property which will be shown in the debugger
  548. virtual const char *GetDescription( CStyleSymbol symProperty )
  549. {
  550. return "Sets the x, y, z position for a panel. Must not be in a flowing layout.<br><br>"
  551. "<b>Example:</b>"
  552. "<pre>"
  553. "position: 3% 20px 0px;"
  554. "</pre>";
  555. }
  556. // Comparison function
  557. virtual bool operator==(const CStyleProperty &other) const
  558. {
  559. if( GetPropertySymbol() != other.GetPropertySymbol() )
  560. return false;
  561. const CStylePropertyPosition &rhs = (const CStylePropertyPosition&)other;
  562. return (x == rhs.x && y == rhs.y && z == rhs.z);
  563. }
  564. // Layout pieces that can be invalidated when the property is applied to a panel
  565. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  566. {
  567. return k_EStyleInvalidateLayoutNone;
  568. }
  569. CUILength x, y, z;
  570. };
  571. //-----------------------------------------------------------------------------
  572. // Purpose: PerspectiveOrigin property
  573. //-----------------------------------------------------------------------------
  574. class CStylePropertyTransformOrigin : public CStyleProperty
  575. {
  576. public:
  577. static const CStyleSymbol symbol;
  578. static inline void GetDefault( CUILength *x, CUILength *y, bool *pbParent )
  579. {
  580. x->SetPercent( 50 );
  581. y->SetPercent( 50 );
  582. *pbParent = false;
  583. }
  584. CStylePropertyTransformOrigin() : CStyleProperty( CStylePropertyTransformOrigin::symbol )
  585. {
  586. GetDefault( &x, &y, &m_bParentRelative );
  587. }
  588. virtual void MergeTo( CStyleProperty *pTarget ) const
  589. {
  590. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  591. {
  592. AssertMsg( false, "Mismatched types to CStylePropertyTransformOrigin::MergeTo" );
  593. return;
  594. }
  595. CStyleProperty::MergeTo( pTarget );
  596. CStylePropertyTransformOrigin *p = (CStylePropertyTransformOrigin *)pTarget;
  597. p->x = x;
  598. p->y = y;
  599. p->m_bParentRelative = m_bParentRelative;
  600. }
  601. // Can this property support animation?
  602. virtual bool BCanTransition() { return true; }
  603. // Interpolation func for animation of this property
  604. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  605. // Parses string and sets value
  606. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  607. {
  608. bool bSuccess = (CSSHelpers::BParseIntoUILength( &x, pchString, &pchString ) && CSSHelpers::BParseIntoUILength( &y, pchString, &pchString ));
  609. pchString = CSSHelpers::SkipSpaces( pchString );
  610. if( V_strnicmp( pchString, "parent-relative", V_strlen( "parent-relative" ) ) == 0 )
  611. m_bParentRelative = true;
  612. else if( V_strlen( pchString ) > 0 )
  613. return false;
  614. return bSuccess;
  615. }
  616. // called when we are ready to apply any scaling factor to the values
  617. virtual void ApplyUIScaleFactor( float flScaleFactor )
  618. {
  619. x.ScaleLengthValue( flScaleFactor );
  620. y.ScaleLengthValue( flScaleFactor );
  621. }
  622. // Gets string representation of property
  623. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  624. {
  625. CSSHelpers::AppendUILength( pfmtBuffer, x );
  626. pfmtBuffer->Append( " " );
  627. CSSHelpers::AppendUILength( pfmtBuffer, y );
  628. if( m_bParentRelative )
  629. pfmtBuffer->Append( " parent-relative" );
  630. }
  631. // Return a description for this property which will be shown in the debugger
  632. virtual const char *GetDescription( CStyleSymbol symProperty )
  633. {
  634. return "Sets the transform origin about which transforms will be applied. Default is 50% 50% on the panel so a rotation/scale is centered.<br><br>"
  635. "<b>Example:</b>"
  636. "<pre>"
  637. "transform-origin: 50% 50%"
  638. "</pre>";
  639. }
  640. // Comparison function
  641. virtual bool operator==(const CStyleProperty &other) const
  642. {
  643. if( GetPropertySymbol() != other.GetPropertySymbol() )
  644. return false;
  645. const CStylePropertyTransformOrigin &rhs = (const CStylePropertyTransformOrigin&)other;
  646. return (x == rhs.x && y == rhs.y && m_bParentRelative == rhs.m_bParentRelative);
  647. }
  648. // Layout pieces that can be invalidated when the property is applied to a panel
  649. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  650. CUILength x;
  651. CUILength y;
  652. bool m_bParentRelative;
  653. };
  654. //-----------------------------------------------------------------------------
  655. // Purpose: PerspectiveOrigin property
  656. //-----------------------------------------------------------------------------
  657. class CStylePropertyPerspectiveOrigin : public CStyleProperty
  658. {
  659. public:
  660. static const CStyleSymbol symbol;
  661. static inline void GetDefault( CUILength *x, CUILength *y, bool *pbInvert )
  662. {
  663. x->SetPercent( 50 );
  664. y->SetPercent( 50 );
  665. *pbInvert = false;
  666. }
  667. CStylePropertyPerspectiveOrigin() : CStyleProperty( CStylePropertyPerspectiveOrigin::symbol )
  668. {
  669. GetDefault( &x, &y, &m_bInvert );
  670. }
  671. virtual void MergeTo( CStyleProperty *pTarget ) const
  672. {
  673. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  674. {
  675. AssertMsg( false, "Mismatched types to CStylePropertyPerspectiveOrigin::MergeTo" );
  676. return;
  677. }
  678. CStyleProperty::MergeTo( pTarget );
  679. CStylePropertyPerspectiveOrigin *p = (CStylePropertyPerspectiveOrigin *)pTarget;
  680. p->x = x;
  681. p->y = y;
  682. p->m_bInvert = m_bInvert;
  683. }
  684. // Can this property support animation?
  685. virtual bool BCanTransition() { return true; }
  686. // Interpolation func for animation of this property
  687. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  688. // Parses string and sets value
  689. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  690. {
  691. bool bSuccess = (CSSHelpers::BParseIntoUILength( &x, pchString, &pchString ) && CSSHelpers::BParseIntoUILength( &y, pchString, &pchString ));
  692. pchString = CSSHelpers::SkipSpaces( pchString );
  693. if( V_strnicmp( pchString, "invert", V_strlen( "invert" ) ) == 0 )
  694. m_bInvert = true;
  695. else if( V_strlen( pchString ) > 0 )
  696. return false;
  697. return bSuccess;
  698. }
  699. // called when we are ready to apply any scaling factor to the values
  700. virtual void ApplyUIScaleFactor( float flScaleFactor )
  701. {
  702. x.ScaleLengthValue( flScaleFactor );
  703. y.ScaleLengthValue( flScaleFactor );
  704. }
  705. // Handle getting applied to a panel
  706. virtual void OnAppliedToPanel( IUIPanel *pPanel )
  707. {
  708. }
  709. // Gets string representation of property
  710. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  711. {
  712. CSSHelpers::AppendUILength( pfmtBuffer, x );
  713. pfmtBuffer->Append( " " );
  714. CSSHelpers::AppendUILength( pfmtBuffer, y );
  715. if( m_bInvert )
  716. pfmtBuffer->Append( " invert" );
  717. }
  718. // Return a description for this property which will be shown in the debugger
  719. virtual const char *GetDescription( CStyleSymbol symProperty )
  720. {
  721. return "Sets the perspective origin which will be used when transforming children of this panel. This can be "
  722. "thought of as the camera x/y position relative to the panel.<br><br>"
  723. "<b>Example:</b>"
  724. "<pre>"
  725. "perspective-origin: 50% 50%;"
  726. "</pre>";
  727. }
  728. // Comparison function
  729. virtual bool operator==(const CStyleProperty &other) const
  730. {
  731. if( GetPropertySymbol() != other.GetPropertySymbol() )
  732. return false;
  733. const CStylePropertyPerspectiveOrigin &rhs = (const CStylePropertyPerspectiveOrigin&)other;
  734. return (x == rhs.x && y == rhs.y && m_bInvert == rhs.m_bInvert);
  735. }
  736. // Layout pieces that can be invalidated when the property is applied to a panel
  737. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  738. bool m_bInvert;
  739. CUILength x;
  740. CUILength y;
  741. };
  742. //-----------------------------------------------------------------------------
  743. // Purpose: Perspective property
  744. //-----------------------------------------------------------------------------
  745. class CStylePropertyPerspective : public CStyleProperty
  746. {
  747. public:
  748. static const CStyleSymbol symbol;
  749. static inline float GetDefault() { return 1000.0f; }
  750. CStylePropertyPerspective() : CStyleProperty( CStylePropertyPerspective::symbol )
  751. {
  752. perspective = GetDefault();
  753. }
  754. virtual void MergeTo( CStyleProperty *pTarget ) const
  755. {
  756. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  757. {
  758. AssertMsg( false, "Mismatched types to CStylePropertyPerspective::MergeTo" );
  759. return;
  760. }
  761. CStyleProperty::MergeTo( pTarget );
  762. CStylePropertyPerspective *p = (CStylePropertyPerspective *)pTarget;
  763. p->perspective = perspective;
  764. }
  765. virtual void ApplyUIScaleFactor( float flScaleFactor )
  766. {
  767. perspective *= flScaleFactor;
  768. }
  769. // Can this property support animation?
  770. virtual bool BCanTransition() { return true; }
  771. // Interpolation func for animation of this property
  772. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  773. {
  774. if( target.GetPropertySymbol() != GetPropertySymbol() )
  775. {
  776. AssertMsg( false, "Mismatched types to CStylePropertyPerspective::Interpolate" );
  777. return;
  778. }
  779. const CStylePropertyPerspective *p = (const CStylePropertyPerspective *)&target;
  780. perspective = perspective + (p->perspective - perspective) * flProgress;
  781. }
  782. // Parses string and sets value
  783. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  784. {
  785. if( !CSSHelpers::BParseNumber( &perspective, pchString ) )
  786. {
  787. return CSSHelpers::BParseLength( &perspective, pchString );
  788. }
  789. return true;
  790. }
  791. // Gets string representation of property
  792. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  793. {
  794. CSSHelpers::AppendFloat( pfmtBuffer, perspective );
  795. }
  796. // Return a description for this property which will be shown in the debugger
  797. virtual const char *GetDescription( CStyleSymbol symProperty )
  798. {
  799. return "Sets the perspective depth space available for children of the panel. Default of 1000 would mean that "
  800. "children at 1000px zpos are right at the viewers eye, -1000px are just out of view distance faded to nothing.<br><br>"
  801. "<b>Example:</b>"
  802. "<pre>"
  803. "perspective: 1000;"
  804. "</pre>";
  805. }
  806. // Comparison function
  807. virtual bool operator==(const CStyleProperty &other) const
  808. {
  809. if( GetPropertySymbol() != other.GetPropertySymbol() )
  810. return false;
  811. const CStylePropertyPerspective &rhs = (const CStylePropertyPerspective&)other;
  812. return (perspective == rhs.perspective);
  813. }
  814. // Layout pieces that can be invalidated when the property is applied to a panel
  815. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  816. float perspective;
  817. };
  818. //-----------------------------------------------------------------------------
  819. // Purpose: z-index, this determines z sorting within panels that are peers with indentical actual zpos
  820. //-----------------------------------------------------------------------------
  821. class CStylePropertyZIndex : public CStyleProperty
  822. {
  823. public:
  824. static const CStyleSymbol symbol;
  825. static inline float GetDefault() { return 0.0f; }
  826. CStylePropertyZIndex() : CStyleProperty( CStylePropertyZIndex::symbol )
  827. {
  828. zindex = GetDefault();
  829. }
  830. virtual void MergeTo( CStyleProperty *pTarget ) const
  831. {
  832. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  833. {
  834. AssertMsg( false, "Mismatched types to CStylePropertyZIndex::MergeTo" );
  835. return;
  836. }
  837. CStyleProperty::MergeTo( pTarget );
  838. CStylePropertyZIndex *p = (CStylePropertyZIndex *)pTarget;
  839. p->zindex = zindex;
  840. }
  841. // Can this property support animation?
  842. virtual bool BCanTransition() { return true; }
  843. // Interpolation func for animation of this property
  844. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  845. {
  846. if( target.GetPropertySymbol() != GetPropertySymbol() )
  847. {
  848. AssertMsg( false, "Mismatched types to CStylePropertyZIndex::Interpolate" );
  849. return;
  850. }
  851. const CStylePropertyZIndex *p = (const CStylePropertyZIndex *)&target;
  852. zindex = zindex + (p->zindex - zindex) * flProgress;
  853. }
  854. // Parses string and sets value
  855. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  856. {
  857. if( !CSSHelpers::BParseNumber( &zindex, pchString ) )
  858. {
  859. return false;
  860. }
  861. return true;
  862. }
  863. // Gets string representation of property
  864. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  865. {
  866. CSSHelpers::AppendFloat( pfmtBuffer, zindex );
  867. }
  868. // Return a description for this property which will be shown in the debugger
  869. virtual const char *GetDescription( CStyleSymbol symProperty )
  870. {
  871. return "Sets the z-index for a panel, panels will be sorted and painted in order within a parent panel. The sorting "
  872. "first sorts by the z-pos computed from position and transforms, then if panels have matching zpos zindex is used. "
  873. "z-index is different than z-pos in that it doesn't affect rendering perspective, just paint/hit-test ordering. "
  874. "The default z-index value is 0, and any floating point value is accepted.<br><br>"
  875. "<b>Example:</b>"
  876. "<pre>"
  877. "z-index: 1;"
  878. "</pre>";
  879. }
  880. // Comparison function
  881. virtual bool operator==(const CStyleProperty &other) const
  882. {
  883. if( GetPropertySymbol() != other.GetPropertySymbol() )
  884. return false;
  885. const CStylePropertyZIndex &rhs = (const CStylePropertyZIndex&)other;
  886. return (zindex == rhs.zindex);
  887. }
  888. // Layout pieces that can be invalidated when the property is applied to a panel
  889. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  890. float zindex;
  891. };
  892. //-----------------------------------------------------------------------------
  893. // Purpose: Perspective property
  894. //-----------------------------------------------------------------------------
  895. class CStylePropertyOpacity : public CStyleProperty
  896. {
  897. public:
  898. static const CStyleSymbol symbol;
  899. static inline float GetDefault() { return 1.0f; }
  900. CStylePropertyOpacity() : CStyleProperty( CStylePropertyOpacity::symbol )
  901. {
  902. opacity = GetDefault();
  903. }
  904. virtual void MergeTo( CStyleProperty *pTarget ) const
  905. {
  906. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  907. {
  908. AssertMsg( false, "Mismatched types to CStylePropertyOpacity::MergeTo" );
  909. return;
  910. }
  911. CStyleProperty::MergeTo( pTarget );
  912. CStylePropertyOpacity *p = (CStylePropertyOpacity *)pTarget;
  913. p->opacity = opacity;
  914. }
  915. // Can this property support animation?
  916. virtual bool BCanTransition() { return true; }
  917. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  918. virtual bool BAffectsCompositionOnly() { return true; }
  919. // Interpolation func for animation of this property
  920. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  921. {
  922. if( target.GetPropertySymbol() != GetPropertySymbol() )
  923. {
  924. AssertMsg( false, "Mismatched types to CStylePropertyOpacity::Interpolate" );
  925. return;
  926. }
  927. const CStylePropertyOpacity *p = (const CStylePropertyOpacity *)&target;
  928. opacity = opacity + (p->opacity - opacity) * flProgress;
  929. }
  930. // Parses string and sets value
  931. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  932. {
  933. return (CSSHelpers::BParseNumber( &opacity, pchString, &pchString ));
  934. }
  935. // Gets string representation of property
  936. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  937. {
  938. CSSHelpers::AppendFloat( pfmtBuffer, opacity );
  939. }
  940. // Return a description for this property which will be shown in the debugger
  941. virtual const char *GetDescription( CStyleSymbol symProperty )
  942. {
  943. return "Sets the opacity or amount of transparency applied to the panel and all it's children during composition. "
  944. "Default of 1.0 means fully opaque, 0.0 means fully transparent.<br><br>"
  945. "<b>Example:</b>"
  946. "<pre>"
  947. "opacity: 0.8;"
  948. "</pre>";
  949. }
  950. // Comparison function
  951. virtual bool operator==(const CStyleProperty &other) const
  952. {
  953. if( GetPropertySymbol() != other.GetPropertySymbol() )
  954. return false;
  955. const CStylePropertyOpacity &rhs = (const CStylePropertyOpacity&)other;
  956. return (opacity == rhs.opacity);
  957. }
  958. // Layout pieces that can be invalidated when the property is applied to a panel
  959. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  960. {
  961. return k_EStyleInvalidateLayoutNone;
  962. }
  963. float opacity;
  964. };
  965. //-----------------------------------------------------------------------------
  966. // Purpose: scale-2d-centered property
  967. //-----------------------------------------------------------------------------
  968. class CStylePropertyScale2DCentered : public CStyleProperty
  969. {
  970. public:
  971. static const CStyleSymbol symbol;
  972. static inline float GetDefaultX() { return 1.0f; }
  973. static inline float GetDefaultY() { return 1.0f; }
  974. CStylePropertyScale2DCentered() : CStyleProperty( CStylePropertyScale2DCentered::symbol )
  975. {
  976. m_flX = GetDefaultX();
  977. m_flY = GetDefaultY();
  978. }
  979. virtual void MergeTo( CStyleProperty *pTarget ) const
  980. {
  981. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  982. {
  983. AssertMsg( false, "Mismatched types to CStylePropertyScale2DCentered::MergeTo" );
  984. return;
  985. }
  986. CStyleProperty::MergeTo( pTarget );
  987. CStylePropertyScale2DCentered *p = (CStylePropertyScale2DCentered *)pTarget;
  988. p->m_flX = m_flX;
  989. p->m_flY = m_flY;
  990. }
  991. // Can this property support animation?
  992. virtual bool BCanTransition() { return true; }
  993. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  994. virtual bool BAffectsCompositionOnly() { return true; }
  995. // Interpolation func for animation of this property
  996. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  997. {
  998. if( target.GetPropertySymbol() != GetPropertySymbol() )
  999. {
  1000. AssertMsg( false, "Mismatched types to CStylePropertyScale2DCentered::Interpolate" );
  1001. return;
  1002. }
  1003. const CStylePropertyScale2DCentered *p = (const CStylePropertyScale2DCentered *)&target;
  1004. m_flX = m_flX + (p->m_flX - m_flX) * flProgress;
  1005. m_flY = m_flY + (p->m_flY - m_flY) * flProgress;
  1006. }
  1007. // Parses string and sets value
  1008. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1009. {
  1010. // should be "x, y"
  1011. CUtlVector< float > vecValues;
  1012. if( !CSSHelpers::BParseCommaSepList( &vecValues, CSSHelpers::BParseNumber, pchString ) )
  1013. return false;
  1014. if( vecValues.Count() < 1 || vecValues.Count() > 2 )
  1015. return false;
  1016. if( vecValues.Count() == 2 )
  1017. {
  1018. m_flX = vecValues[0];
  1019. m_flY = vecValues[1];
  1020. }
  1021. else if( vecValues.Count() == 1 )
  1022. {
  1023. m_flX = m_flY = vecValues[0];
  1024. }
  1025. return true;
  1026. }
  1027. // Gets string representation of property
  1028. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1029. {
  1030. CSSHelpers::AppendFloat( pfmtBuffer, m_flX );
  1031. pfmtBuffer->Append( ", " );
  1032. CSSHelpers::AppendFloat( pfmtBuffer, m_flY );
  1033. }
  1034. // Return a description for this property which will be shown in the debugger
  1035. virtual const char *GetDescription( CStyleSymbol symProperty )
  1036. {
  1037. return "Sets 2 dimensional X/Y scale factors that apply to the quad for this panel prior to 3 dimensional transforms. "
  1038. "This scaling applies without perspective and leaves the panel centered at the same spot as it started. "
  1039. "Default of 1.0 means no scaling, 0.5 would be half size.<br><br>"
  1040. "<b>Examples:</b>"
  1041. "<pre>"
  1042. "pre-transform-scale2d: 0.8\n"
  1043. "pre-transform-scale2d: 0.4, 0.6"
  1044. "</pre>";
  1045. }
  1046. // Comparison function
  1047. virtual bool operator==(const CStyleProperty &other) const
  1048. {
  1049. if( GetPropertySymbol() != other.GetPropertySymbol() )
  1050. return false;
  1051. const CStylePropertyScale2DCentered &rhs = (const CStylePropertyScale2DCentered&)other;
  1052. return (m_flX == rhs.m_flX && m_flY == rhs.m_flY);
  1053. }
  1054. // Layout pieces that can be invalidated when the property is applied to a panel
  1055. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  1056. float m_flX, m_flY;
  1057. };
  1058. //-----------------------------------------------------------------------------
  1059. // Purpose: pre-transform-rotate2d property
  1060. //-----------------------------------------------------------------------------
  1061. class CStylePropertyRotate2DCentered : public CStyleProperty
  1062. {
  1063. public:
  1064. static const CStyleSymbol symbol;
  1065. static inline float GetDefault() { return 0.0f; }
  1066. CStylePropertyRotate2DCentered() : CStyleProperty( CStylePropertyRotate2DCentered::symbol )
  1067. {
  1068. m_flDegrees = GetDefault();
  1069. }
  1070. virtual void MergeTo( CStyleProperty *pTarget ) const
  1071. {
  1072. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1073. {
  1074. AssertMsg( false, "Mismatched types to CStylePropertyRotate2DCentered::MergeTo" );
  1075. return;
  1076. }
  1077. CStyleProperty::MergeTo( pTarget );
  1078. CStylePropertyRotate2DCentered *p = (CStylePropertyRotate2DCentered *)pTarget;
  1079. p->m_flDegrees = m_flDegrees;
  1080. }
  1081. // Can this property support animation?
  1082. virtual bool BCanTransition() { return true; }
  1083. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  1084. virtual bool BAffectsCompositionOnly() { return true; }
  1085. // Interpolation func for animation of this property
  1086. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  1087. {
  1088. if( target.GetPropertySymbol() != GetPropertySymbol() )
  1089. {
  1090. AssertMsg( false, "Mismatched types to CStylePropertyScale2DCentered::Interpolate" );
  1091. return;
  1092. }
  1093. const CStylePropertyRotate2DCentered *p = (const CStylePropertyRotate2DCentered *)&target;
  1094. m_flDegrees = m_flDegrees + (p->m_flDegrees - m_flDegrees) * flProgress;
  1095. }
  1096. // Parses string and sets value
  1097. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1098. {
  1099. // should be "degrees"
  1100. CUtlVector< float > vecValues;
  1101. if( !CSSHelpers::BParseCommaSepList( &vecValues, CSSHelpers::BParseAngle, pchString ) )
  1102. return false;
  1103. if( vecValues.Count() < 1 || vecValues.Count() > 1 )
  1104. return false;
  1105. m_flDegrees = vecValues[0];
  1106. return true;
  1107. }
  1108. // Gets string representation of property
  1109. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1110. {
  1111. CSSHelpers::AppendFloat( pfmtBuffer, m_flDegrees );
  1112. }
  1113. // Return a description for this property which will be shown in the debugger
  1114. virtual const char *GetDescription( CStyleSymbol symProperty )
  1115. {
  1116. return "Sets 2 dimensional rotation degrees that apply to the quad for this panel prior to 3 dimensional transforms. "
  1117. "This rotation applies without perspective and leaves the panel centered at the same spot as it started.<br><br>"
  1118. "<b>Example:</b>"
  1119. "<pre>"
  1120. "pre-transform-rotate2d: 45deg;"
  1121. "</pre>";
  1122. }
  1123. // Comparison function
  1124. virtual bool operator==(const CStyleProperty &other) const
  1125. {
  1126. if( GetPropertySymbol() != other.GetPropertySymbol() )
  1127. return false;
  1128. const CStylePropertyRotate2DCentered &rhs = (const CStylePropertyRotate2DCentered&)other;
  1129. return (m_flDegrees == rhs.m_flDegrees);
  1130. }
  1131. // Layout pieces that can be invalidated when the property is applied to a panel
  1132. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  1133. float m_flDegrees;
  1134. };
  1135. //-----------------------------------------------------------------------------
  1136. // Purpose: Perspective property
  1137. //-----------------------------------------------------------------------------
  1138. class CStylePropertyDesaturation : public CStyleProperty
  1139. {
  1140. public:
  1141. static const CStyleSymbol symbol;
  1142. static inline double GetDefault() { return 0.0f; }
  1143. CStylePropertyDesaturation() : CStyleProperty( CStylePropertyDesaturation::symbol )
  1144. {
  1145. desaturation = GetDefault();
  1146. }
  1147. virtual void MergeTo( CStyleProperty *pTarget ) const
  1148. {
  1149. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1150. {
  1151. AssertMsg( false, "Mismatched types to CStylePropertyDesaturation::MergeTo" );
  1152. return;
  1153. }
  1154. CStyleProperty::MergeTo( pTarget );
  1155. CStylePropertyDesaturation *p = (CStylePropertyDesaturation *)pTarget;
  1156. p->desaturation = desaturation;
  1157. }
  1158. // Can this property support animation?
  1159. virtual bool BCanTransition() { return true; }
  1160. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  1161. virtual bool BAffectsCompositionOnly() { return true; }
  1162. // Interpolation func for animation of this property
  1163. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  1164. {
  1165. if( target.GetPropertySymbol() != GetPropertySymbol() )
  1166. {
  1167. AssertMsg( false, "Mismatched types to CStylePropertyDesaturation::Interpolate" );
  1168. return;
  1169. }
  1170. const CStylePropertyDesaturation *p = (const CStylePropertyDesaturation *)&target;
  1171. desaturation = desaturation + (p->desaturation - desaturation) * flProgress;
  1172. }
  1173. // Parses string and sets value
  1174. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1175. {
  1176. if( V_strnicmp( pchString, "none", V_strlen( "none" ) ) == 0 )
  1177. {
  1178. desaturation = 0.0f;
  1179. return true;
  1180. }
  1181. return (CSSHelpers::BParseNumber( &desaturation, pchString, &pchString ));
  1182. }
  1183. // Gets string representation of property
  1184. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1185. {
  1186. CSSHelpers::AppendFloat( pfmtBuffer, desaturation );
  1187. }
  1188. // Return a description for this property which will be shown in the debugger
  1189. virtual const char *GetDescription( CStyleSymbol symProperty )
  1190. {
  1191. return "Sets the amount of desaturation to apply to the panel and all it's children during composition. "
  1192. "Default of 0.0 means no adjustment, 1.0 means fully desaturated to gray scale.<br><br>"
  1193. "<b>Example:</b>"
  1194. "<pre>"
  1195. "desaturation: 0.6;"
  1196. "</pre>";
  1197. }
  1198. // Comparison function
  1199. virtual bool operator==(const CStyleProperty &other) const
  1200. {
  1201. if( GetPropertySymbol() != other.GetPropertySymbol() )
  1202. return false;
  1203. const CStylePropertyDesaturation &rhs = (const CStylePropertyDesaturation&)other;
  1204. return (desaturation == rhs.desaturation);
  1205. }
  1206. // Layout pieces that can be invalidated when the property is applied to a panel
  1207. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  1208. float desaturation;
  1209. };
  1210. //-----------------------------------------------------------------------------
  1211. // Purpose: Perspective property
  1212. //-----------------------------------------------------------------------------
  1213. class CStylePropertyBlur : public CStyleProperty
  1214. {
  1215. public:
  1216. static const CStyleSymbol symbol;
  1217. static inline double GetDefaultStdDev() { return 0.0f; }
  1218. static inline double GetDefaultPasses() { return 1.0f; }
  1219. CStylePropertyBlur() : CStyleProperty( CStylePropertyBlur::symbol )
  1220. {
  1221. stddevhor = GetDefaultStdDev();
  1222. stddevver = GetDefaultStdDev();
  1223. passes = GetDefaultPasses();
  1224. }
  1225. virtual void MergeTo( CStyleProperty *pTarget ) const
  1226. {
  1227. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1228. {
  1229. AssertMsg( false, "Mismatched types to CStylePropertyBlur::MergeTo" );
  1230. return;
  1231. }
  1232. CStyleProperty::MergeTo( pTarget );
  1233. CStylePropertyBlur *p = (CStylePropertyBlur *)pTarget;
  1234. p->stddevhor = stddevhor;
  1235. p->stddevver = stddevver;
  1236. p->passes = passes;
  1237. }
  1238. // Can this property support animation?
  1239. virtual bool BCanTransition() { return true; }
  1240. // Interpolation func for animation of this property
  1241. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  1242. {
  1243. if( target.GetPropertySymbol() != GetPropertySymbol() )
  1244. {
  1245. AssertMsg( false, "Mismatched types to CStylePropertyBlur::Interpolate" );
  1246. return;
  1247. }
  1248. const CStylePropertyBlur *p = (const CStylePropertyBlur *)&target;
  1249. stddevhor = stddevhor + (p->stddevhor - stddevhor) * flProgress;
  1250. stddevver = stddevver + (p->stddevver - stddevver) * flProgress;
  1251. passes = passes + (p->passes - passes) * flProgress;
  1252. }
  1253. // Parses string and sets value
  1254. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1255. {
  1256. if( !CSSHelpers::BParseGaussianBlur( passes, stddevhor, stddevver, pchString, &pchString ) )
  1257. return false;
  1258. return true;
  1259. }
  1260. // Gets string representation of property
  1261. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1262. {
  1263. if( stddevhor == 0.0f && stddevver == 0.0f && passes == 0.0f )
  1264. {
  1265. pfmtBuffer->Append( "none" );
  1266. }
  1267. else
  1268. {
  1269. pfmtBuffer->Append( "gaussian( " );
  1270. CSSHelpers::AppendFloat( pfmtBuffer, stddevhor );
  1271. pfmtBuffer->Append( ", " );
  1272. CSSHelpers::AppendFloat( pfmtBuffer, stddevver );
  1273. pfmtBuffer->Append( ", " );
  1274. CSSHelpers::AppendFloat( pfmtBuffer, passes );
  1275. pfmtBuffer->Append( ")" );
  1276. }
  1277. }
  1278. // Return a description for this property which will be shown in the debugger
  1279. virtual const char *GetDescription( CStyleSymbol symProperty )
  1280. {
  1281. return "Sets the amount of blur to apply to the panel and all it's children during composition. "
  1282. "Default is no blur, for now Gaussian is the only blur type and takes a horizontal standard deviation, "
  1283. "vertical standard deviation, and number of passes. Good std deviation values are around 0-10, if 10 is "
  1284. "still not intense enough consider more passes, but more than one pass is bad for perf. As shorthand you can "
  1285. "specify with just one value, which will be used for the standard deviation in both directions and 1 pass "
  1286. "will be set.<br><br>"
  1287. "<b>Examples:</b>"
  1288. "<pre>"
  1289. "blur: gaussian( 2.5 );\n"
  1290. "blur: gaussian( 6, 6, 1 );"
  1291. "</pre>";
  1292. }
  1293. // Comparison function
  1294. virtual bool operator==(const CStyleProperty &other) const
  1295. {
  1296. if( GetPropertySymbol() != other.GetPropertySymbol() )
  1297. return false;
  1298. const CStylePropertyBlur &rhs = (const CStylePropertyBlur&)other;
  1299. return (stddevhor == rhs.stddevhor && stddevver == rhs.stddevver && passes == rhs.passes);
  1300. }
  1301. // Layout pieces that can be invalidated when the property is applied to a panel
  1302. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  1303. float stddevhor;
  1304. float stddevver;
  1305. float passes;
  1306. };
  1307. //-----------------------------------------------------------------------------
  1308. // Purpose: Box shadow property
  1309. //-----------------------------------------------------------------------------
  1310. class CStylePropertyBoxShadow : public CStyleProperty
  1311. {
  1312. public:
  1313. static const CStyleSymbol symbol;
  1314. static Color GetDefaultShadowColor() { return Color( 33, 33, 33, 80 ); }
  1315. CStylePropertyBoxShadow() : CStyleProperty( CStylePropertyBoxShadow::symbol )
  1316. {
  1317. m_bFill = false;
  1318. m_bInset = false;
  1319. m_ShadowColor = GetDefaultShadowColor();
  1320. m_HorizontalOffset.SetLength( 0 );
  1321. m_VerticalOffset.SetLength( 0 );
  1322. m_SpreadDistance.SetLength( 0 );
  1323. m_BlurRadius.SetLength( 0 );
  1324. }
  1325. virtual void MergeTo( CStyleProperty *pTarget ) const
  1326. {
  1327. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1328. {
  1329. AssertMsg( false, "Mismatched types to CStylePropertyBoxShadow::MergeTo" );
  1330. return;
  1331. }
  1332. CStyleProperty::MergeTo( pTarget );
  1333. CStylePropertyBoxShadow *p = (CStylePropertyBoxShadow *)pTarget;
  1334. p->m_bInset = m_bInset;
  1335. p->m_bFill = m_bFill;
  1336. p->m_HorizontalOffset = m_HorizontalOffset;
  1337. p->m_VerticalOffset = m_VerticalOffset;
  1338. p->m_SpreadDistance = m_SpreadDistance;
  1339. p->m_BlurRadius = m_BlurRadius;
  1340. p->m_ShadowColor = m_ShadowColor;
  1341. }
  1342. // Can this property support animation?
  1343. virtual bool BCanTransition() { return true; }
  1344. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  1345. virtual bool BAffectsCompositionOnly() { return true; }
  1346. // Interpolation func for animation of this property
  1347. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  1348. // Parses string and sets value
  1349. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1350. {
  1351. // <shadow> = inset? && [ <length>{2,4} && <color>? ]
  1352. // Browsers let color/inset appear before or after lengths, we will too.
  1353. if( V_strnicmp( pchString, "none", V_strlen( "none" ) ) == 0 )
  1354. {
  1355. m_bInset = false;
  1356. m_BlurRadius.SetLength( 0.0f );
  1357. m_HorizontalOffset.SetLength( 0.0f );
  1358. m_VerticalOffset.SetLength( 0.0f );
  1359. m_ShadowColor.SetColor( 0, 0, 0, 0 );
  1360. m_SpreadDistance.SetLength( 0.0f );
  1361. return true;
  1362. }
  1363. bool bInsetParsed = false;
  1364. bool bColorParsed = false;
  1365. bool bLengthsParsed = false;
  1366. bool bFillParsed = false;
  1367. while( 1 )
  1368. {
  1369. pchString = CSSHelpers::SkipSpaces( pchString );
  1370. if( !bInsetParsed && V_strnicmp( pchString, "inset", V_strlen( "inset" ) ) == 0 )
  1371. {
  1372. pchString += V_strlen( "inset" );
  1373. bInsetParsed = true;
  1374. m_bInset = true;
  1375. continue;
  1376. }
  1377. if( !bFillParsed && V_strnicmp( pchString, "fill", V_strlen( "fill" ) ) == 0 )
  1378. {
  1379. pchString += V_strlen( "fill" );
  1380. bFillParsed = true;
  1381. m_bFill = true;
  1382. continue;
  1383. }
  1384. else if( !bColorParsed && CSSHelpers::BParseColor( &m_ShadowColor, pchString, &pchString ) )
  1385. {
  1386. bColorParsed = true;
  1387. continue;
  1388. }
  1389. else if( !bLengthsParsed )
  1390. {
  1391. bLengthsParsed = true;
  1392. if( !CSSHelpers::BParseIntoUILength( &m_HorizontalOffset, pchString, &pchString ) )
  1393. {
  1394. return false;
  1395. }
  1396. if( !CSSHelpers::BParseIntoUILength( &m_VerticalOffset, pchString, &pchString ) )
  1397. {
  1398. return false;
  1399. }
  1400. // These two are optional
  1401. CSSHelpers::BParseIntoUILength( &m_BlurRadius, pchString, &pchString );
  1402. CSSHelpers::BParseIntoUILength( &m_SpreadDistance, pchString, &pchString );
  1403. }
  1404. else
  1405. {
  1406. // Lengths are the only thing required, if we get here and have them, we are good.
  1407. if( bLengthsParsed )
  1408. {
  1409. return true;
  1410. }
  1411. return false;
  1412. }
  1413. }
  1414. return true;
  1415. }
  1416. // called when we are ready to apply any scaling factor to the values
  1417. virtual void ApplyUIScaleFactor( float flScaleFactor )
  1418. {
  1419. m_HorizontalOffset.ScaleLengthValue( flScaleFactor );
  1420. m_VerticalOffset.ScaleLengthValue( flScaleFactor );
  1421. // Although this is a blur pixel radius in css terminology it's really a stddev for our gaussian blur internally,
  1422. // hence it should not scale.
  1423. //m_BlurRadius.ScaleLengthValue( flScaleFactor );
  1424. m_SpreadDistance.ScaleLengthValue( flScaleFactor );
  1425. }
  1426. // Gets string representation of property
  1427. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1428. {
  1429. if( m_bInset )
  1430. pfmtBuffer->Append( "inset " );
  1431. if( m_bFill )
  1432. pfmtBuffer->Append( "fill " );
  1433. CSSHelpers::AppendUILength( pfmtBuffer, m_HorizontalOffset );
  1434. pfmtBuffer->Append( " " );
  1435. CSSHelpers::AppendUILength( pfmtBuffer, m_VerticalOffset );
  1436. pfmtBuffer->Append( " " );
  1437. CSSHelpers::AppendUILength( pfmtBuffer, m_BlurRadius );
  1438. pfmtBuffer->Append( " " );
  1439. CSSHelpers::AppendUILength( pfmtBuffer, m_SpreadDistance );
  1440. pfmtBuffer->Append( " " );
  1441. CSSHelpers::AppendColor( pfmtBuffer, m_ShadowColor );
  1442. }
  1443. // Return a description for this property which will be shown in the debugger
  1444. virtual const char *GetDescription( CStyleSymbol symProperty )
  1445. {
  1446. return "Specifies outer shadows for boxes, or inset shadows/glows. The shadow shape will match the border box for the panel,"
  1447. "so use border-radius to affect rounding. Syntax takes optional 'inset', optional 'fill' then color, and then horizontal offset pixels, "
  1448. "vertical offset pixels, blur radius pixels, and spread distance in pixels. Inset means the shadow is an inner shadow/glow, fill is valid"
  1449. "only on outer shadows and means draw the shadow behind the entire box, not clipping it to outside the border area only.<br><br>"
  1450. "<b>Examples:</b>"
  1451. "<pre>"
  1452. "box-shadow: #ffffff80 4px 4px 8px 0px; // outer\n"
  1453. "box-shadow: fill #ffffff80 4px 4px 8px 0px; // outer, filled\n"
  1454. "box-shadow: inset #333333b0 0px 0px 8px 12px; // inner"
  1455. "</pre>";
  1456. }
  1457. // Comparison function
  1458. virtual bool operator==(const CStyleProperty &other) const
  1459. {
  1460. if( GetPropertySymbol() != other.GetPropertySymbol() )
  1461. return false;
  1462. const CStylePropertyBoxShadow &rhs = (const CStylePropertyBoxShadow&)other;
  1463. return (m_bFill == rhs.m_bFill && m_bInset == rhs.m_bInset && m_HorizontalOffset == rhs.m_HorizontalOffset &&
  1464. m_VerticalOffset == rhs.m_VerticalOffset && m_BlurRadius == rhs.m_BlurRadius && m_SpreadDistance == rhs.m_SpreadDistance &&
  1465. m_ShadowColor == rhs.m_ShadowColor);
  1466. }
  1467. // Layout pieces that can be invalidated when the property is applied to a panel
  1468. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  1469. bool m_bFill;
  1470. bool m_bInset;
  1471. CUILength m_HorizontalOffset;
  1472. CUILength m_VerticalOffset;
  1473. CUILength m_BlurRadius;
  1474. CUILength m_SpreadDistance;
  1475. Color m_ShadowColor;
  1476. };
  1477. //-----------------------------------------------------------------------------
  1478. // Purpose: Text shadow property
  1479. //-----------------------------------------------------------------------------
  1480. class CStylePropertyTextShadow : public CStyleProperty
  1481. {
  1482. public:
  1483. static const CStyleSymbol symbol;
  1484. static Color GetDefaultShadowColor() { return Color( 33, 33, 33, 80 ); }
  1485. CStylePropertyTextShadow() : CStyleProperty( CStylePropertyTextShadow::symbol )
  1486. {
  1487. m_ShadowColor = GetDefaultShadowColor();
  1488. m_HorizontalOffset.SetLength( 0 );
  1489. m_VerticalOffset.SetLength( 0 );
  1490. m_BlurRadius.SetLength( 0 );
  1491. m_flStrength = 1.0f;
  1492. }
  1493. virtual void MergeTo( CStyleProperty *pTarget ) const
  1494. {
  1495. if ( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1496. {
  1497. AssertMsg( false, "Mismatched types to CStylePropertyTextShadow::MergeTo" );
  1498. return;
  1499. }
  1500. CStyleProperty::MergeTo( pTarget );
  1501. CStylePropertyTextShadow *p = (CStylePropertyTextShadow *)pTarget;
  1502. p->m_HorizontalOffset = m_HorizontalOffset;
  1503. p->m_VerticalOffset = m_VerticalOffset;
  1504. p->m_BlurRadius = m_BlurRadius;
  1505. p->m_ShadowColor = m_ShadowColor;
  1506. p->m_flStrength = m_flStrength;
  1507. }
  1508. // Can this property support animation?
  1509. virtual bool BCanTransition() { return true; }
  1510. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  1511. virtual bool BAffectsCompositionOnly() { return false; }
  1512. // Interpolation func for animation of this property
  1513. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  1514. // Parses string and sets value
  1515. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1516. {
  1517. if ( V_strnicmp( pchString, "none", V_strlen( "none" ) ) == 0 )
  1518. {
  1519. m_BlurRadius.SetLength( 0.0f );
  1520. m_flStrength = 1.0f;
  1521. m_HorizontalOffset.SetLength( 0.0f );
  1522. m_VerticalOffset.SetLength( 0.0f );
  1523. m_ShadowColor.SetColor( 0, 0, 0, 0 );
  1524. return true;
  1525. }
  1526. bool bColorParsed = false;
  1527. bool bLengthsParsed = false;
  1528. while ( 1 )
  1529. {
  1530. pchString = CSSHelpers::SkipSpaces( pchString );
  1531. if ( !bColorParsed && CSSHelpers::BParseColor( &m_ShadowColor, pchString, &pchString ) )
  1532. {
  1533. bColorParsed = true;
  1534. continue;
  1535. }
  1536. else if ( !bLengthsParsed )
  1537. {
  1538. bLengthsParsed = true;
  1539. if ( !CSSHelpers::BParseIntoUILength( &m_HorizontalOffset, pchString, &pchString ) )
  1540. {
  1541. return false;
  1542. }
  1543. if ( !CSSHelpers::BParseIntoUILength( &m_VerticalOffset, pchString, &pchString ) )
  1544. {
  1545. return false;
  1546. }
  1547. // These two are optional
  1548. CSSHelpers::BParseIntoUILength( &m_BlurRadius, pchString, &pchString );
  1549. CSSHelpers::BParseNumber( &m_flStrength, pchString, &pchString );
  1550. }
  1551. else
  1552. {
  1553. // Lengths are the only thing required, if we get here and have them, we are good.
  1554. if ( bLengthsParsed )
  1555. {
  1556. return true;
  1557. }
  1558. return false;
  1559. }
  1560. }
  1561. return true;
  1562. }
  1563. // called when we are ready to apply any scaling factor to the values
  1564. virtual void ApplyUIScaleFactor( float flScaleFactor )
  1565. {
  1566. m_HorizontalOffset.ScaleLengthValue( flScaleFactor );
  1567. m_VerticalOffset.ScaleLengthValue( flScaleFactor );
  1568. // Although this is a blur pixel radius in css terminology it's really a stddev for our gaussian blur internally,
  1569. // hence it should not scale.
  1570. //m_BlurRadius.ScaleLengthValue( flScaleFactor );
  1571. }
  1572. // Gets string representation of property
  1573. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1574. {
  1575. CSSHelpers::AppendUILength( pfmtBuffer, m_HorizontalOffset );
  1576. pfmtBuffer->Append( " " );
  1577. CSSHelpers::AppendUILength( pfmtBuffer, m_VerticalOffset );
  1578. pfmtBuffer->Append( " " );
  1579. CSSHelpers::AppendUILength( pfmtBuffer, m_BlurRadius );
  1580. pfmtBuffer->Append( " " );
  1581. CSSHelpers::AppendFloat( pfmtBuffer, m_flStrength );
  1582. pfmtBuffer->Append( " " );
  1583. CSSHelpers::AppendColor( pfmtBuffer, m_ShadowColor );
  1584. }
  1585. // Return a description for this property which will be shown in the debugger
  1586. virtual const char *GetDescription( CStyleSymbol symProperty )
  1587. {
  1588. return "Specifies text shadows. The shadow shape will match the text the panel can generate,"
  1589. "and this is only meaningful for labels. Syntax takes horizontal offset pixels, "
  1590. "vertical offset pixels, blur radius pixels, strength, and then shadow color.<br><br>"
  1591. "<b>Example:</b>"
  1592. "<pre>"
  1593. "text-shadow: 2px 2px 8px 3.0 #333333b0;"
  1594. "</pre>";
  1595. }
  1596. // Comparison function
  1597. virtual bool operator==(const CStyleProperty &other) const
  1598. {
  1599. if ( GetPropertySymbol() != other.GetPropertySymbol() )
  1600. return false;
  1601. const CStylePropertyTextShadow &rhs = (const CStylePropertyTextShadow&)other;
  1602. return ( m_HorizontalOffset == rhs.m_HorizontalOffset &&
  1603. m_VerticalOffset == rhs.m_VerticalOffset &&
  1604. m_BlurRadius == rhs.m_BlurRadius &&
  1605. m_ShadowColor == rhs.m_ShadowColor &&
  1606. m_flStrength == rhs.m_flStrength );
  1607. }
  1608. // Layout pieces that can be invalidated when the property is applied to a panel
  1609. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  1610. CUILength m_HorizontalOffset;
  1611. CUILength m_VerticalOffset;
  1612. CUILength m_BlurRadius;
  1613. float m_flStrength;
  1614. Color m_ShadowColor;
  1615. };
  1616. class CStylePropertyClip : public CStyleProperty
  1617. {
  1618. public:
  1619. static const CStyleSymbol symbol;
  1620. CStylePropertyClip() : CStyleProperty( CStylePropertyClip::symbol )
  1621. {
  1622. }
  1623. virtual void MergeTo( CStyleProperty *pTarget ) const
  1624. {
  1625. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1626. {
  1627. AssertMsg( false, "Mismatched types to CStylePropertyClip::MergeTo" );
  1628. return;
  1629. }
  1630. CStyleProperty::MergeTo( pTarget );
  1631. CStylePropertyClip *p = (CStylePropertyClip *)pTarget;
  1632. if ( !p->m_Left.IsSet() )
  1633. p->m_Left = m_Left;
  1634. if( !p->m_Top.IsSet() )
  1635. p->m_Top = m_Top;
  1636. if( !p->m_Right.IsSet() )
  1637. p->m_Right = m_Right;
  1638. if( !p->m_Bottom.IsSet() )
  1639. p->m_Bottom = m_Bottom;
  1640. }
  1641. // Can this property support animation?
  1642. virtual bool BCanTransition() { return true; }
  1643. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  1644. virtual bool BAffectsCompositionOnly() { return false; }
  1645. // Interpolation func for animation of this property
  1646. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  1647. // Parses string and sets value
  1648. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1649. {
  1650. if( V_strnicmp( pchString, "none", V_strlen( "none" ) ) == 0 )
  1651. {
  1652. return true;
  1653. }
  1654. return CSSHelpers::BParseRect( &m_Top, &m_Right, &m_Bottom, &m_Left, pchString );
  1655. }
  1656. // called when we are ready to apply any scaling factor to the values
  1657. virtual void ApplyUIScaleFactor( float flScaleFactor )
  1658. {
  1659. m_Left.ScaleLengthValue( flScaleFactor );
  1660. m_Top.ScaleLengthValue( flScaleFactor );
  1661. m_Right.ScaleLengthValue( flScaleFactor );
  1662. m_Bottom.ScaleLengthValue( flScaleFactor );
  1663. }
  1664. // Gets string representation of property
  1665. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1666. {
  1667. pfmtBuffer->Append( "rect( " );
  1668. CSSHelpers::AppendUILength( pfmtBuffer, m_Top );
  1669. pfmtBuffer->Append( ", " );
  1670. CSSHelpers::AppendUILength( pfmtBuffer, m_Right );
  1671. pfmtBuffer->Append( ", " );
  1672. CSSHelpers::AppendUILength( pfmtBuffer, m_Bottom );
  1673. pfmtBuffer->Append( ", " );
  1674. CSSHelpers::AppendUILength( pfmtBuffer, m_Left );
  1675. pfmtBuffer->Append( ")" );
  1676. }
  1677. // Return a description for this property which will be shown in the debugger
  1678. virtual const char *GetDescription( CStyleSymbol symProperty )
  1679. {
  1680. return "Specifies a clip region within the panel, where contents will be clipped at render time. "
  1681. "This clipping has no impact on layout, and is fast and supported for transitions/animations.<br><br>"
  1682. "<b>Example:</b>"
  1683. "<pre>"
  1684. "clip: rect( 10%, 90%, 90%, 10% );"
  1685. "</pre>";
  1686. }
  1687. // Comparison function
  1688. virtual bool operator==(const CStyleProperty &other) const
  1689. {
  1690. if( GetPropertySymbol() != other.GetPropertySymbol() )
  1691. return false;
  1692. const CStylePropertyClip &rhs = (const CStylePropertyClip&)other;
  1693. return (m_Left == rhs.m_Left &&
  1694. m_Right == rhs.m_Right &&
  1695. m_Top == rhs.m_Top &&
  1696. m_Bottom == rhs.m_Bottom );
  1697. }
  1698. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  1699. virtual void ResolveDefaultValues()
  1700. {
  1701. if( !m_Left.IsSet() )
  1702. m_Left.SetPercent( 0 );
  1703. if( !m_Top.IsSet() )
  1704. m_Top.SetPercent( 0 );
  1705. if( !m_Right.IsSet() )
  1706. m_Right.SetPercent( 100 );
  1707. if( !m_Bottom.IsSet() )
  1708. m_Bottom.SetPercent( 100 );
  1709. }
  1710. // Layout pieces that can be invalidated when the property is applied to a panel
  1711. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  1712. CUILength m_Left;
  1713. CUILength m_Top;
  1714. CUILength m_Right;
  1715. CUILength m_Bottom;
  1716. };
  1717. //-----------------------------------------------------------------------------
  1718. // Purpose: color wash property, applies basically like drawing the color over
  1719. // the top of the panel after all child rendering is complete, alpha value affects
  1720. // how much of the child drawing colors come through.
  1721. //-----------------------------------------------------------------------------
  1722. class CStylePropertyWashColor : public CStyleProperty
  1723. {
  1724. public:
  1725. static const CStyleSymbol symbol;
  1726. static inline Color GetDefault() { return Color( 255, 255, 255, 255 ); }
  1727. CStylePropertyWashColor() : CStyleProperty( CStylePropertyWashColor::symbol )
  1728. {
  1729. m_color = GetDefault();
  1730. }
  1731. virtual void MergeTo( CStyleProperty *pTarget ) const
  1732. {
  1733. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1734. {
  1735. AssertMsg( false, "Mismatched types to CStylePropertyWashColor::MergeTo" );
  1736. return;
  1737. }
  1738. CStyleProperty::MergeTo( pTarget );
  1739. CStylePropertyWashColor *p = (CStylePropertyWashColor *)pTarget;
  1740. p->m_color = m_color;
  1741. }
  1742. // Can this property support animation?
  1743. virtual bool BCanTransition() { return true; }
  1744. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  1745. virtual bool BAffectsCompositionOnly() { return true; }
  1746. // Interpolation func for animation of this property
  1747. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  1748. {
  1749. if( target.GetPropertySymbol() != GetPropertySymbol() )
  1750. {
  1751. AssertMsg( false, "Mismatched types to CStylePropertyWashColor::Interpolate" );
  1752. return;
  1753. }
  1754. const CStylePropertyWashColor *p = (const CStylePropertyWashColor *)&target;
  1755. int r = m_color.r() + (p->m_color.r() - m_color.r()) * flProgress;
  1756. int b = m_color.b() + (p->m_color.b() - m_color.b()) * flProgress;
  1757. int g = m_color.g() + (p->m_color.g() - m_color.g()) * flProgress;
  1758. int a = m_color.a() + (p->m_color.a() - m_color.a()) * flProgress;
  1759. m_color.SetColor( r, g, b, a );
  1760. }
  1761. // Parses string and sets value
  1762. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1763. {
  1764. if( CSSHelpers::BParseColor( &m_color, pchString ) )
  1765. {
  1766. return true;
  1767. }
  1768. else if( V_stricmp( "transparent", pchString ) == 0 )
  1769. {
  1770. m_color.SetColor( 0, 0, 0, 0 );
  1771. return true;
  1772. }
  1773. return false;
  1774. }
  1775. // Gets string representation of property
  1776. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1777. {
  1778. CSSHelpers::AppendColor( pfmtBuffer, m_color );
  1779. }
  1780. // Return a description for this property which will be shown in the debugger
  1781. virtual const char *GetDescription( CStyleSymbol symProperty )
  1782. {
  1783. return "Specifies a 'wash' color, which means a color that will be blended over the panel and all it's children at "
  1784. "composition time, tinting them. The alpha value of the color determines the intensity of the tinting.<br><br>"
  1785. "<b>Example:</b>"
  1786. "<pre>"
  1787. "wash-color: #39b0d325;"
  1788. "</pre>";
  1789. }
  1790. // Comparison function
  1791. virtual bool operator==(const CStyleProperty &other) const
  1792. {
  1793. if( GetPropertySymbol() != other.GetPropertySymbol() )
  1794. return false;
  1795. const CStylePropertyWashColor &rhs = (const CStylePropertyWashColor&)other;
  1796. return (m_color == rhs.m_color);
  1797. }
  1798. // Layout pieces that can be invalidated when the property is applied to a panel
  1799. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  1800. Color m_color;
  1801. };
  1802. //-----------------------------------------------------------------------------
  1803. // Purpose: Overflow property
  1804. //-----------------------------------------------------------------------------
  1805. class CStylePropertyOverflow : public CStyleProperty
  1806. {
  1807. public:
  1808. static const CStyleSymbol symbol;
  1809. CStylePropertyOverflow() : CStyleProperty( CStylePropertyOverflow::symbol )
  1810. {
  1811. m_eHorizontal = k_EOverflowSquish;
  1812. m_eVertical = k_EOverflowSquish;
  1813. }
  1814. virtual void MergeTo( CStyleProperty *pTarget ) const
  1815. {
  1816. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1817. {
  1818. AssertMsg( false, "Mismatched types to CStylePropertyOverflow::MergeTo" );
  1819. return;
  1820. }
  1821. CStyleProperty::MergeTo( pTarget );
  1822. CStylePropertyOverflow *p = (CStylePropertyOverflow *)pTarget;
  1823. p->m_eHorizontal = m_eHorizontal;
  1824. p->m_eVertical = m_eVertical;
  1825. }
  1826. // Can this property support animation?
  1827. virtual bool BCanTransition() { return false; }
  1828. // Interpolation func for animation of this property
  1829. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { }
  1830. // Parses string and sets value
  1831. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1832. {
  1833. if( !BParseOverflow( &m_eHorizontal, pchString, &pchString ) )
  1834. return false;
  1835. // only 1 value specified?
  1836. pchString = CSSHelpers::SkipSpaces( pchString );
  1837. if( pchString[0] == '\0' )
  1838. {
  1839. m_eVertical = m_eHorizontal;
  1840. return true;
  1841. }
  1842. // get vertical
  1843. if( !BParseOverflow( &m_eVertical, pchString, &pchString ) )
  1844. return false;
  1845. return true;
  1846. }
  1847. bool BParseOverflow( EOverflowValue *peOverflow, const char *pchString, const char **pchAfterParse = NULL )
  1848. {
  1849. char rgchProperty[128];
  1850. if( !CSSHelpers::BParseIdent( rgchProperty, V_ARRAYSIZE( rgchProperty ), pchString, &pchString ) )
  1851. return false;
  1852. // special case none
  1853. if( V_stricmp( rgchProperty, "squish" ) == 0 )
  1854. *peOverflow = k_EOverflowSquish;
  1855. else if( V_stricmp( rgchProperty, "clip" ) == 0 )
  1856. *peOverflow = k_EOverflowClip;
  1857. else if( V_stricmp( rgchProperty, "scroll" ) == 0 )
  1858. *peOverflow = k_EOverflowScroll;
  1859. else if( V_stricmp( rgchProperty, "noclip" ) == 0 )
  1860. *peOverflow = k_EOverflowNoClip;
  1861. else
  1862. return false;
  1863. if( pchAfterParse )
  1864. *pchAfterParse = pchString;
  1865. return true;
  1866. }
  1867. void BAppendOverflow( CFmtStr1024 *pfmtBuffer, const EOverflowValue &eOverflow ) const
  1868. {
  1869. if( eOverflow == k_EOverflowSquish )
  1870. pfmtBuffer->Append( "squish" );
  1871. else if( eOverflow == k_EOverflowClip )
  1872. pfmtBuffer->Append( "clip" );
  1873. else if( eOverflow == k_EOverflowScroll )
  1874. pfmtBuffer->Append( "scroll" );
  1875. else if( eOverflow == k_EOverflowNoClip )
  1876. pfmtBuffer->Append( "noclip" );
  1877. else
  1878. AssertMsg1( false, "Unknown overflow value: %d", eOverflow );
  1879. }
  1880. // Gets string representation of property
  1881. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  1882. {
  1883. BAppendOverflow( pfmtBuffer, m_eHorizontal );
  1884. pfmtBuffer->Append( " " );
  1885. BAppendOverflow( pfmtBuffer, m_eVertical );
  1886. }
  1887. // Return a description for this property which will be shown in the debugger
  1888. virtual const char *GetDescription( CStyleSymbol symProperty )
  1889. {
  1890. return "Specifies what to do with contents that overflow the available space for the panel. "
  1891. "Possible values:<br>"
  1892. "\"squish\" - Children are squished to fit within the panel's bounds if needed (default)<br>"
  1893. "\"clip\" - Children maintain their desired size but their contents are clipped<br>"
  1894. "\"scroll\" - Children maintain their desired size and a scrollbar is added to this panel<br><br>"
  1895. "<b>Examples:</b>"
  1896. "<pre>"
  1897. "overflow: squish squish; // squishes contents in horizontal and vertical directions\n"
  1898. "overflow: squish scroll; // scrolls contents in the Y direction"
  1899. "</pre>";
  1900. }
  1901. // Comparison function
  1902. virtual bool operator==(const CStyleProperty &other) const
  1903. {
  1904. if( GetPropertySymbol() != other.GetPropertySymbol() )
  1905. return false;
  1906. const CStylePropertyOverflow &rhs = (const CStylePropertyOverflow&)other;
  1907. return (m_eHorizontal == rhs.m_eHorizontal && m_eVertical == rhs.m_eVertical);
  1908. }
  1909. // Layout pieces that can be invalidated when the property is applied to a panel
  1910. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  1911. {
  1912. if( !pCompareProperty || !(*this == *pCompareProperty) )
  1913. return k_EStyleInvalidateLayoutSizeAndPosition;
  1914. return k_EStyleInvalidateLayoutNone;
  1915. }
  1916. EOverflowValue m_eHorizontal;
  1917. EOverflowValue m_eVertical;
  1918. };
  1919. //-----------------------------------------------------------------------------
  1920. // Purpose: Font property
  1921. //-----------------------------------------------------------------------------
  1922. class CStylePropertyFont : public CStyleProperty
  1923. {
  1924. public:
  1925. static const CStyleSymbol symbol;
  1926. static const CStyleSymbol fontFamily;
  1927. static const CStyleSymbol fontSize;
  1928. static const CStyleSymbol fontStyle;
  1929. static const CStyleSymbol fontWeight;
  1930. CStylePropertyFont() : CStyleProperty( CStylePropertyFont::symbol )
  1931. {
  1932. m_flFontSize = k_flFloatNotSet;
  1933. m_eFontStyle = k_EFontStyleUnset;
  1934. m_eFontWeight = k_EFontWeightUnset;
  1935. }
  1936. virtual void MergeTo( CStyleProperty *pTarget ) const
  1937. {
  1938. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  1939. {
  1940. AssertMsg( false, "Mismatched types to CStylePropertyFont::MergeTo" );
  1941. return;
  1942. }
  1943. CStyleProperty::MergeTo( pTarget );
  1944. CStylePropertyFont *p = (CStylePropertyFont *)pTarget;
  1945. if( p->m_strFontFamily.IsEmpty() )
  1946. p->m_strFontFamily = m_strFontFamily;
  1947. if( p->m_flFontSize == k_flFloatNotSet )
  1948. p->m_flFontSize = m_flFontSize;
  1949. if( p->m_eFontStyle == k_EFontStyleUnset )
  1950. p->m_eFontStyle = m_eFontStyle;
  1951. if( p->m_eFontWeight == k_EFontWeightUnset )
  1952. p->m_eFontWeight = m_eFontWeight;
  1953. }
  1954. // Can this property support animation?
  1955. virtual bool BCanTransition() { return false; }
  1956. // Interpolation func for animation of this property
  1957. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { Assert( !"You can't interpolate a font" ); }
  1958. // Parses string and sets value
  1959. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  1960. {
  1961. if( symParsedName == fontSize )
  1962. {
  1963. bool bSuccess = false;
  1964. if( !CSSHelpers::BParseNumber( &m_flFontSize, pchString ) )
  1965. {
  1966. if( CSSHelpers::BParseLength( &m_flFontSize, pchString ) )
  1967. {
  1968. bSuccess = true;
  1969. }
  1970. }
  1971. else
  1972. {
  1973. bSuccess = true;
  1974. }
  1975. return bSuccess;
  1976. }
  1977. else if( symParsedName == fontFamily )
  1978. {
  1979. char rgchFontFamily[512] = "";
  1980. pchString = CSSHelpers::SkipSpaces( pchString );
  1981. CSSHelpers::BSkipQuote( pchString, &pchString );
  1982. V_strncpy( rgchFontFamily, pchString, V_ARRAYSIZE( rgchFontFamily ) );
  1983. int len = V_strlen( rgchFontFamily );
  1984. if( len > 1 )
  1985. {
  1986. if( rgchFontFamily[len - 1] == '\'' || rgchFontFamily[len - 1] == '"' )
  1987. rgchFontFamily[len - 1] = 0;
  1988. }
  1989. V_StrTrim( rgchFontFamily );
  1990. m_strFontFamily = rgchFontFamily;
  1991. return !m_strFontFamily.IsEmpty();
  1992. }
  1993. else if( symParsedName == fontWeight )
  1994. {
  1995. if( V_stristr( pchString, "normal" ) )
  1996. m_eFontWeight = k_EFontWeightNormal;
  1997. else if( V_stristr( pchString, "medium" ) )
  1998. m_eFontWeight = k_EFontWeightMedium;
  1999. else if( V_stristr( pchString, "bold" ) )
  2000. m_eFontWeight = k_EFontWeightBold;
  2001. else if( V_stristr( pchString, "black" ) )
  2002. m_eFontWeight = k_EFontWeightBlack;
  2003. else if( V_stristr( pchString, "thin" ) )
  2004. m_eFontWeight = k_EFontWeightThin;
  2005. else if ( V_stristr( pchString, "light" ) )
  2006. m_eFontWeight = k_EFontWeightLight;
  2007. else if ( V_stristr( pchString, "semi-bold" ) )
  2008. m_eFontWeight = k_EFontWeightSemiBold;
  2009. if( m_eFontWeight != k_EFontWeightUnset )
  2010. return true;
  2011. }
  2012. else if( symParsedName == fontStyle )
  2013. {
  2014. if( V_stristr( pchString, "normal" ) )
  2015. m_eFontStyle = k_EFontStyleNormal;
  2016. else if( V_stristr( pchString, "italic" ) )
  2017. m_eFontStyle = k_EFontStyleItalic;
  2018. if( m_eFontStyle != k_EFontStyleUnset )
  2019. return true;
  2020. }
  2021. return false;
  2022. }
  2023. // called when we are ready to apply any scaling factor to the values
  2024. virtual void ApplyUIScaleFactor( float flScaleFactor )
  2025. {
  2026. if( m_flFontSize != k_flFloatNotSet )
  2027. m_flFontSize *= flScaleFactor;
  2028. }
  2029. // Get suggested values based on current text for style property value
  2030. virtual void GetSuggestedValues( CStyleSymbol symAlias, const char *pchTextSoFar, CUtlVector< CUtlString > &vecSuggestions )
  2031. {
  2032. if( symAlias == fontFamily )
  2033. {
  2034. if( pchTextSoFar[0] == '"' )
  2035. ++pchTextSoFar;
  2036. int cchText = V_strlen( pchTextSoFar );
  2037. if( cchText > 0 && pchTextSoFar[cchText - 1] == '"' )
  2038. --cchText;
  2039. const CUtlSortVector< CUtlString > &vecValues = UIEngine()->GetSortedValidFontNames();
  2040. int iVec = vecValues.FindLessOrEqual( pchTextSoFar );
  2041. if( iVec == vecValues.InvalidIndex() )
  2042. iVec = 0;
  2043. while( vecValues.IsValidIndex( iVec ) )
  2044. {
  2045. const char *pchValue = vecValues[iVec].String();
  2046. if( cchText > 0 )
  2047. {
  2048. int nCmp = V_strncmp( pchValue, pchTextSoFar, cchText );
  2049. if( nCmp > 0 )
  2050. break;
  2051. // if less than, keep going
  2052. if( nCmp < 0 )
  2053. {
  2054. iVec++;
  2055. continue;
  2056. }
  2057. }
  2058. CFmtStr1024 strValue( "\"%s\"", vecValues[iVec].String() );
  2059. vecSuggestions.AddToTail( strValue.String() );
  2060. iVec++;
  2061. }
  2062. }
  2063. }
  2064. // Gets string representation of property
  2065. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  2066. {
  2067. pfmtBuffer->AppendFormat( "%s %s ", PchNameFromEFontStyle( m_eFontStyle ), PchNameFromEFontWeight( m_eFontWeight ) );
  2068. CSSHelpers::AppendFloat( pfmtBuffer, m_flFontSize );
  2069. pfmtBuffer->AppendFormat( " %s", m_strFontFamily.String() );
  2070. }
  2071. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  2072. // by looking at lower weight styles
  2073. virtual bool BFullySet()
  2074. {
  2075. return (m_flFontSize != k_flFloatNotSet &&
  2076. !m_strFontFamily.IsEmpty() &&
  2077. m_eFontStyle != k_EFontStyleUnset &&
  2078. m_eFontWeight != k_EFontWeightUnset);
  2079. }
  2080. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  2081. virtual void ResolveDefaultValues()
  2082. {
  2083. // leave unset rather than defaulting. We will fix things up when accessed
  2084. }
  2085. // Return a description for this property which will be shown in the debugger
  2086. virtual const char *GetDescription( CStyleSymbol symProperty )
  2087. {
  2088. if( symProperty == fontFamily )
  2089. {
  2090. return "Specifies the font face to use.<br><br>"
  2091. "<b>Examples:</b>"
  2092. "<pre>"
  2093. "font-family: Arial;\n"
  2094. "font-family: \"Comic Sans MS\";"
  2095. "</pre>";
  2096. }
  2097. else if( symProperty == fontSize )
  2098. {
  2099. return "Specifies the target font face height in pixels.<br><br>"
  2100. "<b>Example:</b>"
  2101. "<pre>"
  2102. "font-size: 12;"
  2103. "</pre>";
  2104. }
  2105. else if( symProperty == fontWeight )
  2106. {
  2107. return "Specifies the font weight to use. Supported values are light, thin, normal, medium, bold, and black.<br><br>"
  2108. "<b>Examples:</b>"
  2109. "<pre>"
  2110. "font-weight: normal;\n"
  2111. "font-weight: bold;\n"
  2112. "font-weight: thin;"
  2113. "</pre>";
  2114. }
  2115. else if( symProperty == fontStyle )
  2116. {
  2117. return "Specifies the font style to use. Supported values are normal, and italic<br><br>"
  2118. "<b>Example:</b>"
  2119. "<pre>"
  2120. "font-style: normal;"
  2121. "</pre>";
  2122. }
  2123. return CStyleProperty::GetDescription( symProperty );
  2124. }
  2125. // Comparison function
  2126. virtual bool operator==(const CStyleProperty &other) const
  2127. {
  2128. if( GetPropertySymbol() != other.GetPropertySymbol() )
  2129. return false;
  2130. const CStylePropertyFont &rhs = (const CStylePropertyFont&)other;
  2131. return (m_strFontFamily == rhs.m_strFontFamily && m_flFontSize == rhs.m_flFontSize && m_eFontStyle == rhs.m_eFontStyle && m_eFontWeight == rhs.m_eFontWeight);
  2132. }
  2133. // Layout pieces that can be invalidated when the property is applied to a panel
  2134. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  2135. {
  2136. if( !pCompareProperty || !(*this == *pCompareProperty) )
  2137. return k_EStyleInvalidateLayoutSizeAndPosition;
  2138. return k_EStyleInvalidateLayoutNone;
  2139. }
  2140. #ifdef DBGFLAG_VALIDATE
  2141. virtual void Validate( CValidator &validator, const tchar *pchName )
  2142. {
  2143. VALIDATE_SCOPE();
  2144. ValidateObj( m_strFontFamily );
  2145. CStyleProperty::Validate( validator, pchName );
  2146. }
  2147. #endif
  2148. CUtlString m_strFontFamily;
  2149. float m_flFontSize;
  2150. EFontStyle m_eFontStyle;
  2151. EFontWeight m_eFontWeight;
  2152. };
  2153. //-----------------------------------------------------------------------------
  2154. // Purpose: Text align property
  2155. //-----------------------------------------------------------------------------
  2156. class CStylePropertyTextAlign : public CStyleProperty
  2157. {
  2158. public:
  2159. static const CStyleSymbol symbol;
  2160. CStylePropertyTextAlign() : CStyleProperty( CStylePropertyTextAlign::symbol )
  2161. {
  2162. m_eAlign = k_ETextAlignUnset;
  2163. }
  2164. virtual void MergeTo( CStyleProperty *pTarget ) const
  2165. {
  2166. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  2167. {
  2168. AssertMsg( false, "Mismatched types to CStylePropertyTextAlign::MergeTo" );
  2169. return;
  2170. }
  2171. CStyleProperty::MergeTo( pTarget );
  2172. CStylePropertyTextAlign *p = (CStylePropertyTextAlign *)pTarget;
  2173. p->m_eAlign = m_eAlign;
  2174. }
  2175. // Can this property support animation?
  2176. virtual bool BCanTransition() { return false; }
  2177. // Interpolation func for animation of this property
  2178. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { Assert( !"You can't interpolate a text-align" ); }
  2179. // Parses string and sets value
  2180. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2181. {
  2182. if( symParsedName == symbol )
  2183. {
  2184. if( V_stristr( pchString, "left" ) )
  2185. m_eAlign = k_ETextAlignLeft;
  2186. else if( V_stristr( pchString, "center" ) )
  2187. m_eAlign = k_ETextAlignCenter;
  2188. else if( V_stristr( pchString, "right" ) )
  2189. m_eAlign = k_ETextAlignRight;
  2190. else
  2191. return false;
  2192. return true;
  2193. }
  2194. return false;
  2195. }
  2196. // Gets string representation of property
  2197. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  2198. {
  2199. pfmtBuffer->Append( PchNameFromETextAlign( m_eAlign ) );
  2200. }
  2201. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  2202. // by looking at lower weight styles
  2203. virtual bool BFullySet()
  2204. {
  2205. return (m_eAlign != k_ETextAlignUnset);
  2206. }
  2207. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  2208. virtual void ResolveDefaultValues()
  2209. {
  2210. // bugbug jmccaskey - someday maybe default to right aligned on rtl languages?
  2211. if( m_eAlign == k_ETextAlignUnset )
  2212. m_eAlign = k_ETextAlignLeft;
  2213. }
  2214. // Return a description for this property which will be shown in the debugger
  2215. virtual const char *GetDescription( CStyleSymbol symProperty )
  2216. {
  2217. return "Specifies the text alignment for text within this panel, defaults to left.<br><br>"
  2218. "<b>Examples:</b>"
  2219. "<pre>"
  2220. "text-align: left;\n"
  2221. "text-align: right;\n"
  2222. "text-align: center;"
  2223. "</pre>";
  2224. }
  2225. // Comparison function
  2226. virtual bool operator==(const CStyleProperty &other) const
  2227. {
  2228. if( GetPropertySymbol() != other.GetPropertySymbol() )
  2229. return false;
  2230. const CStylePropertyTextAlign &rhs = (const CStylePropertyTextAlign&)other;
  2231. return (m_eAlign == rhs.m_eAlign);
  2232. }
  2233. // Layout pieces that can be invalidated when the property is applied to a panel
  2234. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  2235. {
  2236. if( !pCompareProperty || !(*this == *pCompareProperty) )
  2237. return k_EStyleInvalidateLayoutSizeAndPosition;
  2238. return k_EStyleInvalidateLayoutNone;
  2239. }
  2240. ETextAlign m_eAlign;
  2241. };
  2242. //-----------------------------------------------------------------------------
  2243. // Purpose: Letter spacing property
  2244. //-----------------------------------------------------------------------------
  2245. class CStylePropertyTextLetterSpacing : public CStyleProperty
  2246. {
  2247. public:
  2248. static const CStyleSymbol symbol;
  2249. CStylePropertyTextLetterSpacing() : CStyleProperty( CStylePropertyTextLetterSpacing::symbol )
  2250. {
  2251. m_nLetterSpacing = 0;
  2252. }
  2253. virtual void MergeTo( CStyleProperty *pTarget ) const
  2254. {
  2255. if ( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  2256. {
  2257. AssertMsg( false, "Mismatched types to CStylePropertyTextLetterSpacing::MergeTo" );
  2258. return;
  2259. }
  2260. CStylePropertyTextLetterSpacing *p = (CStylePropertyTextLetterSpacing *)pTarget;
  2261. p->m_nLetterSpacing = m_nLetterSpacing;
  2262. }
  2263. // Can this property support animation?
  2264. virtual bool BCanTransition() { return false; }
  2265. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { Assert( !"You can't interpolate a letter-spacing" ); }
  2266. // Parses string and sets value
  2267. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2268. {
  2269. bool bSuccess = false;
  2270. pchString = CSSHelpers::SkipSpaces( pchString );
  2271. if ( V_strnicmp( pchString, "normal", V_ARRAYSIZE( "normal" ) ) == 0 )
  2272. {
  2273. m_nLetterSpacing = 0;
  2274. bSuccess = true;
  2275. }
  2276. else
  2277. {
  2278. float flLength;
  2279. bSuccess = CSSHelpers::BParseLength( &flLength, pchString, NULL );
  2280. m_nLetterSpacing = roundf(flLength);
  2281. }
  2282. return bSuccess;
  2283. }
  2284. // called when we are ready to apply any scaling factor to the values
  2285. virtual void ApplyUIScaleFactor( float flScaleFactor )
  2286. {
  2287. m_nLetterSpacing = (float)roundf(m_nLetterSpacing*flScaleFactor);
  2288. }
  2289. // Gets string representation of property
  2290. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  2291. {
  2292. CSSHelpers::AppendLength( pfmtBuffer, m_nLetterSpacing );
  2293. }
  2294. // Return a description for this property which will be shown in the debugger
  2295. virtual const char *GetDescription( CStyleSymbol symProperty )
  2296. {
  2297. return "Sets letter-spacing for text in a string. "
  2298. "Possible values:<br>"
  2299. "normal - no manual spacing<br>"
  2300. "&lt;pixels&gt; - Any fixed pixel value (ex: \"1px\")";
  2301. }
  2302. // Comparison function
  2303. virtual bool operator==( const CStyleProperty &other ) const
  2304. {
  2305. if ( GetPropertySymbol() != other.GetPropertySymbol() )
  2306. return false;
  2307. const CStylePropertyTextLetterSpacing &rhs = (const CStylePropertyTextLetterSpacing &)other;
  2308. return ( m_nLetterSpacing == rhs.m_nLetterSpacing );
  2309. }
  2310. // Layout pieces that can be invalidated when the property is applied to a panel
  2311. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  2312. {
  2313. if ( !pCompareProperty || !( *this == *pCompareProperty ) )
  2314. return k_EStyleInvalidateLayoutSizeAndPosition;
  2315. return k_EStyleInvalidateLayoutNone;
  2316. }
  2317. int m_nLetterSpacing;
  2318. };
  2319. //-----------------------------------------------------------------------------
  2320. // Purpose: Text decoration property
  2321. //-----------------------------------------------------------------------------
  2322. class CStylePropertyTextDecoration : public CStyleProperty
  2323. {
  2324. public:
  2325. static const CStyleSymbol symbol;
  2326. static inline ETextDecoration GetDefault() { return k_ETextDecorationNone; }
  2327. CStylePropertyTextDecoration() : CStyleProperty( CStylePropertyTextDecoration::symbol )
  2328. {
  2329. m_eDecoration = GetDefault();
  2330. }
  2331. virtual void MergeTo( CStyleProperty *pTarget ) const
  2332. {
  2333. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  2334. {
  2335. AssertMsg( false, "Mismatched types to CStylePropertyTextDecoration::MergeTo" );
  2336. return;
  2337. }
  2338. CStyleProperty::MergeTo( pTarget );
  2339. CStylePropertyTextDecoration *p = (CStylePropertyTextDecoration *)pTarget;
  2340. p->m_eDecoration = m_eDecoration;
  2341. }
  2342. // Can this property support animation?
  2343. virtual bool BCanTransition() { return false; }
  2344. // Interpolation func for animation of this property
  2345. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { Assert( !"You can't interpolate a text-decorations" ); }
  2346. // Parses string and sets value
  2347. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2348. {
  2349. if( symParsedName == symbol )
  2350. {
  2351. m_eDecoration = ETextDecorationFromName( pchString );
  2352. return (m_eDecoration != k_ETextDecorationUnset);
  2353. }
  2354. return false;
  2355. }
  2356. // Gets string representation of property
  2357. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  2358. {
  2359. pfmtBuffer->Append( PchNameFromETextDecoration( m_eDecoration ) );
  2360. }
  2361. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  2362. // by looking at lower weight styles
  2363. virtual bool BFullySet()
  2364. {
  2365. return (m_eDecoration != k_ETextDecorationUnset);
  2366. }
  2367. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  2368. virtual void ResolveDefaultValues()
  2369. {
  2370. }
  2371. // Return a description for this property which will be shown in the debugger
  2372. virtual const char *GetDescription( CStyleSymbol symProperty )
  2373. {
  2374. return "Specifies the decoration for text within this panel, defaults to none. Possible values: none, underline, line-through.<br><br>"
  2375. "<b>Example:</b>"
  2376. "<pre>"
  2377. "text-decoration: underline;"
  2378. "</pre>";
  2379. }
  2380. // Comparison function
  2381. virtual bool operator==(const CStyleProperty &other) const
  2382. {
  2383. if( GetPropertySymbol() != other.GetPropertySymbol() )
  2384. return false;
  2385. const CStylePropertyTextDecoration &rhs = (const CStylePropertyTextDecoration&)other;
  2386. return (m_eDecoration == rhs.m_eDecoration);
  2387. }
  2388. // Layout pieces that can be invalidated when the property is applied to a panel
  2389. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  2390. {
  2391. if( !pCompareProperty || !(*this == *pCompareProperty) )
  2392. return k_EStyleInvalidateLayoutSizeAndPosition;
  2393. return k_EStyleInvalidateLayoutNone;
  2394. }
  2395. ETextDecoration m_eDecoration;
  2396. };
  2397. //-----------------------------------------------------------------------------
  2398. // Purpose: Text decoration property
  2399. //-----------------------------------------------------------------------------
  2400. class CStylePropertyTextTransform : public CStyleProperty
  2401. {
  2402. public:
  2403. static const CStyleSymbol symbol;
  2404. static inline ETextTransform GetDefault() { return k_ETextTransformNone; }
  2405. CStylePropertyTextTransform() : CStyleProperty( CStylePropertyTextTransform::symbol )
  2406. {
  2407. m_eTransform = GetDefault();
  2408. }
  2409. virtual void MergeTo( CStyleProperty *pTarget ) const
  2410. {
  2411. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  2412. {
  2413. AssertMsg( false, "Mismatched types to CStylePropertyTextDecoration::MergeTo" );
  2414. return;
  2415. }
  2416. CStyleProperty::MergeTo( pTarget );
  2417. CStylePropertyTextTransform *p = (CStylePropertyTextTransform *)pTarget;
  2418. p->m_eTransform = m_eTransform;
  2419. }
  2420. // Can this property support animation?
  2421. virtual bool BCanTransition() { return false; }
  2422. // Interpolation func for animation of this property
  2423. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { Assert( !"You can't interpolate a text-decorations" ); }
  2424. // Parses string and sets value
  2425. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2426. {
  2427. if( symParsedName == symbol )
  2428. {
  2429. m_eTransform = ETextTransformFromName( pchString );
  2430. return (m_eTransform != k_ETextTransformUnset);
  2431. }
  2432. return false;
  2433. }
  2434. // Gets string representation of property
  2435. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  2436. {
  2437. pfmtBuffer->Append( PchNameFromETextTransform( m_eTransform ) );
  2438. }
  2439. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  2440. // by looking at lower weight styles
  2441. virtual bool BFullySet()
  2442. {
  2443. return (m_eTransform != k_ETextTransformUnset);
  2444. }
  2445. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  2446. virtual void ResolveDefaultValues()
  2447. {
  2448. }
  2449. // Return a description for this property which will be shown in the debugger
  2450. virtual const char *GetDescription( CStyleSymbol symProperty )
  2451. {
  2452. return "Specifies the transform for text within this panel, defaults to none. Possible values: none, uppercase, lowercase.<br><br>"
  2453. "<b>Example:</b>"
  2454. "<pre>"
  2455. "text-transform: uppercase;"
  2456. "</pre>";
  2457. }
  2458. // Comparison function
  2459. virtual bool operator==(const CStyleProperty &other) const
  2460. {
  2461. if( GetPropertySymbol() != other.GetPropertySymbol() )
  2462. return false;
  2463. const CStylePropertyTextTransform &rhs = (const CStylePropertyTextTransform&)other;
  2464. return (m_eTransform == rhs.m_eTransform);
  2465. }
  2466. // Layout pieces that can be invalidated when the property is applied to a panel
  2467. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  2468. {
  2469. if( !pCompareProperty || !(*this == *pCompareProperty) )
  2470. return k_EStyleInvalidateLayoutSizeAndPosition;
  2471. return k_EStyleInvalidateLayoutNone;
  2472. }
  2473. ETextTransform m_eTransform;
  2474. };
  2475. //-----------------------------------------------------------------------------
  2476. // Purpose: Line height property
  2477. //-----------------------------------------------------------------------------
  2478. class CStylePropertyLineHeight : public CStyleProperty
  2479. {
  2480. public:
  2481. static const CStyleSymbol symbol;
  2482. CStylePropertyLineHeight() : CStyleProperty( CStylePropertyLineHeight::symbol )
  2483. {
  2484. m_flLineHeight = k_flFloatNotSet;
  2485. }
  2486. virtual void MergeTo( CStyleProperty *pTarget ) const
  2487. {
  2488. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  2489. {
  2490. AssertMsg( false, "Mismatched types to CStylePropertyLineHeight::MergeTo" );
  2491. return;
  2492. }
  2493. CStyleProperty::MergeTo( pTarget );
  2494. CStylePropertyLineHeight *p = (CStylePropertyLineHeight *)pTarget;
  2495. p->m_flLineHeight = m_flLineHeight;
  2496. }
  2497. // Can this property support animation?
  2498. virtual bool BCanTransition() { return false; }
  2499. // Interpolation func for animation of this property
  2500. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { Assert( !"You can't interpolate a line height" ); }
  2501. // Parses string and sets value
  2502. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2503. {
  2504. if( symParsedName == symbol )
  2505. {
  2506. bool bSuccess = false;
  2507. if( !CSSHelpers::BParseNumber( &m_flLineHeight, pchString ) )
  2508. {
  2509. bSuccess = CSSHelpers::BParseLength( &m_flLineHeight, pchString );
  2510. }
  2511. else
  2512. {
  2513. bSuccess = true;
  2514. }
  2515. return bSuccess;
  2516. }
  2517. return false;
  2518. }
  2519. // called when we are ready to apply any scaling factor to the values
  2520. virtual void ApplyUIScaleFactor( float flScaleFactor )
  2521. {
  2522. if( m_flLineHeight != k_flFloatNotSet )
  2523. m_flLineHeight *= flScaleFactor;
  2524. }
  2525. // Gets string representation of property
  2526. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  2527. {
  2528. CSSHelpers::AppendFloat( pfmtBuffer, m_flLineHeight );
  2529. }
  2530. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  2531. // by looking at lower weight styles
  2532. virtual bool BFullySet()
  2533. {
  2534. return (m_flLineHeight != k_flFloatNotSet);
  2535. }
  2536. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  2537. virtual void ResolveDefaultValues()
  2538. {
  2539. // Leave unset rather than defaulting, will mean don't apply and let font-size set
  2540. }
  2541. // Return a description for this property which will be shown in the debugger
  2542. virtual const char *GetDescription( CStyleSymbol symProperty )
  2543. {
  2544. return "Specifies the line height (distance between top edge of line above and line below) to use for text. By default "
  2545. "this is unset and a value that matches the font-size reasonably will be used automatically.<br><br>"
  2546. "<b>Example:</b>"
  2547. "<pre>"
  2548. "line-height: 20px;"
  2549. "</pre>";
  2550. }
  2551. // Comparison function
  2552. virtual bool operator==(const CStyleProperty &other) const
  2553. {
  2554. if( GetPropertySymbol() != other.GetPropertySymbol() )
  2555. return false;
  2556. const CStylePropertyLineHeight &rhs = (const CStylePropertyLineHeight&)other;
  2557. return (m_flLineHeight == rhs.m_flLineHeight);
  2558. }
  2559. // Layout pieces that can be invalidated when the property is applied to a panel
  2560. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  2561. {
  2562. if( !pCompareProperty || !(*this == *pCompareProperty) )
  2563. return k_EStyleInvalidateLayoutSizeAndPosition;
  2564. return k_EStyleInvalidateLayoutNone;
  2565. }
  2566. float m_flLineHeight;
  2567. };
  2568. //-----------------------------------------------------------------------------
  2569. // Purpose: Fill color property, this is not a real style property, but instead
  2570. // a base that others derive from if they include a fill color.
  2571. //-----------------------------------------------------------------------------
  2572. class CStylePropertyFillColor : public CStyleProperty
  2573. {
  2574. public:
  2575. CStylePropertyFillColor( CStyleSymbol symbol ) : CStyleProperty( symbol )
  2576. {
  2577. }
  2578. virtual ~CStylePropertyFillColor() {}
  2579. virtual void MergeTo( CStyleProperty *pTarget ) const
  2580. {
  2581. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  2582. {
  2583. AssertMsg( false, "Mismatched types to CStylePropertyFillColor::MergeTo" );
  2584. return;
  2585. }
  2586. CStyleProperty::MergeTo( pTarget );
  2587. CStylePropertyFillColor *p = (CStylePropertyFillColor *)pTarget;
  2588. p->m_FillBrushCollection = m_FillBrushCollection;
  2589. }
  2590. // Can this property support animation?
  2591. virtual bool BCanTransition() { return true; }
  2592. // Interpolation func for animation of this property, must implement if you override BCanTransition to return true.
  2593. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  2594. // Parses string and sets value
  2595. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2596. {
  2597. m_FillBrushCollection.Clear();
  2598. return CSSHelpers::BParseFillBrushCollection( &m_FillBrushCollection, pchString, NULL );
  2599. }
  2600. // called when we are ready to apply any scaling factor to the values
  2601. virtual void ApplyUIScaleFactor( float flScaleFactor )
  2602. {
  2603. m_FillBrushCollection.ScaleLengthValues( flScaleFactor );
  2604. }
  2605. // Gets string representation of property
  2606. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  2607. {
  2608. CSSHelpers::AppendFillBrushCollection( pfmtBuffer, m_FillBrushCollection );
  2609. }
  2610. // Comparison function
  2611. virtual bool operator==(const CStyleProperty &other) const
  2612. {
  2613. if( GetPropertySymbol() != other.GetPropertySymbol() )
  2614. return false;
  2615. const CStylePropertyFillColor &rhs = (const CStylePropertyFillColor&)other;
  2616. return (m_FillBrushCollection == rhs.m_FillBrushCollection);
  2617. }
  2618. // Layout pieces that can be invalidated when the property is applied to a panel
  2619. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  2620. #ifdef DBGFLAG_VALIDATE
  2621. virtual void Validate( CValidator &validator, const tchar *pchName )
  2622. {
  2623. VALIDATE_SCOPE();
  2624. ValidateObj( m_FillBrushCollection );
  2625. CStyleProperty::Validate( validator, pchName );
  2626. }
  2627. #endif
  2628. CFillBrushCollection m_FillBrushCollection;
  2629. };
  2630. //-----------------------------------------------------------------------------
  2631. // Purpose: foreground color property
  2632. //-----------------------------------------------------------------------------
  2633. class CStylePropertyForegroundColor : public CStylePropertyFillColor
  2634. {
  2635. public:
  2636. static const CStyleSymbol symbol;
  2637. CStylePropertyForegroundColor() : CStylePropertyFillColor( CStylePropertyForegroundColor::symbol )
  2638. {
  2639. }
  2640. // Return a description for this property which will be shown in the debugger
  2641. virtual const char *GetDescription( CStyleSymbol symProperty )
  2642. {
  2643. return "Sets the foreground fill color/gradient/combination for a panel. This color is the color used to render text within the panel.<br><br>"
  2644. "<b>Examples:</b>"
  2645. "<pre>"
  2646. "color: #FFFFFFFF;\n"
  2647. "color: gradient( linear, 0% 0%, 0% 100%, from( #cbcbcbff ), to( #a0a0a0a0 ) );"
  2648. "</pre>";
  2649. }
  2650. // Parses string and sets value
  2651. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2652. {
  2653. bool bResult = CStylePropertyFillColor::BSetFromString( symParsedName, pchString );
  2654. #ifdef _DEBUG
  2655. const CUtlVectorFixed< CFillBrushCollection::FillBrush_t, MAX_FILL_BRUSHES_PER_COLLECTION > &vecBrushes = m_FillBrushCollection.AccessBrushes();
  2656. FOR_EACH_VEC( vecBrushes, i )
  2657. {
  2658. AssertMsg( vecBrushes[i].m_Brush.GetType() != CFillBrush::k_EStrokeTypeParticleSystem, "Particle systems not supported as foreground color, only background. Won't render." );
  2659. }
  2660. #endif
  2661. return bResult;
  2662. }
  2663. };
  2664. //-----------------------------------------------------------------------------
  2665. // Purpose: 3D transform properties
  2666. //-----------------------------------------------------------------------------
  2667. class CStylePropertyTransform3D : public CStyleProperty
  2668. {
  2669. public:
  2670. static const CStyleSymbol symbol;
  2671. static inline VMatrix GetDefault() { return VMatrix::GetIdentityMatrix(); }
  2672. CStylePropertyTransform3D() : CStyleProperty( CStylePropertyTransform3D::symbol )
  2673. {
  2674. m_bDirty = true;
  2675. m_bInterpolated = false;
  2676. m_Matrix = VMatrix::GetIdentityMatrix();
  2677. m_flCachedParentWidth = 0.0f;
  2678. m_flCachedParentHeight = 0.0f;
  2679. };
  2680. virtual ~CStylePropertyTransform3D()
  2681. {
  2682. m_vecTransforms.PurgeAndDeleteElements();
  2683. }
  2684. virtual void MergeTo( CStyleProperty *pTarget ) const
  2685. {
  2686. Assert( !m_bInterpolated );
  2687. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  2688. {
  2689. AssertMsg( false, "Mismatched types to CStylePropertyTransform3D::MergeTo" );
  2690. return;
  2691. }
  2692. CStyleProperty::MergeTo( pTarget );
  2693. CStylePropertyTransform3D *p = (CStylePropertyTransform3D *)pTarget;
  2694. p->m_bDirty = true;
  2695. p->m_Matrix = m_Matrix;
  2696. p->m_vecTransforms.EnsureCapacity( p->m_vecTransforms.Count() + m_vecTransforms.Count() );
  2697. FOR_EACH_VEC( m_vecTransforms, i )
  2698. {
  2699. p->m_vecTransforms.AddToTail( m_vecTransforms[i]->Clone() );
  2700. }
  2701. }
  2702. // Can this property support animation?
  2703. virtual bool BCanTransition() { return true; }
  2704. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  2705. virtual bool BAffectsCompositionOnly() { return true; }
  2706. // Interpolation func for animation of this property
  2707. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  2708. bool BHasNon2DTransforms()
  2709. {
  2710. FOR_EACH_VEC( m_vecTransforms, i )
  2711. {
  2712. if( !m_vecTransforms[i]->BOnlyImpacts2DValues() )
  2713. return true;
  2714. }
  2715. return false;
  2716. }
  2717. VMatrix GetTransformMatrix( float flParentWidth, float flParentHeight ) const
  2718. {
  2719. // If dirty, or if called with new width/height (and not interpolated, because once interpolated we can't recompute values), then recompute the matrix
  2720. // with the specified width/height for the parent
  2721. if( m_bDirty || (!m_bInterpolated && (fabs( flParentWidth - m_flCachedParentWidth ) > 0.0001f || fabs( flParentHeight - m_flCachedParentHeight ) > 0.0001f ) ) )
  2722. {
  2723. // Should never be "dirty" when interpolated, this checks that
  2724. Assert( !m_bInterpolated );
  2725. m_flCachedParentWidth = flParentWidth;
  2726. m_flCachedParentHeight = flParentHeight;
  2727. m_bDirty = false;
  2728. m_Matrix = VMatrix::GetIdentityMatrix();
  2729. FOR_EACH_VEC( m_vecTransforms, i )
  2730. {
  2731. m_Matrix = m_vecTransforms[i]->GetTransformMatrix( flParentWidth, flParentHeight ) * m_Matrix;
  2732. }
  2733. }
  2734. return m_Matrix;
  2735. }
  2736. void AddTransform3D( CTransform3D *pTransform )
  2737. {
  2738. if( !pTransform )
  2739. {
  2740. Assert( pTransform );
  2741. return;
  2742. }
  2743. Assert( !m_bInterpolated );
  2744. m_bDirty = true;
  2745. m_vecTransforms.AddToTail( pTransform );
  2746. }
  2747. // Parses string and sets value
  2748. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2749. {
  2750. Assert( !m_bInterpolated );
  2751. m_bDirty = true;
  2752. m_vecTransforms.PurgeAndDeleteElements();
  2753. // special case none
  2754. if( V_stricmp( pchString, "none" ) == 0 )
  2755. return true;
  2756. // space separated string of transform-functions
  2757. while( pchString[0] != '\0' )
  2758. {
  2759. CTransform3D *pTransform = NULL;
  2760. if( !CSSHelpers::BParseTransformFunction( &pTransform, pchString, &pchString ) )
  2761. return false;
  2762. Assert( pTransform );
  2763. AddTransform3D( pTransform );
  2764. pchString = CSSHelpers::SkipSpaces( pchString );
  2765. }
  2766. return true;
  2767. }
  2768. // called when we are ready to apply any scaling factor to the values
  2769. virtual void ApplyUIScaleFactor( float flScaleFactor )
  2770. {
  2771. if( flScaleFactor == 1.0f )
  2772. return;
  2773. if( !m_bInterpolated )
  2774. {
  2775. FOR_EACH_VEC( m_vecTransforms, i )
  2776. {
  2777. m_vecTransforms[i]->ScaleLengthValues( flScaleFactor );
  2778. m_bDirty = true;
  2779. }
  2780. }
  2781. else
  2782. {
  2783. if( m_Matrix.IsIdentity() )
  2784. return;
  2785. // Can't make an interpolated matrix dirty as we don't have data to recreate it fully, must
  2786. // decompose and scale the appropriate values that way
  2787. DecomposedMatrix_t current = DecomposeTransformMatrix( m_Matrix );
  2788. current.m_flTranslationXYZ[0] *= flScaleFactor;
  2789. current.m_flTranslationXYZ[1] *= flScaleFactor;
  2790. current.m_flTranslationXYZ[2] *= flScaleFactor;
  2791. m_Matrix = RecomposeTransformMatrix( current );
  2792. }
  2793. }
  2794. // Gets string representation of property
  2795. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  2796. {
  2797. if( m_vecTransforms.Count() == 0 )
  2798. {
  2799. pfmtBuffer->Append( "none" );
  2800. return;
  2801. }
  2802. FOR_EACH_VEC( m_vecTransforms, i )
  2803. {
  2804. if( i > 0 )
  2805. pfmtBuffer->Append( "\n" );
  2806. CSSHelpers::AppendTransform( pfmtBuffer, m_vecTransforms[i] );
  2807. }
  2808. }
  2809. // Return a description for this property which will be shown in the debugger
  2810. virtual const char *GetDescription( CStyleSymbol symProperty )
  2811. {
  2812. return "Sets the transforms to apply to the panel in 2d or 3d space. You can combine various transforms (comma separated) "
  2813. "and they will be applied in order to create a 4x4 3d transform matrix. The possible operations are: translate3d( x, y, z ), "
  2814. "translatex( x ), translatey( y ), translatez( z ), scale3d( x, y, z), rotate3d( x, y, z ), rotatex( x ), rotatey( y ), rotatez( z ).<br><br>"
  2815. "<b>Examples:</b>"
  2816. "<pre>"
  2817. "transform: translate3d( -100px, -100px, 0px );\n"
  2818. "transform: rotateZ( -32deg ) rotateX( 30deg ) translate3d( 125px, 520px, 230px );"
  2819. "</pre>";
  2820. }
  2821. // Comparison function
  2822. #ifdef WIN32
  2823. #pragma optimize( "", off )
  2824. #endif
  2825. virtual bool operator==(const CStyleProperty &other) const
  2826. {
  2827. if( GetPropertySymbol() != other.GetPropertySymbol() )
  2828. return false;
  2829. const CStylePropertyTransform3D &rhs = (const CStylePropertyTransform3D&)other;
  2830. if( m_bInterpolated || rhs.m_bInterpolated )
  2831. {
  2832. AssertMsg( false, "Can't compare two CStylePropertyTransform3D that have been interpolated" );
  2833. return false;
  2834. }
  2835. if( m_vecTransforms.Count() != rhs.m_vecTransforms.Count() )
  2836. return false;
  2837. FOR_EACH_VEC( m_vecTransforms, i )
  2838. {
  2839. CTransform3D *pLHS = m_vecTransforms[i];
  2840. CTransform3D *pRHS = rhs.m_vecTransforms[i];
  2841. ETransform3DType eType1 = pLHS->GetType();
  2842. Assert( eType1 == k_ETransform3DRotate || eType1 == k_ETransform3DTranslate || eType1 == k_ETransform3DScale );
  2843. ETransform3DType eType2 = pRHS->GetType();
  2844. Assert( eType2 == k_ETransform3DRotate || eType2 == k_ETransform3DTranslate || eType2 == k_ETransform3DScale );
  2845. if( *pLHS != *pRHS )
  2846. return false;
  2847. }
  2848. return true;
  2849. }
  2850. #ifdef WIN32
  2851. #pragma optimize( "", on )
  2852. #endif
  2853. // Layout pieces that can be invalidated when the property is applied to a panel
  2854. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  2855. #ifdef DBGFLAG_VALIDATE
  2856. virtual void Validate( CValidator &validator, const tchar *pchName )
  2857. {
  2858. VALIDATE_SCOPE();
  2859. ValidateObj( m_vecTransforms );
  2860. FOR_EACH_VEC( m_vecTransforms, i )
  2861. {
  2862. validator.ClaimMemory( m_vecTransforms[i] );
  2863. }
  2864. CStyleProperty::Validate( validator, pchName );
  2865. }
  2866. #endif
  2867. private:
  2868. CUtlVector<CTransform3D *> m_vecTransforms;
  2869. mutable float m_flCachedParentWidth;
  2870. mutable float m_flCachedParentHeight;
  2871. mutable bool m_bDirty;
  2872. mutable VMatrix m_Matrix;
  2873. bool m_bInterpolated; // once interpolated, only m_Matrix will be set. m_vecTransforms will be empty.
  2874. };
  2875. //-----------------------------------------------------------------------------
  2876. // Purpose: Transition property
  2877. //-----------------------------------------------------------------------------
  2878. class CStylePropertyTransitionProperties : public CStyleProperty
  2879. {
  2880. public:
  2881. static const CStyleSymbol symbol;
  2882. static const CStyleSymbol symbolProperty;
  2883. static const CStyleSymbol symbolDuration;
  2884. static const CStyleSymbol symbolTiming;
  2885. static const CStyleSymbol symbolDelay;
  2886. CStylePropertyTransitionProperties() : CStyleProperty( CStylePropertyTransitionProperties::symbol ) { m_bImmediate = false; }
  2887. virtual void MergeTo( CStyleProperty *pTarget ) const
  2888. {
  2889. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  2890. {
  2891. AssertMsg( false, "Mismatched types to CStylePropertyTransitionProperties::MergeTo" );
  2892. return;
  2893. }
  2894. CStyleProperty::MergeTo( pTarget );
  2895. CStylePropertyTransitionProperties *p = (CStylePropertyTransitionProperties *)pTarget;
  2896. // bugbug cboyd - need to think about what to do when property counts dont match. currently, we do not change the number of properties in the
  2897. // target when a property name has been set as that count should override ours
  2898. bool bPropertiesSet = (p->m_vecTransitionProperties.Count() > 0) ? p->m_vecTransitionProperties[0].m_symProperty.IsValid() : false;
  2899. // add properties to target to match our count
  2900. if( !bPropertiesSet )
  2901. {
  2902. p->m_vecTransitionProperties.EnsureCapacity( m_vecTransitionProperties.Count() );
  2903. for( int i = p->m_vecTransitionProperties.Count(); i < m_vecTransitionProperties.Count(); i++ )
  2904. p->AddNewProperty();
  2905. }
  2906. // set all unset properties on target
  2907. FOR_EACH_VEC( m_vecTransitionProperties, i )
  2908. {
  2909. // we have more properties than the other guy. Stop processing.
  2910. if( bPropertiesSet && p->m_vecTransitionProperties.Count() - 1 < i )
  2911. break;
  2912. TransitionProperty_t &transOther = p->m_vecTransitionProperties[i];
  2913. const TransitionProperty_t &transUs = m_vecTransitionProperties[i];
  2914. if( !transOther.m_symProperty.IsValid() )
  2915. transOther.m_symProperty = transUs.m_symProperty;
  2916. if( transOther.m_flTransitionSeconds == k_flFloatNotSet )
  2917. transOther.m_flTransitionSeconds = transUs.m_flTransitionSeconds;
  2918. if( transOther.m_eTimingFunction == k_EAnimationUnset )
  2919. {
  2920. transOther.m_eTimingFunction = transUs.m_eTimingFunction;
  2921. transOther.m_CubicBezier = transUs.m_CubicBezier;
  2922. }
  2923. if( transOther.m_flTransitionDelaySeconds == k_flFloatNotSet )
  2924. transOther.m_flTransitionDelaySeconds = transUs.m_flTransitionDelaySeconds;
  2925. }
  2926. if( !p->m_bImmediate )
  2927. p->m_bImmediate = m_bImmediate;
  2928. }
  2929. virtual bool BCanTransition() { return false; }
  2930. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  2931. void AddNewProperty()
  2932. {
  2933. int iVec = m_vecTransitionProperties.AddToTail();
  2934. TransitionProperty_t &transition = m_vecTransitionProperties[iVec];
  2935. // copy other set properties forward
  2936. if( iVec == 0 )
  2937. {
  2938. transition.m_eTimingFunction = k_EAnimationUnset;
  2939. Vector2D vec[4];
  2940. panorama::GetAnimationCurveControlPoints( k_EAnimationUnset, vec );
  2941. transition.m_CubicBezier.SetControlPoints( vec );
  2942. transition.m_flTransitionSeconds = k_flFloatNotSet;
  2943. transition.m_flTransitionDelaySeconds = k_flFloatNotSet;
  2944. }
  2945. else
  2946. {
  2947. transition.m_eTimingFunction = m_vecTransitionProperties[iVec - 1].m_eTimingFunction;
  2948. transition.m_CubicBezier = m_vecTransitionProperties[iVec - 1].m_CubicBezier;
  2949. transition.m_flTransitionSeconds = m_vecTransitionProperties[iVec - 1].m_flTransitionSeconds;
  2950. transition.m_flTransitionDelaySeconds = m_vecTransitionProperties[iVec - 1].m_flTransitionDelaySeconds;
  2951. }
  2952. }
  2953. // Parses string and sets value
  2954. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  2955. {
  2956. // need a temp buffer that we can terminate if !immediate is on the end of the string
  2957. char rgchBuffer[1024];
  2958. V_strncpy( rgchBuffer, pchString, V_ARRAYSIZE( rgchBuffer ) );
  2959. if( !BParseAndRemoveImmediate( m_bImmediate ? NULL : &m_bImmediate, rgchBuffer ) )
  2960. return false;
  2961. pchString = rgchBuffer;
  2962. if( symParsedName == symbol )
  2963. {
  2964. m_vecTransitionProperties.RemoveAll();
  2965. // transition property format: property duration timing-function delay [,*]
  2966. // we also support 'none'
  2967. if( V_strcmp( "none", pchString ) == 0 )
  2968. return true;
  2969. while( *pchString != '\0' )
  2970. {
  2971. TransitionProperty_t transition;
  2972. // get property name
  2973. char rgchProperty[k_nCSSPropertyNameMax];
  2974. if( !CSSHelpers::BParseIdent( rgchProperty, V_ARRAYSIZE( rgchProperty ), pchString, &pchString ) )
  2975. return false;
  2976. transition.m_symProperty = panorama::CStyleSymbol( rgchProperty );
  2977. if( !BCanPropertyTransition( transition.m_symProperty ) )
  2978. return false;
  2979. // get rest
  2980. if( !CSSHelpers::BParseTime( &transition.m_flTransitionSeconds, pchString, &pchString ) ||
  2981. !CSSHelpers::BParseTimingFunction( &transition.m_eTimingFunction, &transition.m_CubicBezier, pchString, &pchString ) ||
  2982. !CSSHelpers::BParseTime( &transition.m_flTransitionDelaySeconds, pchString, &pchString ) )
  2983. {
  2984. return false;
  2985. }
  2986. m_vecTransitionProperties.AddToTail( transition );
  2987. // see if there is another transition property
  2988. if( !CSSHelpers::BSkipComma( pchString, &pchString ) )
  2989. {
  2990. // end of list.. should be an empty string
  2991. pchString = CSSHelpers::SkipSpaces( pchString );
  2992. return (pchString[0] == '\0');
  2993. }
  2994. }
  2995. return true;
  2996. }
  2997. else if( symParsedName == symbolProperty )
  2998. {
  2999. // comma separated list of porperty names
  3000. CUtlVector< panorama::CStyleSymbol > vecProperties;
  3001. if( !CSSHelpers::BParseCommaSepList( &vecProperties, CSSHelpers::BParseIdentToStyleSymbol, pchString ) )
  3002. return false;
  3003. // if we have less properties specified than other params, error
  3004. if( m_vecTransitionProperties.Count() > vecProperties.Count() )
  3005. return false;
  3006. m_vecTransitionProperties.EnsureCapacity( vecProperties.Count() );
  3007. FOR_EACH_VEC( vecProperties, i )
  3008. {
  3009. if( vecProperties[i] == "none" )
  3010. continue;
  3011. if( !BCanPropertyTransition( vecProperties[i] ) )
  3012. return false;
  3013. // new property?
  3014. if( m_vecTransitionProperties.Count() <= i )
  3015. AddNewProperty();
  3016. m_vecTransitionProperties[i].m_symProperty = vecProperties[i];
  3017. }
  3018. return true;
  3019. }
  3020. else if( symParsedName == symbolDuration )
  3021. {
  3022. return BParseAndAddProperty( &TransitionProperty_t::m_flTransitionSeconds, CSSHelpers::BParseTime, pchString );
  3023. }
  3024. else if( symParsedName == symbolDelay )
  3025. {
  3026. return BParseAndAddProperty( &TransitionProperty_t::m_flTransitionDelaySeconds, CSSHelpers::BParseTime, pchString );
  3027. }
  3028. else if( symParsedName == symbolTiming )
  3029. {
  3030. return BParseAndAddTimingFunction( CSSHelpers::BParseTimingFunction, pchString );
  3031. }
  3032. return false;
  3033. }
  3034. bool BParseAndRemoveImmediate( bool *pbImmediate, char *pchString )
  3035. {
  3036. const char k_rgchImmediate[] = "!immediate";
  3037. char *pchImmediate = V_strstr( pchString, k_rgchImmediate );
  3038. if( !pchImmediate )
  3039. {
  3040. if( pbImmediate )
  3041. *pbImmediate = false;
  3042. return true;
  3043. }
  3044. pchString = pchImmediate + V_ARRAYSIZE( k_rgchImmediate ) - 1;
  3045. pchString = (char*)CSSHelpers::SkipSpaces( pchString );
  3046. if( pchString[0] != '\0' )
  3047. return false;
  3048. if( pbImmediate )
  3049. *pbImmediate = true;
  3050. pchImmediate[0] = '\0';
  3051. return true;
  3052. }
  3053. template < typename T >
  3054. bool BParseAndAddProperty( T TransitionProperty_t::*pProp, bool( *func )(T*, const char *, const char **), const char *pchString )
  3055. {
  3056. // parse comma separated list
  3057. CUtlVector< T > vec;
  3058. if( !CSSHelpers::BParseCommaSepList( &vec, func, pchString ) || vec.Count() == 0 )
  3059. return false;
  3060. FOR_EACH_VEC( vec, i )
  3061. {
  3062. // new property?
  3063. if( m_vecTransitionProperties.Count() <= i )
  3064. AddNewProperty();
  3065. m_vecTransitionProperties[i].*pProp = vec[i];
  3066. }
  3067. // if provided list is less than the total number of properties, fill in rest with last value
  3068. for( int i = vec.Count(); i < m_vecTransitionProperties.Count(); i++ )
  3069. m_vecTransitionProperties[i].*pProp = m_vecTransitionProperties[i - 1].*pProp;
  3070. return true;
  3071. }
  3072. bool BParseAndAddTimingFunction( bool( *func )(EAnimationTimingFunction *pTimeingFunc, CCubicBezierCurve< Vector2D > *pBezier, const char *, const char **), const char *pchString )
  3073. {
  3074. // parse comma separated list
  3075. CUtlVector< EAnimationTimingFunction > vec;
  3076. CUtlVector< CCubicBezierCurve< Vector2D > > vec2;
  3077. if( !CSSHelpers::BParseCommaSepList( &vec, &vec2, func, pchString ) || vec.Count() == 0 )
  3078. return false;
  3079. Assert( vec.Count() == vec2.Count() );
  3080. FOR_EACH_VEC( vec, i )
  3081. {
  3082. // new property?
  3083. if( m_vecTransitionProperties.Count() <= i )
  3084. AddNewProperty();
  3085. m_vecTransitionProperties[i].m_eTimingFunction = vec[i];
  3086. m_vecTransitionProperties[i].m_CubicBezier = vec2[i];
  3087. }
  3088. // if provided list is less than the total number of properties, fill in rest with last value
  3089. for( int i = vec.Count(); i < m_vecTransitionProperties.Count(); i++ )
  3090. {
  3091. m_vecTransitionProperties[i].m_eTimingFunction = m_vecTransitionProperties[i - 1].m_eTimingFunction;
  3092. m_vecTransitionProperties[i].m_CubicBezier = m_vecTransitionProperties[i - 1].m_CubicBezier;
  3093. }
  3094. return true;
  3095. }
  3096. bool BCanPropertyTransition( CStyleSymbol symProperty )
  3097. {
  3098. // make sure the property is valid, and is not an alias
  3099. if( !UIEngine()->UIStyleFactory()->BRegisteredProperty( symProperty ) )
  3100. return false;
  3101. // bugbug cboyd - need less expensive check for valid property symbol and if it supports transition
  3102. CStyleProperty *pStyleProperty = UIEngine()->UIStyleFactory()->CreateStyleProperty( symProperty );
  3103. if( !pStyleProperty )
  3104. return false;
  3105. bool bCanTransition = pStyleProperty->BCanTransition();
  3106. UIEngine()->UIStyleFactory()->FreeStyleProperty( pStyleProperty );
  3107. return bCanTransition;
  3108. }
  3109. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found by looking at lower weight styles
  3110. virtual bool BFullySet()
  3111. {
  3112. if( m_vecTransitionProperties.Count() < 1 )
  3113. return false;
  3114. // if the first transition property is fully set, all other transition properties should be set
  3115. TransitionProperty_t &transitionProperty = m_vecTransitionProperties[0];
  3116. return (transitionProperty.m_symProperty.IsValid() &&
  3117. transitionProperty.m_flTransitionSeconds != k_flFloatNotSet &&
  3118. transitionProperty.m_eTimingFunction != k_EAnimationUnset &&
  3119. transitionProperty.m_flTransitionDelaySeconds != k_flFloatNotSet);
  3120. }
  3121. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  3122. virtual void ResolveDefaultValues()
  3123. {
  3124. if( m_vecTransitionProperties.Count() < 1 )
  3125. return;
  3126. // if property names aren't set or transition time isn't set (would default to 0), remove all and exit
  3127. TransitionProperty_t &firstProperty = m_vecTransitionProperties[0];
  3128. if( !firstProperty.m_symProperty.IsValid() || firstProperty.m_flTransitionSeconds == k_flFloatNotSet )
  3129. {
  3130. m_vecTransitionProperties.RemoveAll();
  3131. return;
  3132. }
  3133. // default to 'ease' timing function and 0 delay
  3134. FOR_EACH_VEC( m_vecTransitionProperties, i )
  3135. {
  3136. TransitionProperty_t &transitionProperty = m_vecTransitionProperties[i];
  3137. if( transitionProperty.m_eTimingFunction == k_EAnimationUnset )
  3138. {
  3139. transitionProperty.m_eTimingFunction = k_EAnimationEase;
  3140. Vector2D vec[4];
  3141. panorama::GetAnimationCurveControlPoints( transitionProperty.m_eTimingFunction, vec );
  3142. transitionProperty.m_CubicBezier.SetControlPoints( vec );
  3143. }
  3144. if( transitionProperty.m_flTransitionDelaySeconds == k_flFloatNotSet )
  3145. transitionProperty.m_flTransitionDelaySeconds = 0;
  3146. }
  3147. }
  3148. // Gets string representation of property
  3149. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  3150. {
  3151. if( m_vecTransitionProperties.Count() == 0 )
  3152. {
  3153. pfmtBuffer->Append( "none" );
  3154. return;
  3155. }
  3156. FOR_EACH_VEC( m_vecTransitionProperties, i )
  3157. {
  3158. if( i > 0 )
  3159. pfmtBuffer->Append( ",\n" );
  3160. const TransitionProperty_t &transition = m_vecTransitionProperties[i];
  3161. pfmtBuffer->Append( transition.m_symProperty.String() );
  3162. pfmtBuffer->Append( " " );
  3163. CSSHelpers::AppendTime( pfmtBuffer, transition.m_flTransitionSeconds );
  3164. if( transition.m_eTimingFunction != k_EAnimationCustomBezier )
  3165. pfmtBuffer->AppendFormat( " %s ", PchNameFromEAnimationTimingFunction( transition.m_eTimingFunction ) );
  3166. else
  3167. pfmtBuffer->AppendFormat( " cubic-bezier( %1.3f, %1.3f, %1.3f, %1.3f ) ",
  3168. transition.m_CubicBezier.ControlPoint( 1 ).x,
  3169. transition.m_CubicBezier.ControlPoint( 1 ).y,
  3170. transition.m_CubicBezier.ControlPoint( 2 ).x,
  3171. transition.m_CubicBezier.ControlPoint( 2 ).y );
  3172. CSSHelpers::AppendTime( pfmtBuffer, transition.m_flTransitionDelaySeconds );
  3173. }
  3174. }
  3175. // Return a description for this property which will be shown in the debugger
  3176. virtual const char *GetDescription( CStyleSymbol symProperty )
  3177. {
  3178. if( symProperty == symbol )
  3179. {
  3180. return "Specifies which properties should transition smoothly to new values if a class/pseudo class changes the styles. "
  3181. "Also specifies duration, timing function, and delay. Valid timing functions are: ease, ease-in, ease-out, ease-in-out, linear.<br><br>"
  3182. "<b>Example:</b>"
  3183. "<pre>"
  3184. "transition: position 2.0s ease-in-out 0.0s, perspective-origin 1.2s ease-in-out 0.8s;"
  3185. "</pre>";
  3186. }
  3187. else if( symProperty == symbolProperty )
  3188. {
  3189. return "Specifies which properties should transition smoothly to new values if a class/pseudo class changes the styles.<br><br>"
  3190. "<b>Examples:</b>"
  3191. "<pre>"
  3192. "transition: position, transform, background-color;"
  3193. "</pre>";
  3194. }
  3195. else if( symProperty == symbolTiming )
  3196. {
  3197. return "Specifies the timing function to use for transition properties on this panel, if more than one comma delimited value is specified "
  3198. "then the values are applied to each property specified in 'transition-property' in order. If only one value is specified then "
  3199. "it applies to all the properties specified in transition-property. Valid timing functions are: ease, ease-in, ease-out, ease-in-out, linear.<br><br>"
  3200. "<b>Examples:</b>"
  3201. "<pre>"
  3202. "transition-timing-function: ease-in-out;\n"
  3203. "transition-timing-function: ease-in-out, linear;\n"
  3204. "transition-timing-function: cubic-bezier( 0.785, 0.385, 0.555, 1.505 );"
  3205. "</pre>";
  3206. }
  3207. else if( symProperty == symbolDuration )
  3208. {
  3209. return "Specifies the durating in seconds to use for transition properties on this panel, if more than one comma delimited value is specified "
  3210. "then the values are applied to each property specified in 'transition-property' in order. If only one value is specified then "
  3211. "it applies to all the properties specified in transition-property.<br><br>"
  3212. "<b>Examples:</b>"
  3213. "<pre>"
  3214. "transition-duration: 2.0s;\n"
  3215. "transition-duration: 2.0s, 1.2s, 1.2s, 4.0s, 2.0s;"
  3216. "</pre>";
  3217. }
  3218. else if( symProperty == symbolDelay )
  3219. {
  3220. return "Specifies the delay in seconds to use for transition properties on this panel, if more than one comma delimited value is specified "
  3221. "then the values are applied to each property specified in 'transition-property' in order. If only one value is specified then "
  3222. "it applies to all the properties specified in transition-property.<br><br>"
  3223. "<b>Examples:</b>"
  3224. "<pre>"
  3225. "transition-delay: 0.0s;\n"
  3226. "transition-delay: 0.0s, 1.2s;"
  3227. "</pre>";
  3228. }
  3229. return CStyleProperty::GetDescription( symProperty );
  3230. }
  3231. // Comparison function
  3232. virtual bool operator==(const CStyleProperty &other) const
  3233. {
  3234. if( GetPropertySymbol() != other.GetPropertySymbol() )
  3235. return false;
  3236. const CStylePropertyTransitionProperties &rhs = (const CStylePropertyTransitionProperties &)other;
  3237. if( m_vecTransitionProperties.Count() != rhs.m_vecTransitionProperties.Count() )
  3238. return false;
  3239. FOR_EACH_VEC( m_vecTransitionProperties, i )
  3240. {
  3241. if( m_vecTransitionProperties[i] != rhs.m_vecTransitionProperties[i] )
  3242. return false;
  3243. }
  3244. // should not compare immediate
  3245. return true;
  3246. }
  3247. // Layout pieces that can be invalidated when the property is applied to a panel
  3248. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  3249. // looks up transition data for a property
  3250. TransitionProperty_t *GetTransitionData( CStyleSymbol hSymbol )
  3251. {
  3252. FOR_EACH_VEC( m_vecTransitionProperties, i )
  3253. {
  3254. if( m_vecTransitionProperties[i].m_symProperty == hSymbol )
  3255. return &m_vecTransitionProperties[i];
  3256. }
  3257. return NULL;
  3258. }
  3259. #ifdef DBGFLAG_VALIDATE
  3260. virtual void Validate( CValidator &validator, const tchar *pchName )
  3261. {
  3262. VALIDATE_SCOPE();
  3263. ValidateObj( m_vecTransitionProperties );
  3264. CStyleProperty::Validate( validator, pchName );
  3265. }
  3266. #endif
  3267. CUtlVector< TransitionProperty_t > m_vecTransitionProperties;
  3268. bool m_bImmediate;
  3269. };
  3270. //-----------------------------------------------------------------------------
  3271. // Purpose: background-color property
  3272. //-----------------------------------------------------------------------------
  3273. class CStylePropertyBackgroundColor : public CStylePropertyFillColor
  3274. {
  3275. public:
  3276. static const CStyleSymbol symbol;
  3277. CStylePropertyBackgroundColor() : CStylePropertyFillColor( CStylePropertyBackgroundColor::symbol )
  3278. {
  3279. }
  3280. bool BHasAnyParticleSystems()
  3281. {
  3282. return m_FillBrushCollection.GetNumParticleSystems() > 0 ? true : false;
  3283. }
  3284. // Return a description for this property which will be shown in the debugger
  3285. virtual const char *GetDescription( CStyleSymbol symProperty )
  3286. {
  3287. return "Sets the background fill color/gradient/combination for a panel.<br><br>"
  3288. "<b>Examples:</b>"
  3289. "<pre>"
  3290. "background-color: #FFFFFFFF;\n"
  3291. "background-color: gradient( linear, 0% 0%, 0% 100%, from( #fbfbfbff ), to( #c0c0c0c0 ) );\n"
  3292. "background-color: gradient( linear, 0% 0%, 0% 100%, from( #fbfbfbff ), color-stop( 0.3, #ebebebff ), to( #c0c0c0c0 ) );\n"
  3293. "background-color: gradient( radial, 50% 50%, 0% 0%, 80% 80%, from( #00ff00ff ), to( #0000ffff ) );\n"
  3294. "background-color: #0d1c22ff, gradient( radial, 100% -0%, 100px -40px, 320% 270%, from( #3a464bff ), color-stop( 0.23, #0d1c22ff ), to( #0d1c22ff ) );"
  3295. "</pre>";
  3296. }
  3297. };
  3298. //-----------------------------------------------------------------------------
  3299. // Purpose: border property
  3300. //-----------------------------------------------------------------------------
  3301. class CStylePropertyBorder : public CStyleProperty
  3302. {
  3303. public:
  3304. static const CStyleSymbol symbol;
  3305. static const CStyleSymbol symTop;
  3306. static const CStyleSymbol symRight;
  3307. static const CStyleSymbol symBottom;
  3308. static const CStyleSymbol symLeft;
  3309. static const CStyleSymbol symStyle;
  3310. static const CStyleSymbol symTopStyle;
  3311. static const CStyleSymbol symRightStyle;
  3312. static const CStyleSymbol symBottomStyle;
  3313. static const CStyleSymbol symLeftStyle;
  3314. static const CStyleSymbol symWidth;
  3315. static const CStyleSymbol symTopWidth;
  3316. static const CStyleSymbol symRightWidth;
  3317. static const CStyleSymbol symBottomWidth;
  3318. static const CStyleSymbol symLeftWidth;
  3319. static const CStyleSymbol symColor;
  3320. static const CStyleSymbol symTopColor;
  3321. static const CStyleSymbol symRightColor;
  3322. static const CStyleSymbol symBottomColor;
  3323. static const CStyleSymbol symLeftColor;
  3324. CStylePropertyBorder() : CStyleProperty( CStylePropertyBorder::symbol )
  3325. {
  3326. for( int i = 0; i < 4; i++ )
  3327. {
  3328. m_rgBorderStyle[i] = k_EBorderStyleUnset;
  3329. m_rgColorsSet[i] = false;
  3330. m_rgBorderColor[i] = Color( 0, 0, 0, 0 );
  3331. }
  3332. }
  3333. virtual void MergeTo( CStyleProperty *pTarget ) const
  3334. {
  3335. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  3336. {
  3337. AssertMsg( false, "Mismatched types to CStylePropertyBorder::MergeTo" );
  3338. return;
  3339. }
  3340. CStyleProperty::MergeTo( pTarget );
  3341. CStylePropertyBorder *pBorderTarget = (CStylePropertyBorder*)pTarget;
  3342. for( int i = 0; i < 4; i++ )
  3343. {
  3344. if( pBorderTarget->m_rgBorderStyle[i] == k_EBorderStyleUnset )
  3345. pBorderTarget->m_rgBorderStyle[i] = m_rgBorderStyle[i];
  3346. if( !pBorderTarget->m_rgBorderWidth[i].IsSet() )
  3347. pBorderTarget->m_rgBorderWidth[i] = m_rgBorderWidth[i];
  3348. if( pBorderTarget->m_rgColorsSet[i] == false )
  3349. {
  3350. pBorderTarget->m_rgColorsSet[i] = m_rgColorsSet[i];
  3351. pBorderTarget->m_rgBorderColor[i] = m_rgBorderColor[i];
  3352. }
  3353. }
  3354. }
  3355. // Can this property support animation?
  3356. virtual bool BCanTransition() { return true; }
  3357. // Interpolation func for animation of this property
  3358. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  3359. // Parses string and sets value
  3360. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  3361. {
  3362. if( symParsedName == symbol )
  3363. {
  3364. // shorthand for width, style, color
  3365. if( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[0], pchString, &pchString ) )
  3366. {
  3367. m_rgBorderWidth[1] = m_rgBorderWidth[2] = m_rgBorderWidth[3] = m_rgBorderWidth[0];
  3368. if( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[0], pchString, &pchString ) )
  3369. {
  3370. m_rgBorderStyle[1] = m_rgBorderStyle[2] = m_rgBorderStyle[3] = m_rgBorderStyle[0];
  3371. if( CSSHelpers::BParseColor( &m_rgBorderColor[0], pchString, &pchString ) )
  3372. {
  3373. m_rgColorsSet[0] = m_rgColorsSet[1] = m_rgColorsSet[2] = m_rgColorsSet[3] = true;
  3374. m_rgBorderColor[1] = m_rgBorderColor[2] = m_rgBorderColor[3] = m_rgBorderColor[0];
  3375. }
  3376. }
  3377. // bugbug - should reset all values, as well as border-image and border-radius as well, see
  3378. // http://www.w3.org/TR/css3-background/#ltborder-widthgt
  3379. return true;
  3380. }
  3381. return false;
  3382. }
  3383. else if ( symParsedName == symTop )
  3384. {
  3385. return BParseSingleEdgeShortcutProperty( 0, pchString );
  3386. }
  3387. else if ( symParsedName == symRight )
  3388. {
  3389. return BParseSingleEdgeShortcutProperty( 1, pchString );
  3390. }
  3391. else if ( symParsedName == symBottom )
  3392. {
  3393. return BParseSingleEdgeShortcutProperty( 2, pchString );
  3394. }
  3395. else if ( symParsedName == symLeft )
  3396. {
  3397. return BParseSingleEdgeShortcutProperty( 3, pchString );
  3398. }
  3399. else if( symParsedName == symWidth )
  3400. {
  3401. // "top right bottom left" in order
  3402. if( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[0], pchString, &pchString ) )
  3403. {
  3404. if( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[1], pchString, &pchString ) )
  3405. {
  3406. if( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[2], pchString, &pchString ) )
  3407. {
  3408. if( !CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[3], pchString, &pchString ) )
  3409. m_rgBorderWidth[3] = m_rgBorderWidth[1];
  3410. }
  3411. else
  3412. {
  3413. m_rgBorderWidth[2] = m_rgBorderWidth[0];
  3414. m_rgBorderWidth[3] = m_rgBorderWidth[1];
  3415. }
  3416. }
  3417. else
  3418. {
  3419. m_rgBorderWidth[1] = m_rgBorderWidth[2] = m_rgBorderWidth[3] = m_rgBorderWidth[0];
  3420. }
  3421. return true;
  3422. }
  3423. return false;
  3424. }
  3425. else if( symParsedName == symTopWidth )
  3426. {
  3427. if( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[0], pchString, &pchString ) )
  3428. {
  3429. return true;
  3430. }
  3431. return false;
  3432. }
  3433. else if( symParsedName == symRightWidth )
  3434. {
  3435. if( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[1], pchString, &pchString ) )
  3436. {
  3437. return true;
  3438. }
  3439. return false;
  3440. }
  3441. else if( symParsedName == symBottomWidth )
  3442. {
  3443. if( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[2], pchString, &pchString ) )
  3444. {
  3445. return true;
  3446. }
  3447. return false;
  3448. }
  3449. else if( symParsedName == symLeftWidth )
  3450. {
  3451. if( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[3], pchString, &pchString ) )
  3452. {
  3453. return true;
  3454. }
  3455. return false;
  3456. }
  3457. else if( symParsedName == symStyle )
  3458. {
  3459. // "top right bottom left" in order
  3460. if( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[0], pchString, &pchString ) )
  3461. {
  3462. if( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[1], pchString, &pchString ) )
  3463. {
  3464. if( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[2], pchString, &pchString ) )
  3465. {
  3466. if( !CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[3], pchString, &pchString ) )
  3467. m_rgBorderStyle[3] = m_rgBorderStyle[1];
  3468. }
  3469. else
  3470. {
  3471. m_rgBorderStyle[2] = m_rgBorderStyle[0];
  3472. m_rgBorderStyle[3] = m_rgBorderStyle[1];
  3473. }
  3474. }
  3475. else
  3476. {
  3477. m_rgBorderStyle[1] = m_rgBorderStyle[2] = m_rgBorderStyle[3] = m_rgBorderStyle[0];
  3478. }
  3479. return true;
  3480. }
  3481. return false;
  3482. }
  3483. else if( symParsedName == symTopStyle )
  3484. {
  3485. if( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[0], pchString, &pchString ) )
  3486. return true;
  3487. return false;
  3488. }
  3489. else if( symParsedName == symRightStyle )
  3490. {
  3491. if( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[1], pchString, &pchString ) )
  3492. return true;
  3493. return false;
  3494. }
  3495. else if( symParsedName == symBottomStyle )
  3496. {
  3497. if( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[2], pchString, &pchString ) )
  3498. return true;
  3499. return false;
  3500. }
  3501. else if( symParsedName == symLeftStyle )
  3502. {
  3503. if( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[3], pchString, &pchString ) )
  3504. return true;
  3505. return false;
  3506. }
  3507. else if( symParsedName == symColor )
  3508. {
  3509. // "top right bottom left" in order
  3510. if( CSSHelpers::BParseColor( &m_rgBorderColor[0], pchString, &pchString ) )
  3511. {
  3512. if( CSSHelpers::BParseColor( &m_rgBorderColor[1], pchString, &pchString ) )
  3513. {
  3514. if( CSSHelpers::BParseColor( &m_rgBorderColor[2], pchString, &pchString ) )
  3515. {
  3516. if( !CSSHelpers::BParseColor( &m_rgBorderColor[3], pchString, &pchString ) )
  3517. m_rgBorderColor[3] = m_rgBorderColor[1];
  3518. }
  3519. else
  3520. {
  3521. m_rgBorderColor[2] = m_rgBorderColor[0];
  3522. m_rgBorderColor[3] = m_rgBorderColor[1];
  3523. }
  3524. }
  3525. else
  3526. {
  3527. m_rgBorderColor[1] = m_rgBorderColor[2] = m_rgBorderColor[3] = m_rgBorderColor[0];
  3528. }
  3529. m_rgColorsSet[0] = m_rgColorsSet[1] = m_rgColorsSet[2] = m_rgColorsSet[3] = true;
  3530. return true;
  3531. }
  3532. return false;
  3533. }
  3534. else if( symParsedName == symTopColor )
  3535. {
  3536. if( CSSHelpers::BParseColor( &m_rgBorderColor[0], pchString, &pchString ) )
  3537. {
  3538. m_rgColorsSet[0] = true;
  3539. return true;
  3540. }
  3541. return false;
  3542. }
  3543. else if( symParsedName == symRightColor )
  3544. {
  3545. if( CSSHelpers::BParseColor( &m_rgBorderColor[1], pchString, &pchString ) )
  3546. {
  3547. m_rgColorsSet[1] = true;
  3548. return true;
  3549. }
  3550. return false;
  3551. }
  3552. else if( symParsedName == symBottomColor )
  3553. {
  3554. if( CSSHelpers::BParseColor( &m_rgBorderColor[2], pchString, &pchString ) )
  3555. {
  3556. m_rgColorsSet[2] = true;
  3557. return true;
  3558. }
  3559. return false;
  3560. }
  3561. else if( symParsedName == symLeftColor )
  3562. {
  3563. if( CSSHelpers::BParseColor( &m_rgBorderColor[3], pchString, &pchString ) )
  3564. {
  3565. m_rgColorsSet[3] = true;
  3566. return true;
  3567. }
  3568. return false;
  3569. }
  3570. return false;
  3571. }
  3572. // helper function to parse the shortcut property for a single edge (border-top, border-right, border-bottom, border-left)
  3573. bool BParseSingleEdgeShortcutProperty( int nEdgeIndex, const char *pchString )
  3574. {
  3575. // shorthand for width, style, color
  3576. if ( CSSHelpers::BParseIntoUILength( &m_rgBorderWidth[ nEdgeIndex ], pchString, &pchString ) )
  3577. {
  3578. if ( CSSHelpers::BParseBorderStyle( &m_rgBorderStyle[ nEdgeIndex ], pchString, &pchString ) )
  3579. {
  3580. if ( CSSHelpers::BParseColor( &m_rgBorderColor[ nEdgeIndex ], pchString, &pchString ) )
  3581. {
  3582. m_rgColorsSet[ nEdgeIndex ] = true;
  3583. }
  3584. }
  3585. return true;
  3586. }
  3587. return false;
  3588. }
  3589. // called when we are ready to apply any scaling factor to the values
  3590. virtual void ApplyUIScaleFactor( float flScaleFactor )
  3591. {
  3592. m_rgBorderWidth[0].ScaleLengthValue( flScaleFactor );
  3593. m_rgBorderWidth[1].ScaleLengthValue( flScaleFactor );
  3594. m_rgBorderWidth[2].ScaleLengthValue( flScaleFactor );
  3595. m_rgBorderWidth[3].ScaleLengthValue( flScaleFactor );
  3596. }
  3597. // Gets string representation of property
  3598. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  3599. {
  3600. // bugbug jmccaskey - this emits an invalid value for now... can't really put it all into just "border:"...
  3601. pfmtBuffer->Append( m_rgBorderStyle[0] == k_EBorderStyleSolid ? "solid " : "none " );
  3602. pfmtBuffer->Append( m_rgBorderStyle[1] == k_EBorderStyleSolid ? "solid " : "none " );
  3603. pfmtBuffer->Append( m_rgBorderStyle[2] == k_EBorderStyleSolid ? "solid " : "none " );
  3604. pfmtBuffer->Append( m_rgBorderStyle[3] == k_EBorderStyleSolid ? "solid " : "none " );
  3605. pfmtBuffer->Append( "/ " );
  3606. CSSHelpers::AppendUILength( pfmtBuffer, m_rgBorderWidth[0] );
  3607. pfmtBuffer->Append( " " );
  3608. CSSHelpers::AppendUILength( pfmtBuffer, m_rgBorderWidth[1] );
  3609. pfmtBuffer->Append( " " );
  3610. CSSHelpers::AppendUILength( pfmtBuffer, m_rgBorderWidth[2] );
  3611. pfmtBuffer->Append( " " );
  3612. CSSHelpers::AppendUILength( pfmtBuffer, m_rgBorderWidth[3] );
  3613. pfmtBuffer->Append( " " );
  3614. pfmtBuffer->AppendFormat( "/ " );
  3615. if( m_rgColorsSet[0] )
  3616. {
  3617. CSSHelpers::AppendColor( pfmtBuffer, m_rgBorderColor[0] );
  3618. pfmtBuffer->Append( " " );
  3619. }
  3620. else
  3621. pfmtBuffer->Append( "none " );
  3622. if( m_rgColorsSet[1] )
  3623. {
  3624. CSSHelpers::AppendColor( pfmtBuffer, m_rgBorderColor[1] );
  3625. pfmtBuffer->Append( " " );
  3626. }
  3627. else
  3628. pfmtBuffer->Append( "none " );
  3629. if( m_rgColorsSet[2] )
  3630. {
  3631. CSSHelpers::AppendColor( pfmtBuffer, m_rgBorderColor[2] );
  3632. pfmtBuffer->Append( " " );
  3633. }
  3634. else
  3635. pfmtBuffer->Append( "none " );
  3636. if( m_rgColorsSet[3] )
  3637. {
  3638. CSSHelpers::AppendColor( pfmtBuffer, m_rgBorderColor[3] );
  3639. pfmtBuffer->Append( " " );
  3640. }
  3641. else
  3642. pfmtBuffer->Append( "none " );
  3643. }
  3644. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  3645. // by looking at lower weight styles
  3646. virtual bool BFullySet()
  3647. {
  3648. for( int i = 0; i < 4; ++i )
  3649. {
  3650. if( m_rgBorderStyle[i] == k_EBorderStyleUnset )
  3651. return false;
  3652. if( !m_rgBorderWidth[i].IsSet() )
  3653. return false;
  3654. if( m_rgColorsSet[i] == false )
  3655. return false;
  3656. }
  3657. return true;
  3658. }
  3659. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  3660. virtual void ResolveDefaultValues()
  3661. {
  3662. for( int i = 0; i < 4; ++i )
  3663. {
  3664. if( !m_rgBorderWidth[i].IsSet() )
  3665. m_rgBorderWidth[i].SetLength( 0 );
  3666. if( m_rgBorderStyle[i] == k_EBorderStyleUnset )
  3667. m_rgBorderStyle[i] = k_EBorderStyleNone;
  3668. if( m_rgColorsSet[i] == false )
  3669. {
  3670. m_rgColorsSet[i] = true;
  3671. m_rgBorderColor[i] = Color( 0, 0, 0, 0 );
  3672. }
  3673. }
  3674. }
  3675. // Return a description for this property which will be shown in the debugger
  3676. virtual const char *GetDescription( CStyleSymbol symProperty )
  3677. {
  3678. if( symProperty == symbol )
  3679. {
  3680. return "Shorthand for setting panel border. Specify width, style, and color. Supported styles are: solid, none.<br><br>"
  3681. "<b>Examples:</b>"
  3682. "<pre>"
  3683. "border: 2px solid #111111FF;"
  3684. "</pre>";
  3685. }
  3686. else if ( symProperty == symTop )
  3687. {
  3688. return "Shorthand for setting the top panel border. Specify width, style, and color. Supported styles are: solid, none.<br><br>"
  3689. "<b>Examples:</b>"
  3690. "<pre>"
  3691. "border-top: 2px solid #111111FF;"
  3692. "</pre>";
  3693. }
  3694. else if ( symProperty == symRight )
  3695. {
  3696. return "Shorthand for setting the right panel border. Specify width, style, and color. Supported styles are: solid, none.<br><br>"
  3697. "<b>Examples:</b>"
  3698. "<pre>"
  3699. "border-right: 2px solid #111111FF;"
  3700. "</pre>";
  3701. }
  3702. else if ( symProperty == symBottom )
  3703. {
  3704. return "Shorthand for setting the bottom panel border. Specify width, style, and color. Supported styles are: solid, none.<br><br>"
  3705. "<b>Examples:</b>"
  3706. "<pre>"
  3707. "border-bottom: 2px solid #111111FF;"
  3708. "</pre>";
  3709. }
  3710. else if ( symProperty == symLeft )
  3711. {
  3712. return "Shorthand for setting the left panel border. Specify width, style, and color. Supported styles are: solid, none.<br><br>"
  3713. "<b>Examples:</b>"
  3714. "<pre>"
  3715. "border-left: 2px solid #111111FF;"
  3716. "</pre>";
  3717. }
  3718. else if ( symProperty == symColor )
  3719. {
  3720. return "Specifies border color for panel. If a single color value is set it applies to all sides, if 2 are set the first is top/bottom and "
  3721. "the second is left/right, if all four are set then they are top, right, bottom, left in order.<br><br>"
  3722. "<b>Examples:</b>"
  3723. "<pre>"
  3724. "border-color: #111111FF;\n"
  3725. "border-color: #FF0000FF #00FF00FF #0000FFFF #00FFFFFF;"
  3726. "</pre>";
  3727. }
  3728. else if( symProperty == symTopColor )
  3729. {
  3730. return "Specifies border color for the top edge of the panel. <br><br>"
  3731. "<b>Examples:</b>"
  3732. "<pre>"
  3733. "border-top-color: #111111FF;"
  3734. "</pre>";
  3735. }
  3736. else if( symProperty == symRightColor )
  3737. {
  3738. return "Specifies border color for the right edge of the panel. <br><br>"
  3739. "<b>Examples:</b>"
  3740. "<pre>"
  3741. "border-right-color: #111111FF;"
  3742. "</pre>";
  3743. }
  3744. else if( symProperty == symBottomColor )
  3745. {
  3746. return "Specifies border color for the bottom edge of the panel. <br><br>"
  3747. "<b>Examples:</b>"
  3748. "<pre>"
  3749. "border-bottom-color: #111111FF;"
  3750. "</pre>";
  3751. }
  3752. else if( symProperty == symLeftColor )
  3753. {
  3754. return "Specifies border color for the left edge of the panel. <br><br>"
  3755. "<b>Examples:</b>"
  3756. "<pre>"
  3757. "border-left-color: #111111FF;"
  3758. "</pre>";
  3759. }
  3760. else if( symProperty == symWidth )
  3761. {
  3762. return "Specifies border width for panel. If a single width value is set it applies to all sides, if 2 are set the first is top/bottom and "
  3763. "the second is left/right, if all four are set then they are top, right, bottom, left in order.<br><br>"
  3764. "<b>Examples:</b>"
  3765. "<pre>"
  3766. "border-width: 1px;'\n"
  3767. "border-width: 20px 1px 20px 1px;"
  3768. "</pre>";
  3769. }
  3770. else if( symProperty == symTopWidth )
  3771. {
  3772. return "Specifies border width for the top edge of the panel. <br><br>"
  3773. "<b>Examples:</b>"
  3774. "<pre>"
  3775. "border-top-width: 2px;"
  3776. "</pre>";
  3777. }
  3778. else if( symProperty == symRightWidth )
  3779. {
  3780. return "Specifies border width for the right edge of the panel. <br><br>"
  3781. "<b>Examples:</b>"
  3782. "<pre>"
  3783. "border-right-width: 2px;"
  3784. "</pre>";
  3785. }
  3786. else if( symProperty == symBottomWidth )
  3787. {
  3788. return "Specifies border width for the bottom edge of the panel. <br><br>"
  3789. "<b>Examples:</b>"
  3790. "<pre>"
  3791. "border-bottom-width: 2px;"
  3792. "</pre>";
  3793. }
  3794. else if( symProperty == symLeftWidth )
  3795. {
  3796. return "Specifies border width for the left edge of the panel. <br><br>"
  3797. "<b>Examples:</b>"
  3798. "<pre>"
  3799. "border-left-width: 2px;"
  3800. "</pre>";
  3801. }
  3802. else if( symProperty == symStyle )
  3803. {
  3804. return "Specifies border style for panel. If a single style value is set it applies to all sides, if 2 are set the first is top/bottom and "
  3805. "the second is left/right, if all four are set then they are top, right, bottom, left in order.<br><br>"
  3806. "<b>Examples:</b>"
  3807. "<pre>"
  3808. "border-style: solid;\n"
  3809. "border-style: solid none solid none;"
  3810. "</pre>";
  3811. }
  3812. else if( symProperty == symTopStyle )
  3813. {
  3814. return "Specifies border style for the top edge of the panel. <br><br>"
  3815. "<b>Examples:</b>"
  3816. "<pre>"
  3817. "border-top-style: solid;"
  3818. "</pre>";
  3819. }
  3820. else if( symProperty == symRightStyle )
  3821. {
  3822. return "Specifies border style for the right edge of the panel. <br><br>"
  3823. "<b>Examples:</b>"
  3824. "<pre>"
  3825. "border-right-style: solid;"
  3826. "</pre>";
  3827. }
  3828. else if( symProperty == symBottomStyle )
  3829. {
  3830. return "Specifies border style for the bottom edge of the panel. <br><br>"
  3831. "<b>Examples:</b>"
  3832. "<pre>"
  3833. "border-bottom-style: solid;"
  3834. "</pre>";
  3835. }
  3836. else if( symProperty == symLeftStyle )
  3837. {
  3838. return "Specifies border style for the left edge of the panel. <br><br>"
  3839. "<b>Examples:</b>"
  3840. "<pre>"
  3841. "border-left-style: solid;"
  3842. "</pre>";
  3843. }
  3844. return CStyleProperty::GetDescription( symProperty );
  3845. }
  3846. // Comparison function
  3847. virtual bool operator==(const CStyleProperty &other) const
  3848. {
  3849. if( GetPropertySymbol() != other.GetPropertySymbol() )
  3850. return false;
  3851. const CStylePropertyBorder &rhs = (const CStylePropertyBorder &)other;
  3852. if( V_memcmp( m_rgBorderStyle, rhs.m_rgBorderStyle, sizeof( m_rgBorderStyle ) ) != 0 )
  3853. return false;
  3854. for( int i = 0; i < V_ARRAYSIZE( m_rgBorderWidth ); i++ )
  3855. {
  3856. if( m_rgBorderWidth[i] != rhs.m_rgBorderWidth[i] )
  3857. return false;
  3858. }
  3859. if( V_memcmp( m_rgColorsSet, rhs.m_rgColorsSet, sizeof( m_rgColorsSet ) ) != 0 )
  3860. return false;
  3861. for( int i = 0; i < V_ARRAYSIZE( m_rgBorderColor ); i++ )
  3862. {
  3863. if( m_rgBorderColor[i] != rhs.m_rgBorderColor[i] )
  3864. return false;
  3865. }
  3866. return true;
  3867. }
  3868. // Layout pieces that can be invalidated when the property is applied to a panel
  3869. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  3870. {
  3871. if( !pCompareProperty )
  3872. return k_EStyleInvalidateLayoutSizeAndPosition;
  3873. const CStylePropertyBorder &rhs = (const CStylePropertyBorder &)*pCompareProperty;
  3874. if( m_rgBorderWidth[0] != rhs.m_rgBorderWidth[0] || m_rgBorderWidth[1] != rhs.m_rgBorderWidth[1]
  3875. || m_rgBorderWidth[2] != rhs.m_rgBorderWidth[2] || m_rgBorderWidth[3] != rhs.m_rgBorderWidth[3] )
  3876. {
  3877. return k_EStyleInvalidateLayoutSizeAndPosition;
  3878. }
  3879. return k_EStyleInvalidateLayoutNone;
  3880. }
  3881. EBorderStyle m_rgBorderStyle[4];
  3882. CUILength m_rgBorderWidth[4];
  3883. bool m_rgColorsSet[4];
  3884. Color m_rgBorderColor[4];
  3885. };
  3886. //-----------------------------------------------------------------------------
  3887. // Purpose: border radius property
  3888. //-----------------------------------------------------------------------------
  3889. class CStylePropertyBorderRadius : public CStyleProperty
  3890. {
  3891. public:
  3892. static const CStyleSymbol symbol;
  3893. static const CStyleSymbol topRightRadius;
  3894. static const CStyleSymbol bottomRightRadius;
  3895. static const CStyleSymbol bottomLeftRadius;
  3896. static const CStyleSymbol topLeftRadius;
  3897. CStylePropertyBorderRadius() : CStyleProperty( CStylePropertyBorderRadius::symbol )
  3898. {
  3899. }
  3900. virtual void MergeTo( CStyleProperty *pTarget ) const
  3901. {
  3902. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  3903. {
  3904. AssertMsg( false, "Mismatched types to CStylePropertyBorderRadius::MergeTo" );
  3905. return;
  3906. }
  3907. CStyleProperty::MergeTo( pTarget );
  3908. CStylePropertyBorderRadius *p = (CStylePropertyBorderRadius *)pTarget;
  3909. for( int i = 0; i < k_ECornerMax; ++i )
  3910. {
  3911. if( !p->m_rgCornerRaddi[i].m_HorizontalRadii.IsSet() )
  3912. p->m_rgCornerRaddi[i].m_HorizontalRadii = m_rgCornerRaddi[i].m_HorizontalRadii;
  3913. if( !p->m_rgCornerRaddi[i].m_VerticalRadii.IsSet() )
  3914. p->m_rgCornerRaddi[i].m_VerticalRadii = m_rgCornerRaddi[i].m_VerticalRadii;
  3915. }
  3916. }
  3917. // Can this property support animation?
  3918. virtual bool BCanTransition() { return true; }
  3919. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  3920. virtual bool BAffectsCompositionOnly() { return true; }
  3921. // Interpolation func for animation of this property
  3922. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ );
  3923. // Parses string and sets value
  3924. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  3925. {
  3926. if( symParsedName == symbol )
  3927. {
  3928. // horizontal before /, vertical after, vertical matches horizontal if unset
  3929. //[ <length> | <percentage> ]{1,4} [ / [ <length> | <percentage> ]{1,4} ]
  3930. CUILength topLeft;
  3931. CUILength topRight;
  3932. CUILength bottomRight;
  3933. CUILength bottomLeft;
  3934. if( !CSSHelpers::BParseIntoUILength( &topLeft, pchString, &pchString ) )
  3935. return false;
  3936. m_rgCornerRaddi[k_ECornerTopLeft].m_HorizontalRadii = topLeft;
  3937. if( !CSSHelpers::BParseIntoUILength( &topRight, pchString, &pchString ) )
  3938. {
  3939. // All horizontal values then equal topLeft
  3940. m_rgCornerRaddi[k_ECornerTopRight].m_HorizontalRadii = topLeft;
  3941. m_rgCornerRaddi[k_ECornerBottomRight].m_HorizontalRadii = topLeft;
  3942. m_rgCornerRaddi[k_ECornerBottomLeft].m_HorizontalRadii = topLeft;
  3943. }
  3944. else
  3945. {
  3946. m_rgCornerRaddi[k_ECornerTopRight].m_HorizontalRadii = topRight;
  3947. if( !CSSHelpers::BParseIntoUILength( &bottomRight, pchString, &pchString ) )
  3948. {
  3949. // Bottom right matches top left then, and bottom left matches top right
  3950. m_rgCornerRaddi[k_ECornerBottomRight].m_HorizontalRadii = topLeft;
  3951. m_rgCornerRaddi[k_ECornerBottomLeft].m_HorizontalRadii = topRight;
  3952. }
  3953. else
  3954. {
  3955. m_rgCornerRaddi[k_ECornerBottomRight].m_HorizontalRadii = bottomRight;
  3956. if( !CSSHelpers::BParseIntoUILength( &bottomLeft, pchString, &pchString ) )
  3957. {
  3958. // Bottom left matches top right then
  3959. m_rgCornerRaddi[k_ECornerBottomLeft].m_HorizontalRadii = topRight;
  3960. }
  3961. else
  3962. {
  3963. m_rgCornerRaddi[k_ECornerBottomLeft].m_HorizontalRadii = bottomLeft;
  3964. }
  3965. }
  3966. }
  3967. // Look for the / then, which will have vertical values after. If not found set them all
  3968. // to match horizontal.
  3969. pchString = CSSHelpers::SkipSpaces( pchString );
  3970. if( pchString[0] != '/' )
  3971. {
  3972. for( int i = 0; i < k_ECornerMax; ++i )
  3973. m_rgCornerRaddi[i].m_VerticalRadii = m_rgCornerRaddi[i].m_HorizontalRadii;
  3974. }
  3975. else
  3976. {
  3977. // Skip /
  3978. pchString++;
  3979. CSSHelpers::SkipSpaces( pchString );
  3980. // Insist we get one value after the /, having a trailing / with no vertical values is bogus
  3981. if( !CSSHelpers::BParseIntoUILength( &topLeft, pchString, &pchString ) )
  3982. {
  3983. // Set to match horizontal anyway so our values are kind of valid
  3984. for( int i = 0; i < k_ECornerMax; ++i )
  3985. m_rgCornerRaddi[i].m_VerticalRadii = m_rgCornerRaddi[i].m_HorizontalRadii;
  3986. return false;
  3987. }
  3988. m_rgCornerRaddi[k_ECornerTopLeft].m_VerticalRadii = topLeft;
  3989. if( !CSSHelpers::BParseIntoUILength( &topRight, pchString, &pchString ) )
  3990. {
  3991. // All vertical values then equal topLeft
  3992. m_rgCornerRaddi[k_ECornerTopRight].m_VerticalRadii = topLeft;
  3993. m_rgCornerRaddi[k_ECornerBottomRight].m_VerticalRadii = topLeft;
  3994. m_rgCornerRaddi[k_ECornerBottomLeft].m_VerticalRadii = topLeft;
  3995. }
  3996. else
  3997. {
  3998. m_rgCornerRaddi[k_ECornerTopRight].m_VerticalRadii = topRight;
  3999. if( !CSSHelpers::BParseIntoUILength( &bottomRight, pchString, &pchString ) )
  4000. {
  4001. // Bottom right matches top left then, and bottom left matches top right
  4002. m_rgCornerRaddi[k_ECornerBottomRight].m_VerticalRadii = topLeft;
  4003. m_rgCornerRaddi[k_ECornerBottomLeft].m_VerticalRadii = topRight;
  4004. }
  4005. else
  4006. {
  4007. m_rgCornerRaddi[k_ECornerBottomRight].m_VerticalRadii = bottomRight;
  4008. if( !CSSHelpers::BParseIntoUILength( &bottomLeft, pchString, &pchString ) )
  4009. {
  4010. // Bottom left matches top right then
  4011. m_rgCornerRaddi[k_ECornerBottomLeft].m_VerticalRadii = topRight;
  4012. }
  4013. else
  4014. {
  4015. m_rgCornerRaddi[k_ECornerBottomLeft].m_VerticalRadii = bottomLeft;
  4016. }
  4017. }
  4018. }
  4019. }
  4020. return true;
  4021. }
  4022. else
  4023. {
  4024. int iCorner = k_ECornerInvalid;
  4025. if( symParsedName == topLeftRadius )
  4026. iCorner = k_ECornerTopLeft;
  4027. else if( symParsedName == topRightRadius )
  4028. iCorner = k_ECornerTopRight;
  4029. else if( symParsedName == bottomRightRadius )
  4030. iCorner = k_ECornerBottomRight;
  4031. else if( symParsedName == bottomLeftRadius )
  4032. iCorner = k_ECornerBottomLeft;
  4033. if( iCorner == k_ECornerInvalid )
  4034. return false;
  4035. CUILength length;
  4036. if( !CSSHelpers::BParseIntoUILength( &length, pchString, &pchString ) )
  4037. return false;
  4038. m_rgCornerRaddi[iCorner].m_HorizontalRadii = length;
  4039. // Second value is optional, otherwise vertical matches horizontal
  4040. if( !CSSHelpers::BParseIntoUILength( &length, pchString, &pchString ) )
  4041. m_rgCornerRaddi[iCorner].m_VerticalRadii = m_rgCornerRaddi[iCorner].m_HorizontalRadii;
  4042. else
  4043. m_rgCornerRaddi[iCorner].m_VerticalRadii = length;
  4044. return true;
  4045. }
  4046. }
  4047. // called when we are ready to apply any scaling factor to the values
  4048. virtual void ApplyUIScaleFactor( float flScaleFactor )
  4049. {
  4050. m_rgCornerRaddi[k_ECornerTopLeft].m_HorizontalRadii.ScaleLengthValue( flScaleFactor );
  4051. m_rgCornerRaddi[k_ECornerTopLeft].m_VerticalRadii.ScaleLengthValue( flScaleFactor );
  4052. m_rgCornerRaddi[k_ECornerTopRight].m_HorizontalRadii.ScaleLengthValue( flScaleFactor );
  4053. m_rgCornerRaddi[k_ECornerTopRight].m_VerticalRadii.ScaleLengthValue( flScaleFactor );
  4054. m_rgCornerRaddi[k_ECornerBottomRight].m_HorizontalRadii.ScaleLengthValue( flScaleFactor );
  4055. m_rgCornerRaddi[k_ECornerBottomRight].m_VerticalRadii.ScaleLengthValue( flScaleFactor );
  4056. m_rgCornerRaddi[k_ECornerBottomLeft].m_HorizontalRadii.ScaleLengthValue( flScaleFactor );
  4057. m_rgCornerRaddi[k_ECornerBottomLeft].m_VerticalRadii.ScaleLengthValue( flScaleFactor );
  4058. }
  4059. // Gets string representation of property
  4060. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  4061. {
  4062. CSSHelpers::AppendUILength( pfmtBuffer, m_rgCornerRaddi[k_ECornerTopLeft].m_HorizontalRadii );
  4063. pfmtBuffer->Append( " " );
  4064. CSSHelpers::AppendUILength( pfmtBuffer, m_rgCornerRaddi[k_ECornerTopRight].m_HorizontalRadii );
  4065. pfmtBuffer->Append( " " );
  4066. CSSHelpers::AppendUILength( pfmtBuffer, m_rgCornerRaddi[k_ECornerBottomRight].m_HorizontalRadii );
  4067. pfmtBuffer->Append( " " );
  4068. CSSHelpers::AppendUILength( pfmtBuffer, m_rgCornerRaddi[k_ECornerBottomLeft].m_HorizontalRadii );
  4069. pfmtBuffer->AppendFormat( " / " );
  4070. CSSHelpers::AppendUILength( pfmtBuffer, m_rgCornerRaddi[k_ECornerTopLeft].m_VerticalRadii );
  4071. pfmtBuffer->Append( " " );
  4072. CSSHelpers::AppendUILength( pfmtBuffer, m_rgCornerRaddi[k_ECornerTopRight].m_VerticalRadii );
  4073. pfmtBuffer->Append( " " );
  4074. CSSHelpers::AppendUILength( pfmtBuffer, m_rgCornerRaddi[k_ECornerBottomRight].m_VerticalRadii );
  4075. pfmtBuffer->Append( " " );
  4076. CSSHelpers::AppendUILength( pfmtBuffer, m_rgCornerRaddi[k_ECornerBottomLeft].m_VerticalRadii );
  4077. }
  4078. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  4079. // by looking at lower weight styles
  4080. virtual bool BFullySet()
  4081. {
  4082. for( int i = 0; i < (int)k_ECornerMax; ++i )
  4083. {
  4084. if( !m_rgCornerRaddi[i].m_HorizontalRadii.IsSet() )
  4085. return false;
  4086. if( !m_rgCornerRaddi[i].m_VerticalRadii.IsSet() )
  4087. return false;
  4088. }
  4089. return true;
  4090. }
  4091. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  4092. virtual void ResolveDefaultValues()
  4093. {
  4094. for( int i = 0; i < (int)k_ECornerMax; ++i )
  4095. {
  4096. if( !m_rgCornerRaddi[i].m_HorizontalRadii.IsSet() )
  4097. m_rgCornerRaddi[i].m_HorizontalRadii.SetLength( 0 );
  4098. if( !m_rgCornerRaddi[i].m_VerticalRadii.IsSet() )
  4099. m_rgCornerRaddi[i].m_VerticalRadii.SetLength( 0 );
  4100. }
  4101. }
  4102. // Return a description for this property which will be shown in the debugger
  4103. virtual const char *GetDescription( CStyleSymbol symProperty )
  4104. {
  4105. if( symProperty == symbol )
  4106. {
  4107. return "Shorthand to set border radius for all corners at once. Border radius rounds off corners of the panel, adjusting the border to "
  4108. "smoothly round and also clipping background image/color and contents to the specified elliptical or circular values. In this shorthand "
  4109. "version you may specify a single value for all raddi, or horizontal / vertical separated by the '/' character. For both horizontal and "
  4110. "vertical you may specify 1 to 4 values in pixels or %, they will be taken in order as top-left, top-right, bottom-right, bottom-left radii "
  4111. "values.<br><br>"
  4112. "<b>Examples:</b>"
  4113. "<pre>"
  4114. "// 2 px circular corners on all sides\n"
  4115. "border-radius: 2px;\n"
  4116. "// Perfect circular or elliptical panel (circular if box was square)\n"
  4117. "border-radius: 50% / 50%;\n"
  4118. "// 2 px horizontal radii 4px vertical elliptical corners on all sides\n"
  4119. "border-radius: 2px / 4px;\n"
  4120. "// All corners fully specified \n"
  4121. "border-radius: 2px 3px 4px 2px / 2px 3px 3px 2px;"
  4122. "</pre>";
  4123. }
  4124. else if( symProperty == topLeftRadius )
  4125. {
  4126. return "Specifies border-radius for top-left corner which rounds off border and clips background/foreground content to rounded edge. "
  4127. "Takes 1 or 2 values in px or %, first value is horizontal radii for elliptical corner, second is vertical radii, if only one is specified "
  4128. "then horizontal/vertical will both be set and corner will be circular.<br><br>"
  4129. "<b>Examples:</b>"
  4130. "<pre>"
  4131. "border-top-left-radius: 2px 2px;\n"
  4132. "border-top-left-radius: 5%;"
  4133. "</pre>";
  4134. }
  4135. else if( symProperty == topRightRadius )
  4136. {
  4137. return "Specifies border-radius for top-right corner which rounds off border and clips background/foreground content to rounded edge. "
  4138. "Takes 1 or 2 values in px or %, first value is horizontal radii for elliptical corner, second is vertical radii, if only one is specified "
  4139. "then horizontal/vertical will both be set and corner will be circular.<br><br>"
  4140. "<b>Examples:</b>"
  4141. "<pre>"
  4142. "border-top-right-radius: 2px 2px;\n"
  4143. "border-top-right-radius: 5%;"
  4144. "</pre>";
  4145. }
  4146. else if( symProperty == bottomRightRadius )
  4147. {
  4148. return "Specifies border-radius for bottom-right corner which rounds off border and clips background/foreground content to rounded edge. "
  4149. "Takes 1 or 2 values in px or %, first value is horizontal radii for elliptical corner, second is vertical radii, if only one is specified "
  4150. "then horizontal/vertical will both be set and corner will be circular.<br><br>"
  4151. "<b>Examples:</b>"
  4152. "<pre>"
  4153. "border-bottom-right-radius: 2px 2px;\n"
  4154. "border-bottom-right-radius: 5%;"
  4155. "</pre>";
  4156. }
  4157. else if( symProperty == bottomLeftRadius )
  4158. {
  4159. return "Specifies border-radius for bottom-left corner which rounds off border and clips background/foreground content to rounded edge. "
  4160. "Takes 1 or 2 values in px or %, first value is horizontal radii for elliptical corner, second is vertical radii, if only one is specified "
  4161. "then horizontal/vertical will both be set and corner will be circular.<br><br>"
  4162. "<b>Examples:</b>"
  4163. "<pre>"
  4164. "border-bottom-left-radius: 2px 2px;\n"
  4165. "border-bottom-left-radius: 5%;"
  4166. "</pre>";
  4167. }
  4168. return CStyleProperty::GetDescription( symProperty );
  4169. }
  4170. // Comparison function
  4171. virtual bool operator==(const CStyleProperty &other) const
  4172. {
  4173. if( GetPropertySymbol() != other.GetPropertySymbol() )
  4174. return false;
  4175. const CStylePropertyBorderRadius &rhs = (const CStylePropertyBorderRadius &)other;
  4176. for( int i = 0; i < V_ARRAYSIZE( m_rgCornerRaddi ); i++ )
  4177. {
  4178. if( m_rgCornerRaddi[i] != rhs.m_rgCornerRaddi[i] )
  4179. return false;
  4180. }
  4181. return true;
  4182. }
  4183. // Layout pieces that can be invalidated when the property is applied to a panel
  4184. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  4185. enum ECorner
  4186. {
  4187. k_ECornerInvalid = -1,
  4188. k_ECornerTopLeft = 0,
  4189. k_ECornerTopRight,
  4190. k_ECornerBottomRight,
  4191. k_ECornerBottomLeft,
  4192. // Sentinel, for array iteration
  4193. k_ECornerMax
  4194. };
  4195. struct CornerRadii_t
  4196. {
  4197. CUILength m_HorizontalRadii;
  4198. CUILength m_VerticalRadii;
  4199. bool operator==(const CornerRadii_t &rhs) const { return (m_HorizontalRadii == rhs.m_HorizontalRadii && m_VerticalRadii == rhs.m_VerticalRadii); }
  4200. bool operator!=(const CornerRadii_t &rhs) const { return !(*this == rhs); }
  4201. };
  4202. CornerRadii_t m_rgCornerRaddi[k_ECornerMax];
  4203. };
  4204. //-----------------------------------------------------------------------------
  4205. // Purpose: border image property
  4206. //-----------------------------------------------------------------------------
  4207. class CStylePropertyBorderImage : public CStyleProperty
  4208. {
  4209. public:
  4210. // forward decl
  4211. struct BorderImageWidth_t;
  4212. static const CStyleSymbol symbol;
  4213. static const CStyleSymbol symImageSource;
  4214. static const CStyleSymbol symImageSlice;
  4215. static const CStyleSymbol symImageWidth;
  4216. static const CStyleSymbol symImageOutset;
  4217. static const CStyleSymbol symImageRepeat;
  4218. CStylePropertyBorderImage() : CStyleProperty( CStylePropertyBorderImage::symbol )
  4219. {
  4220. m_bFillCenter = false;
  4221. m_pImage = NULL;
  4222. m_bSlicesSet = false;
  4223. m_bWidthsSet = false;
  4224. m_bOutsetsSet = false;
  4225. m_bStretchSet = false;
  4226. for( int i = 0; i < 4; ++i )
  4227. {
  4228. m_Width[i].m_eType = k_EBorderImageWidthNumber;
  4229. m_Width[i].m_flValue = 1.0f;
  4230. m_Outsets[i].SetLength( 0.0f );
  4231. m_Slices[i].SetPercent( 100.0f );
  4232. }
  4233. m_Stretch[0] = k_EBorderImageStretchStretch;
  4234. m_Stretch[1] = k_EBorderImageStretchStretch;
  4235. }
  4236. virtual ~CStylePropertyBorderImage()
  4237. {
  4238. SAFE_RELEASE( m_pImage );
  4239. }
  4240. // Merge properties
  4241. virtual void MergeTo( CStyleProperty *pTarget ) const;
  4242. // Can this property support animation?
  4243. virtual bool BCanTransition() { return false; }
  4244. // Interpolation func for animation of this property
  4245. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { }
  4246. // Parses string and sets value
  4247. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString );
  4248. // Parse image source
  4249. bool BParseImageSource( const char *pchString, const char **pchAfterParse );
  4250. // Parse image slices
  4251. bool BParseImageSlices( const char *pchString, const char **pchAfterParse );
  4252. // Parse image widths
  4253. bool BParseImageWidths( const char *pchString, const char **pchAfterParse );
  4254. // Parse image outsets
  4255. bool BParseImageOutsets( const char *pchString, const char **pchAfterParse );
  4256. // Parse image repeats
  4257. bool BParseImageRepeats( const char *pchString, const char **pchAfterParse );
  4258. // Parse individual border image width
  4259. bool BParseImageWidth( BorderImageWidth_t *pWidth, const char *pchString, const char **pchAfterParse );
  4260. // Parse individual repeat
  4261. bool BParseRepeat( EBorderImageRepeatType *pRepeat, const char *pchString, const char **pchAfterParse );
  4262. // Gets string representation of property
  4263. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const;
  4264. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  4265. // by looking at lower weight styles
  4266. virtual bool BFullySet()
  4267. {
  4268. if( m_bSlicesSet && m_bStretchSet && m_bWidthsSet && m_bOutsetsSet && !m_sURLPath.IsEmpty() )
  4269. return true;
  4270. return false;
  4271. }
  4272. // called when we are ready to apply any scaling factor to the values
  4273. virtual void ApplyUIScaleFactor( float flScaleFactor );
  4274. // called when applied to a panel after comparing with set values
  4275. virtual void OnAppliedToPanel( IUIPanel *pPanel, float flScaleFactor );
  4276. // Return a description for this property which will be shown in the debugger
  4277. virtual const char *GetDescription( CStyleSymbol symProperty )
  4278. {
  4279. if( symProperty == symbol )
  4280. {
  4281. return "Shorthand for specifying all the border-image related properties at once.\n"
  4282. "Technical syntax is: &lt;border-image-source&gt; || &lt;border-image-slice&gt; [ / &lt;border-image-width&gt;? [ / &lt;border-image-outset&gt; ]? ]? || &lt;border-image-repeat&gt;, "
  4283. "see the explanations for individual properties for details on each.<br><br>"
  4284. "<b>Examples:</b>"
  4285. "<pre>"
  4286. "border-image: url( \"file://message_border.tga\" ) 25% repeat;\n"
  4287. "border-image: url( \"file://message_border.tga\" ) 25% / 1 / 20px repeat;"
  4288. "</pre>";
  4289. }
  4290. else if( symProperty == symImageSource )
  4291. {
  4292. return "Specifies the source image to use as the 9-slice border-image.<br><br>"
  4293. "<b>Examples:</b>"
  4294. "<pre>"
  4295. "border-image-source: url( \"file://message_border.tga\" );\n"
  4296. "border-image-source: url( \"http://store.steampowered.com/public/images/steam/message_border.tga\" );"
  4297. "</pre>";
  4298. }
  4299. else if( symProperty == symImageSlice )
  4300. {
  4301. return "Specifies the insets for top, right, bottom, and left (in order) slice offsets to use for slicing the source image into 9 regions. "
  4302. "The 'fill' keyword may optionally appear before or after the length values and specifies to draw the middle region as a fill for the body "
  4303. "background of the panel, without it the middle region will not be drawn.<br><br>"
  4304. "<b>Examples:</b>"
  4305. "<pre>"
  4306. "border-image-slice: 10px 10px 10px 10px;\n"
  4307. "border-image-slice: 20% 10% 20% 10% fill;"
  4308. "</pre>";
  4309. }
  4310. else if( symProperty == symImageWidth )
  4311. {
  4312. return "By default after slicing the image as specified in border-image-slice the 9 regions will be used to fill the space specified "
  4313. "by the standard border-width property. This border-image-width property may be used to override that and specify different widths. "
  4314. "The values appear in top, right, bottom, left order, the 2nd through 4th may be ommited and corresponding earlier values will be used. "
  4315. "Values may be straight floats which specify a multiple of the corresponding border-width value, a percentage (which is relative "
  4316. "to the size of the border image in the corresponding dimension), or 'auto' which means to use the intrinsic size of the corresponding "
  4317. "border-image-slice.<br><br>"
  4318. "<b>Examples:</b>"
  4319. "<pre>"
  4320. "border-image-width: 1 1 1 1;\n"
  4321. "border-image-slice: 50% 50% 50% 50%;\n"
  4322. "border-image-slice: auto;"
  4323. "</pre>";
  4324. }
  4325. else if( symProperty == symImageOutset )
  4326. {
  4327. return "Specifies the amount by which the border image should draw outside of the normal content/border box, this allows the border image "
  4328. "to extend into the margin area and draw outside the panels bounds. This may still result in clipping of the image by a parent panel if "
  4329. "the parents bounds are too close to the edges of the panel with the border-image. Values are specified as px or % in top, right, bottom, left "
  4330. "order with the 2nd through 4th values optional.<br><br>"
  4331. "<b>Examples:</b>"
  4332. "<pre>"
  4333. "border-image-outset: 0px;\n"
  4334. "border-image-outset: 20px 20px 20px 20px;"
  4335. "</pre>";
  4336. }
  4337. else if( symProperty == symImageRepeat )
  4338. {
  4339. return "Specifies how the top/right/bottom/left/middle images of the 9 slice regions are stretched to fit the available space. "
  4340. "Options are stretch, repeat, round or space. Stretch/repeat are self explanatory, round means tile (repeat) but scale first"
  4341. "to ensure that a whole number of tiles is used with no partial tile at the edge of the space, space means tile (repeat) but add "
  4342. "padding between tiles to ensure a whole number of tiles with no partial tile at the edge is needed.\n"
  4343. "Two values are specified, the first applies to how we stretch the top/middle/bottom horizontally to fill space, the second "
  4344. "applies to how we stretch the left/middle/right vertically to fill space.<br><br>"
  4345. "<b>Examples:</b>"
  4346. "<pre>"
  4347. "border-image-repeat: stretch stretch;\n"
  4348. "border-image-outset: repeat;\n"
  4349. "border-image-outset: round;\n"
  4350. "border-image-outset: stetch space;"
  4351. "</pre>";
  4352. }
  4353. return CStyleProperty::GetDescription( symProperty );
  4354. }
  4355. // Comparison function
  4356. virtual bool operator==(const CStyleProperty &other) const
  4357. {
  4358. if( GetPropertySymbol() != other.GetPropertySymbol() )
  4359. return false;
  4360. const CStylePropertyBorderImage &rhs = (const CStylePropertyBorderImage &)other;
  4361. if( m_sURLPath != rhs.m_sURLPath || m_bSlicesSet != rhs.m_bSlicesSet )
  4362. return false;
  4363. for( int i = 0; i < V_ARRAYSIZE( m_Slices ); i++ )
  4364. {
  4365. if( m_Slices[i] != rhs.m_Slices[i] )
  4366. return false;
  4367. }
  4368. if( m_bFillCenter != rhs.m_bFillCenter )
  4369. return false;
  4370. if( m_bWidthsSet != rhs.m_bWidthsSet )
  4371. return false;
  4372. if( m_bWidthsSet && V_memcmp( m_Width, rhs.m_Width, sizeof( m_Width ) ) != 0 )
  4373. return false;
  4374. if( m_bOutsetsSet != rhs.m_bOutsetsSet )
  4375. return false;
  4376. if( m_bOutsetsSet )
  4377. {
  4378. for( int i = 0; i < V_ARRAYSIZE( m_Outsets ); i++ )
  4379. {
  4380. if( m_Outsets[i] != rhs.m_Outsets[i] )
  4381. return false;
  4382. }
  4383. }
  4384. if( m_bStretchSet != rhs.m_bStretchSet )
  4385. return false;
  4386. if( m_bStretchSet && V_memcmp( m_Stretch, rhs.m_Stretch, sizeof( m_Stretch ) ) != 0 )
  4387. return false;
  4388. return true;
  4389. }
  4390. // Layout pieces that can be invalidated when the property is applied to a panel
  4391. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  4392. // border image source
  4393. IImageSource *m_pImage;
  4394. CUtlString m_sURLPath;
  4395. // border image slice
  4396. bool m_bSlicesSet;
  4397. CUILength m_Slices[4];
  4398. bool m_bFillCenter;
  4399. // border image width
  4400. struct BorderImageWidth_t
  4401. {
  4402. EBorderImageWidthType m_eType;
  4403. float m_flValue;
  4404. };
  4405. bool m_bWidthsSet;
  4406. BorderImageWidth_t m_Width[4];
  4407. // border image outsets
  4408. bool m_bOutsetsSet;
  4409. CUILength m_Outsets[4];
  4410. // border image stretch values
  4411. bool m_bStretchSet;
  4412. EBorderImageRepeatType m_Stretch[2];
  4413. };
  4414. //-----------------------------------------------------------------------------
  4415. // Purpose: Background-image property
  4416. //-----------------------------------------------------------------------------
  4417. class CStylePropertyBackgroundImage : public CStyleProperty
  4418. {
  4419. public:
  4420. static const CStyleSymbol symbol;
  4421. static const CStyleSymbol backgroundSize;
  4422. static const CStyleSymbol backgroundPosition;
  4423. static const CStyleSymbol backgroundRepeat;
  4424. CStylePropertyBackgroundImage();
  4425. virtual ~CStylePropertyBackgroundImage();
  4426. // from CStyleProperty
  4427. virtual void MergeTo( CStyleProperty *pTarget ) const;
  4428. virtual bool BCanTransition() { return false; }
  4429. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) { Assert( !"You can't interpolate an image" ); }
  4430. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString );
  4431. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const;
  4432. virtual bool BFullySet();
  4433. virtual void ResolveDefaultValues();
  4434. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  4435. virtual bool operator==(const CStyleProperty &rhs) const;
  4436. virtual void ApplyUIScaleFactor( float flScaleFactor );
  4437. virtual void OnAppliedToPanel( IUIPanel *pPanel );
  4438. virtual const char *GetDescription( CStyleSymbol symProperty );
  4439. CUtlVector< CBackgroundImageLayer * > &AccessLayers() { return m_vecLayers; }
  4440. void Set( const CUtlVector< CBackgroundImageLayer * > &vecLayers );
  4441. bool BHasActiveMovie();
  4442. void EnableBackgroundMovies( bool bEnable );
  4443. #ifdef DBGFLAG_VALIDATE
  4444. virtual void Validate( CValidator &validator, const tchar *pchName );
  4445. #endif
  4446. private:
  4447. CBackgroundImageLayer *GetOrAddLayer( int i );
  4448. void AddLayer();
  4449. void Clear();
  4450. void RemoveUnsetLayers();
  4451. CUtlVector< CBackgroundImageLayer * > m_vecLayers;
  4452. };
  4453. //-----------------------------------------------------------------------------
  4454. // Purpose: opacity-mask property
  4455. //-----------------------------------------------------------------------------
  4456. class CStylePropertyOpacityMask : public CStyleProperty
  4457. {
  4458. public:
  4459. static const CStyleSymbol symbol;
  4460. static const CStyleSymbol symbolScrollUp;
  4461. static const CStyleSymbol symbolScrollDown;
  4462. static const CStyleSymbol symbolScrollUpDown;
  4463. CStylePropertyOpacityMask() : CStyleProperty( CStylePropertyOpacityMask::symbol )
  4464. {
  4465. m_pImage = NULL;
  4466. m_flOpacityMaskOpacity = 1.0f;
  4467. m_pImageUp = NULL;
  4468. m_flOpacityMaskOpacityUp = 1.0f;
  4469. m_pImageDown = NULL;
  4470. m_flOpacityMaskOpacityDown = 1.0f;
  4471. m_pImageUpDown = NULL;
  4472. m_flOpacityMaskOpacityUpDown = 1.0f;
  4473. m_bWasSet = false;
  4474. }
  4475. virtual ~CStylePropertyOpacityMask()
  4476. {
  4477. SAFE_RELEASE( m_pImage );
  4478. SAFE_RELEASE( m_pImageUp );
  4479. SAFE_RELEASE( m_pImageDown );
  4480. SAFE_RELEASE( m_pImageUpDown );
  4481. }
  4482. virtual void MergeTo( CStyleProperty *pTarget ) const
  4483. {
  4484. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  4485. {
  4486. AssertMsg( false, "Mismatched types to CStylePropertyOpacityMask::MergeTo" );
  4487. return;
  4488. }
  4489. CStylePropertyOpacityMask *p = (CStylePropertyOpacityMask *)pTarget;
  4490. if( !p->m_bWasSet )
  4491. {
  4492. p->m_pImage = m_pImage;
  4493. p->m_sURL = m_sURL;
  4494. p->m_flOpacityMaskOpacity = m_flOpacityMaskOpacity;
  4495. p->m_sURLUp = m_sURLUp;
  4496. p->m_pImageUp = m_pImageUp;
  4497. p->m_sURLUp = m_sURLUp;
  4498. p->m_sURLDown = m_sURLDown;
  4499. p->m_pImageDown = m_pImageDown;
  4500. p->m_sURLDown = m_sURLDown;
  4501. p->m_sURLUpDown = m_sURLUpDown;
  4502. p->m_pImageUpDown = m_pImageUpDown;
  4503. p->m_sURLUpDown = m_sURLUpDown;
  4504. }
  4505. }
  4506. // Does the style only affect compositing of it's panels and not drawing within a composition layer?
  4507. virtual bool BAffectsCompositionOnly() { return true; }
  4508. // Can this property support animation?
  4509. virtual bool BCanTransition() { return true; }
  4510. // Interpolation func for animation of this property
  4511. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  4512. {
  4513. CStylePropertyOpacityMask *p = (CStylePropertyOpacityMask *)&target;
  4514. if( !p->m_sURL.IsValid() )
  4515. {
  4516. // Fade out
  4517. m_flOpacityMaskOpacity = Lerp( flProgress, m_flOpacityMaskOpacity, 0.0f );
  4518. }
  4519. else if( !m_sURL.IsValid() && p->m_sURL.IsValid() )
  4520. {
  4521. // Fade in
  4522. m_sURL = p->m_sURL;
  4523. m_flOpacityMaskOpacity = Lerp( flProgress, 0.0f, p->m_flOpacityMaskOpacity );
  4524. }
  4525. else
  4526. {
  4527. m_sURL = p->m_sURL;
  4528. m_flOpacityMaskOpacity = Lerp( flProgress, m_flOpacityMaskOpacity, p->m_flOpacityMaskOpacity );
  4529. }
  4530. m_sURLUp = p->m_sURLUp;
  4531. m_pImageUp = p->m_pImageUp;
  4532. m_sURLUp = p->m_sURLUp;
  4533. m_sURLDown = p->m_sURLDown;
  4534. m_pImageDown = p->m_pImageDown;
  4535. m_sURLDown = p->m_sURLDown;
  4536. m_sURLUpDown = p->m_sURLUpDown;
  4537. m_pImageUpDown = p->m_pImageUpDown;
  4538. m_sURLUpDown = p->m_sURLUpDown;
  4539. }
  4540. // Parses string and sets value
  4541. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  4542. {
  4543. if( symParsedName == symbol )
  4544. {
  4545. if( BParseProperty( pchString, m_flOpacityMaskOpacity, &m_pImage, m_sURL ) )
  4546. {
  4547. m_bWasSet = true;
  4548. return true;
  4549. }
  4550. return false;
  4551. }
  4552. else if( symParsedName == symbolScrollUp )
  4553. {
  4554. return BParseProperty( pchString, m_flOpacityMaskOpacityUp, &m_pImageUp, m_sURLUp );
  4555. }
  4556. else if( symParsedName == symbolScrollDown )
  4557. {
  4558. return BParseProperty( pchString, m_flOpacityMaskOpacityDown, &m_pImageDown, m_sURLDown );
  4559. }
  4560. else if( symParsedName == symbolScrollUpDown )
  4561. {
  4562. return BParseProperty( pchString, m_flOpacityMaskOpacityUpDown, &m_pImageUpDown, m_sURLUpDown );
  4563. }
  4564. return false;
  4565. }
  4566. bool BParseProperty( const char *pchString, float &flOpacityMaskOpacity, IImageSource **ppImage, CUtlString &sURL )
  4567. {
  4568. if( V_stricmp( "none", pchString ) == 0 )
  4569. {
  4570. *ppImage = NULL;
  4571. flOpacityMaskOpacity = 0.0f;
  4572. return true;
  4573. }
  4574. else
  4575. {
  4576. CUtlString sURLPath;
  4577. if( !CSSHelpers::BParseURL( sURLPath, pchString, &pchString ) )
  4578. return false;
  4579. sURL = sURLPath;
  4580. if( !sURL.IsValid() )
  4581. return false;
  4582. // Optional opacity value following
  4583. pchString = CSSHelpers::SkipSpaces( pchString );
  4584. if( !CSSHelpers::BParseNumber( &flOpacityMaskOpacity, pchString, &pchString ) )
  4585. flOpacityMaskOpacity = 1.0f;
  4586. return true;
  4587. }
  4588. }
  4589. // Gets string representation of property
  4590. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  4591. {
  4592. if( !m_sURL.IsValid() )
  4593. {
  4594. pfmtBuffer->Append( "none" );
  4595. }
  4596. else
  4597. {
  4598. CSSHelpers::AppendURL( pfmtBuffer, m_sURL.String() );
  4599. pfmtBuffer->Append( " " );
  4600. pfmtBuffer->AppendFormat( "%f", m_flOpacityMaskOpacity );
  4601. }
  4602. }
  4603. // Return a description for this property which will be shown in the debugger
  4604. virtual const char *GetDescription( CStyleSymbol symProperty )
  4605. {
  4606. if( symProperty == symbol )
  4607. {
  4608. return "Applies an image as an opacity mask that stretches to the panel bounds and fades out it's content based on the alpha channel. "
  4609. "The second float value is an optional opacity value for the mask itself, the image won't interpolate/cross-fade, but you can animate the opacity to fade the mask in/out. "
  4610. "The -scroll-up, -scroll-down, and -scroll-up-down varients override the mask and apply only when the various vertical scroll scenarios affect the panel based on the overflow property.<br><br>"
  4611. "<b>Examples:</b>"
  4612. "<pre>"
  4613. "opacity-mask: url( \"file://{images}/upper_row_mask.tga\" );\n"
  4614. "opacity-mask: url( \"file://{images}/upper_row_mask.tga\" ) 0.5;\n"
  4615. "opacity-mask-scroll-up: url( \"file://{images}/upper_row_mask_up.tga\" ) 0.5;\n"
  4616. "opacity-mask-scroll-down: url( \"file://{images}/upper_row_mask_down.tga\" ) 0.5;\n"
  4617. "opacity-mask-scroll-up-down: url( \"file://{images}/upper_row_mask_up_down.tga\" ) 0.5;"
  4618. "</pre>";
  4619. }
  4620. return "";
  4621. }
  4622. virtual void OnAppliedToPanel( IUIPanel *pPanel );
  4623. // Comparison function
  4624. virtual bool operator==(const CStyleProperty &other) const
  4625. {
  4626. if( GetPropertySymbol() != other.GetPropertySymbol() )
  4627. return false;
  4628. const CStylePropertyOpacityMask &rhs = (const CStylePropertyOpacityMask &)other;
  4629. return (
  4630. m_sURL == rhs.m_sURL && m_flOpacityMaskOpacity == rhs.m_flOpacityMaskOpacity &&
  4631. m_sURLUp == rhs.m_sURLUp && m_flOpacityMaskOpacityUp == rhs.m_flOpacityMaskOpacityUp &&
  4632. m_sURLDown == rhs.m_sURLDown && m_flOpacityMaskOpacityDown == rhs.m_flOpacityMaskOpacityDown &&
  4633. m_sURLUpDown == rhs.m_sURLUpDown && m_flOpacityMaskOpacityUpDown == rhs.m_flOpacityMaskOpacityUpDown
  4634. );
  4635. }
  4636. // Layout pieces that can be invalidated when the property is applied to a panel
  4637. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  4638. #ifdef DBGFLAG_VALIDATE
  4639. virtual void Validate( CValidator &validator, const tchar *pchName );
  4640. #endif
  4641. IImageSource *m_pImage;
  4642. IImageSource *m_pImageUp;
  4643. IImageSource *m_pImageDown;
  4644. IImageSource *m_pImageUpDown;
  4645. float m_flOpacityMaskOpacity;
  4646. float m_flOpacityMaskOpacityUp;
  4647. float m_flOpacityMaskOpacityDown;
  4648. float m_flOpacityMaskOpacityUpDown;
  4649. private:
  4650. bool m_bWasSet;
  4651. CUtlString m_sURL;
  4652. CUtlString m_sURLUp;
  4653. CUtlString m_sURLDown;
  4654. CUtlString m_sURLUpDown;
  4655. };
  4656. //-----------------------------------------------------------------------------
  4657. // Purpose: White-space property
  4658. //-----------------------------------------------------------------------------
  4659. class CStylePropertyWhiteSpace : public CStyleProperty
  4660. {
  4661. public:
  4662. static const CStyleSymbol symbol;
  4663. CStylePropertyWhiteSpace() : CStyleProperty( CStylePropertyWhiteSpace::symbol )
  4664. {
  4665. m_bSet = false;
  4666. m_bWrap = true;
  4667. }
  4668. virtual void MergeTo( CStyleProperty *pTarget ) const
  4669. {
  4670. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  4671. {
  4672. AssertMsg( false, "Mismatched types to CStylePropertyWhiteSpace::MergeTo" );
  4673. return;
  4674. }
  4675. CStylePropertyWhiteSpace *p = (CStylePropertyWhiteSpace *)pTarget;
  4676. if( !p->m_bSet )
  4677. {
  4678. p->m_bWrap = m_bWrap;
  4679. p->m_bSet = m_bSet;
  4680. }
  4681. }
  4682. // Can this property support animation?
  4683. virtual bool BCanTransition() { return false; }
  4684. // Interpolation func for animation of this property
  4685. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  4686. {
  4687. }
  4688. // Parses string and sets value
  4689. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  4690. {
  4691. pchString = CSSHelpers::SkipSpaces( pchString );
  4692. if( V_strnicmp( pchString, "nowrap", V_ARRAYSIZE( "nowrap" ) ) == 0 )
  4693. {
  4694. m_bWrap = false;
  4695. m_bSet = true;
  4696. return true;
  4697. }
  4698. else if( V_strnicmp( pchString, "normal", V_ARRAYSIZE( "normal" ) ) == 0 )
  4699. {
  4700. m_bWrap = true;
  4701. m_bSet = true;
  4702. return true;
  4703. }
  4704. return false;
  4705. }
  4706. // Gets string representation of property
  4707. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  4708. {
  4709. if( m_bWrap )
  4710. pfmtBuffer->Append( "normal" );
  4711. else
  4712. pfmtBuffer->Append( "nowrap" );
  4713. }
  4714. // Return a description for this property which will be shown in the debugger
  4715. virtual const char *GetDescription( CStyleSymbol symProperty )
  4716. {
  4717. if( symProperty == symbol )
  4718. {
  4719. return "Controls white-space wrapping on rendered text. \"normal\" means wrap on whitespace, \"nowrap\" means do no wrapping at all.<br><br>"
  4720. "<b>Examples:</b>"
  4721. "<pre>"
  4722. "white-space: normal;\n"
  4723. "white-space: nowrap;"
  4724. "</pre>";
  4725. }
  4726. return "";
  4727. }
  4728. // Comparison function
  4729. virtual bool operator==(const CStyleProperty &other) const
  4730. {
  4731. if( GetPropertySymbol() != other.GetPropertySymbol() )
  4732. return false;
  4733. const CStylePropertyWhiteSpace &rhs = (const CStylePropertyWhiteSpace &)other;
  4734. return (m_bWrap == rhs.m_bWrap && m_bSet == rhs.m_bSet);
  4735. }
  4736. // Layout pieces that can be invalidated when the property is applied to a panel
  4737. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  4738. bool m_bWrap;
  4739. bool m_bSet;
  4740. };
  4741. //-----------------------------------------------------------------------------
  4742. // Purpose: text-overflow property
  4743. //-----------------------------------------------------------------------------
  4744. class CStylePropertyTextOverflow : public CStyleProperty
  4745. {
  4746. public:
  4747. static const CStyleSymbol symbol;
  4748. CStylePropertyTextOverflow() : CStyleProperty( CStylePropertyTextOverflow::symbol )
  4749. {
  4750. m_bSet = false;
  4751. m_bEllipsis = true;
  4752. }
  4753. virtual void MergeTo( CStyleProperty *pTarget ) const
  4754. {
  4755. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  4756. {
  4757. AssertMsg( false, "Mismatched types to CStylePropertyTextOverflow::MergeTo" );
  4758. return;
  4759. }
  4760. CStylePropertyTextOverflow *p = (CStylePropertyTextOverflow *)pTarget;
  4761. if( !p->m_bSet )
  4762. {
  4763. p->m_bEllipsis = m_bEllipsis;
  4764. p->m_bSet = m_bSet;
  4765. }
  4766. }
  4767. // Can this property support animation?
  4768. virtual bool BCanTransition() { return false; }
  4769. // Interpolation func for animation of this property
  4770. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  4771. {
  4772. }
  4773. // Parses string and sets value
  4774. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  4775. {
  4776. pchString = CSSHelpers::SkipSpaces( pchString );
  4777. if( V_strnicmp( pchString, "clip", V_ARRAYSIZE( "clip" ) ) == 0 )
  4778. {
  4779. m_bEllipsis = false;
  4780. m_bSet = true;
  4781. return true;
  4782. }
  4783. else if( V_strnicmp( pchString, "ellipsis", V_ARRAYSIZE( "ellipsis" ) ) == 0 )
  4784. {
  4785. m_bEllipsis = true;
  4786. m_bSet = true;
  4787. return true;
  4788. }
  4789. return false;
  4790. }
  4791. // Gets string representation of property
  4792. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  4793. {
  4794. if( m_bEllipsis )
  4795. pfmtBuffer->Append( "ellipsis" );
  4796. else
  4797. pfmtBuffer->Append( "clip" );
  4798. }
  4799. // Return a description for this property which will be shown in the debugger
  4800. virtual const char *GetDescription( CStyleSymbol symProperty )
  4801. {
  4802. if( symProperty == symbol )
  4803. {
  4804. return "Controls truncation of text that doesn't fit in a panel. \"clip\" means to simply truncate (on char boundaries), \"ellipsis\" means to end with '...'.\n"
  4805. "We default to ellipsis, which is contrary to the normal CSS spec.<br><br>"
  4806. "<b>Examples:</b>"
  4807. "<pre>"
  4808. "text-overflow: ellipsis;\n"
  4809. "text-overflow: clip;"
  4810. "</pre>";
  4811. }
  4812. return "";
  4813. }
  4814. // Comparison function
  4815. virtual bool operator==(const CStyleProperty &other) const
  4816. {
  4817. if( GetPropertySymbol() != other.GetPropertySymbol() )
  4818. return false;
  4819. const CStylePropertyTextOverflow &rhs = (const CStylePropertyTextOverflow &)other;
  4820. return (m_bEllipsis == rhs.m_bEllipsis && m_bSet == rhs.m_bSet);
  4821. }
  4822. // Layout pieces that can be invalidated when the property is applied to a panel
  4823. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  4824. bool m_bEllipsis;
  4825. bool m_bSet;
  4826. };
  4827. //-----------------------------------------------------------------------------
  4828. // Purpose: Width property
  4829. //-----------------------------------------------------------------------------
  4830. class CStylePropertyWidth : public CStyleProperty
  4831. {
  4832. public:
  4833. static const CStyleSymbol symbol;
  4834. CStylePropertyWidth() : CStyleProperty( CStylePropertyWidth::symbol )
  4835. {
  4836. m_Length.SetFitChildren();
  4837. }
  4838. virtual void MergeTo( CStyleProperty *pTarget ) const
  4839. {
  4840. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  4841. {
  4842. AssertMsg( false, "Mismatched types to CStylePropertyWidth::MergeTo" );
  4843. return;
  4844. }
  4845. CStylePropertyWidth *p = (CStylePropertyWidth *)pTarget;
  4846. p->m_Length = m_Length;
  4847. }
  4848. // Can this property support animation?
  4849. virtual bool BCanTransition() { return true; }
  4850. // Interpolation func for animation of this property
  4851. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  4852. {
  4853. CStylePropertyWidth *p = (CStylePropertyWidth *)&target;
  4854. float flParentWidth, flParentHeight, flParentPerspective;
  4855. GetParentSizeAvailable( pPanel, flParentWidth, flParentHeight, flParentPerspective );
  4856. m_Length = LerpUILength( flProgress, m_Length, p->m_Length, flParentWidth );
  4857. }
  4858. // Parses string and sets value
  4859. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  4860. {
  4861. bool bSuccess = CSSHelpers::BParseIntoUILengthForSizing( &m_Length, pchString, NULL );
  4862. if ( m_Length.IsWidthPercentage() )
  4863. return false;
  4864. return bSuccess;
  4865. }
  4866. // called when we are ready to apply any scaling factor to the values
  4867. virtual void ApplyUIScaleFactor( float flScaleFactor )
  4868. {
  4869. m_Length.ScaleLengthValue( flScaleFactor );
  4870. }
  4871. // Gets string representation of property
  4872. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  4873. {
  4874. CSSHelpers::AppendUILength( pfmtBuffer, m_Length );
  4875. }
  4876. // Return a description for this property which will be shown in the debugger
  4877. virtual const char *GetDescription( CStyleSymbol symProperty )
  4878. {
  4879. return "Sets the width for this panel. "
  4880. "Possible values:<br>"
  4881. "\"fit-children\" - Panel size is set to the required size of all children (default)<br>"
  4882. "&lt;pixels&gt; - Any fixed pixel value (ex: \"100px\")<br>"
  4883. "&lt;percentage&gt; - Percentage of parent width (ex: \"100%\")<br>"
  4884. "\"fill-parent-flow( &lt;weight&gt; )\" - Fills to remaining parent width. If multiple children are set to this value, weight is used to determine final width. For example, if three children are set to fill-parent-flow of 1.0 and the parent is 300px wide, each child will be 100px wide. (ex: \"fill-parent-flow( 1.0 )\" )<br>"
  4885. "\"height-percentage( &lt;percentage&gt; )\" - Percentage of the panel's height, which allows you to enforce a particular aspect ratio. The height cannot also be width-percentage.";
  4886. }
  4887. // Comparison function
  4888. virtual bool operator==(const CStyleProperty &other) const
  4889. {
  4890. if( GetPropertySymbol() != other.GetPropertySymbol() )
  4891. return false;
  4892. const CStylePropertyWidth &rhs = (const CStylePropertyWidth &)other;
  4893. return (m_Length == rhs.m_Length);
  4894. }
  4895. // Layout pieces that can be invalidated when the property is applied to a panel
  4896. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  4897. {
  4898. if( !pCompareProperty || !(*this == *pCompareProperty) )
  4899. return k_EStyleInvalidateLayoutSizeAndPosition;
  4900. return k_EStyleInvalidateLayoutNone;
  4901. }
  4902. CUILength m_Length;
  4903. };
  4904. //-----------------------------------------------------------------------------
  4905. // Purpose: Height property
  4906. //-----------------------------------------------------------------------------
  4907. class CStylePropertyHeight : public CStyleProperty
  4908. {
  4909. public:
  4910. static const CStyleSymbol symbol;
  4911. CStylePropertyHeight() : CStyleProperty( CStylePropertyHeight::symbol )
  4912. {
  4913. m_Height.SetFitChildren();
  4914. }
  4915. virtual void MergeTo( CStyleProperty *pTarget ) const
  4916. {
  4917. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  4918. {
  4919. AssertMsg( false, "Mismatched types to CStylePropertyHeight::MergeTo" );
  4920. return;
  4921. }
  4922. CStylePropertyHeight *p = (CStylePropertyHeight *)pTarget;
  4923. p->m_Height = m_Height;
  4924. }
  4925. // Can this property support animation?
  4926. virtual bool BCanTransition() { return true; }
  4927. // Interpolation func for animation of this property
  4928. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  4929. {
  4930. CStylePropertyHeight *p = (CStylePropertyHeight *)&target;
  4931. float flParentWidth, flParentHeight, flParentPerspective;
  4932. GetParentSizeAvailable( pPanel, flParentWidth, flParentHeight, flParentPerspective );
  4933. m_Height = LerpUILength( flProgress, m_Height, p->m_Height, flParentHeight );
  4934. }
  4935. // Parses string and sets value
  4936. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  4937. {
  4938. bool bSuccess = CSSHelpers::BParseIntoUILengthForSizing( &m_Height, pchString, NULL );
  4939. if ( m_Height.IsHeightPercentage() )
  4940. return false;
  4941. return bSuccess;
  4942. }
  4943. // called when we are ready to apply any scaling factor to the values
  4944. virtual void ApplyUIScaleFactor( float flScaleFactor )
  4945. {
  4946. m_Height.ScaleLengthValue( flScaleFactor );
  4947. }
  4948. // Gets string representation of property
  4949. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  4950. {
  4951. CSSHelpers::AppendUILength( pfmtBuffer, m_Height );
  4952. }
  4953. // Return a description for this property which will be shown in the debugger
  4954. virtual const char *GetDescription( CStyleSymbol symProperty )
  4955. {
  4956. return "Sets the height for this panel. "
  4957. "Possible values:<br>"
  4958. "\"fit-children\" - Panel size is set to the required size of all children (default)<br>"
  4959. "&lt;pixels&gt; - Any fixed pixel value (ex: \"100px\")<br>"
  4960. "&lt;percentage&gt; - Percentage of parent height (ex: \"100%\")<br>"
  4961. "\"fill-parent-flow( &lt;weight&gt; )\" - Fills to remaining parent width. If multiple children are set to this value, weight is used to determine final height. For example, if three children are set to fill-parent-flow of 1.0 and the parent is 300px tall, each child will be 100px tall. (ex: \"fill-parent-flow( 1.0 )\" )<br>"
  4962. "\"width-percentage( &lt;percentage&gt; )\" - Percentage of the panel's width, which allows you to enforce a particular aspect ratio. The width cannot also be height-percentage.";
  4963. }
  4964. // Comparison function
  4965. virtual bool operator==(const CStyleProperty &other) const
  4966. {
  4967. if( GetPropertySymbol() != other.GetPropertySymbol() )
  4968. return false;
  4969. const CStylePropertyHeight &rhs = (const CStylePropertyHeight &)other;
  4970. return (m_Height == rhs.m_Height);
  4971. }
  4972. // Layout pieces that can be invalidated when the property is applied to a panel
  4973. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  4974. {
  4975. if( !pCompareProperty || !(*this == *pCompareProperty) )
  4976. return k_EStyleInvalidateLayoutSizeAndPosition;
  4977. return k_EStyleInvalidateLayoutNone;
  4978. }
  4979. CUILength m_Height;
  4980. };
  4981. //-----------------------------------------------------------------------------
  4982. // Purpose: min-width property
  4983. //-----------------------------------------------------------------------------
  4984. class CStylePropertyMinWidth : public CStyleProperty
  4985. {
  4986. public:
  4987. static const CStyleSymbol symbol;
  4988. CStylePropertyMinWidth() : CStyleProperty( CStylePropertyMinWidth::symbol )
  4989. {
  4990. }
  4991. virtual void MergeTo( CStyleProperty *pTarget ) const
  4992. {
  4993. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  4994. {
  4995. AssertMsg( false, "Mismatched types to CStylePropertyMinWidth::MergeTo" );
  4996. return;
  4997. }
  4998. CStylePropertyMinWidth *p = (CStylePropertyMinWidth *)pTarget;
  4999. p->m_minWidth = m_minWidth;
  5000. }
  5001. // Can this property support animation?
  5002. virtual bool BCanTransition() { return false; }
  5003. // Interpolation func for animation of this property
  5004. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  5005. // Parses string and sets value
  5006. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5007. {
  5008. bool bSuccess = CSSHelpers::BParseIntoUILengthForSizing( &m_minWidth, pchString, NULL );
  5009. return bSuccess;
  5010. }
  5011. // called when we are ready to apply any scaling factor to the values
  5012. virtual void ApplyUIScaleFactor( float flScaleFactor )
  5013. {
  5014. m_minWidth.ScaleLengthValue( flScaleFactor );
  5015. }
  5016. // Gets string representation of property
  5017. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5018. {
  5019. CSSHelpers::AppendUILength( pfmtBuffer, m_minWidth );
  5020. }
  5021. // Comparison function
  5022. virtual bool operator==(const CStyleProperty &other) const
  5023. {
  5024. if( GetPropertySymbol() != other.GetPropertySymbol() )
  5025. return false;
  5026. const CStylePropertyMinWidth &rhs = (const CStylePropertyMinWidth &)other;
  5027. return (m_minWidth == rhs.m_minWidth);
  5028. }
  5029. // Layout pieces that can be invalidated when the property is applied to a panel
  5030. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  5031. {
  5032. if( !pCompareProperty || !(*this == *pCompareProperty) )
  5033. return k_EStyleInvalidateLayoutSizeAndPosition;
  5034. return k_EStyleInvalidateLayoutNone;
  5035. }
  5036. CUILength m_minWidth;
  5037. };
  5038. //-----------------------------------------------------------------------------
  5039. // Purpose: min-height property
  5040. //-----------------------------------------------------------------------------
  5041. class CStylePropertyMinHeight : public CStyleProperty
  5042. {
  5043. public:
  5044. static const CStyleSymbol symbol;
  5045. CStylePropertyMinHeight() : CStyleProperty( CStylePropertyMinHeight::symbol )
  5046. {
  5047. }
  5048. virtual void MergeTo( CStyleProperty *pTarget ) const
  5049. {
  5050. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  5051. {
  5052. AssertMsg( false, "Mismatched types to CStylePropertyMinHeight::MergeTo" );
  5053. return;
  5054. }
  5055. CStylePropertyMinHeight *p = (CStylePropertyMinHeight *)pTarget;
  5056. p->m_minHeight = m_minHeight;
  5057. }
  5058. // Can this property support animation?
  5059. virtual bool BCanTransition() { return false; }
  5060. // Interpolation func for animation of this property
  5061. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  5062. // Parses string and sets value
  5063. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5064. {
  5065. bool bSuccess = CSSHelpers::BParseIntoUILengthForSizing( &m_minHeight, pchString, NULL );
  5066. return bSuccess;
  5067. }
  5068. // called when we are ready to apply any scaling factor to the values
  5069. virtual void ApplyUIScaleFactor( float flScaleFactor )
  5070. {
  5071. m_minHeight.ScaleLengthValue( flScaleFactor );
  5072. }
  5073. // Gets string representation of property
  5074. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5075. {
  5076. CSSHelpers::AppendUILength( pfmtBuffer, m_minHeight );
  5077. }
  5078. // Comparison function
  5079. virtual bool operator==(const CStyleProperty &other) const
  5080. {
  5081. if( GetPropertySymbol() != other.GetPropertySymbol() )
  5082. return false;
  5083. const CStylePropertyMinHeight &rhs = (const CStylePropertyMinHeight &)other;
  5084. return (m_minHeight == rhs.m_minHeight);
  5085. }
  5086. // Layout pieces that can be invalidated when the property is applied to a panel
  5087. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  5088. {
  5089. if( !pCompareProperty || !(*this == *pCompareProperty) )
  5090. return k_EStyleInvalidateLayoutSizeAndPosition;
  5091. return k_EStyleInvalidateLayoutNone;
  5092. }
  5093. CUILength m_minHeight;
  5094. };
  5095. //-----------------------------------------------------------------------------
  5096. // Purpose: max-width property
  5097. //-----------------------------------------------------------------------------
  5098. class CStylePropertyMaxWidth : public CStyleProperty
  5099. {
  5100. public:
  5101. static const CStyleSymbol symbol;
  5102. CStylePropertyMaxWidth() : CStyleProperty( CStylePropertyMaxWidth::symbol )
  5103. {
  5104. }
  5105. virtual void MergeTo( CStyleProperty *pTarget ) const
  5106. {
  5107. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  5108. {
  5109. AssertMsg( false, "Mismatched types to CStylePropertyMaxWidth::MergeTo" );
  5110. return;
  5111. }
  5112. CStylePropertyMaxWidth *p = (CStylePropertyMaxWidth *)pTarget;
  5113. p->m_maxWidth = m_maxWidth;
  5114. }
  5115. // Can this property support animation?
  5116. virtual bool BCanTransition() { return true; }
  5117. // Interpolation func for animation of this property
  5118. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  5119. {
  5120. float flParentWidth, flParentHeight, flParentPerspective;
  5121. GetParentSizeAvailable( pPanel, flParentWidth, flParentHeight, flParentPerspective );
  5122. const CStylePropertyMaxWidth *p = (const CStylePropertyMaxWidth*)&target;
  5123. m_maxWidth = LerpUILength( flProgress, m_maxWidth, p->m_maxWidth, flParentWidth );
  5124. }
  5125. // Parses string and sets value
  5126. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5127. {
  5128. bool bSuccess = CSSHelpers::BParseIntoUILengthForSizing( &m_maxWidth, pchString, NULL );
  5129. return bSuccess;
  5130. }
  5131. // called when we are ready to apply any scaling factor to the values
  5132. virtual void ApplyUIScaleFactor( float flScaleFactor )
  5133. {
  5134. m_maxWidth.ScaleLengthValue( flScaleFactor );
  5135. }
  5136. // Gets string representation of property
  5137. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5138. {
  5139. CSSHelpers::AppendUILength( pfmtBuffer, m_maxWidth );
  5140. }
  5141. // Comparison function
  5142. virtual bool operator==(const CStyleProperty &other) const
  5143. {
  5144. if( GetPropertySymbol() != other.GetPropertySymbol() )
  5145. return false;
  5146. const CStylePropertyMaxWidth &rhs = (const CStylePropertyMaxWidth &)other;
  5147. return (m_maxWidth == rhs.m_maxWidth);
  5148. }
  5149. // Layout pieces that can be invalidated when the property is applied to a panel
  5150. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  5151. {
  5152. if( !pCompareProperty || !(*this == *pCompareProperty) )
  5153. return k_EStyleInvalidateLayoutSizeAndPosition;
  5154. return k_EStyleInvalidateLayoutNone;
  5155. }
  5156. CUILength m_maxWidth;
  5157. };
  5158. //-----------------------------------------------------------------------------
  5159. // Purpose: max-height property
  5160. //-----------------------------------------------------------------------------
  5161. class CStylePropertyMaxHeight : public CStyleProperty
  5162. {
  5163. public:
  5164. static const CStyleSymbol symbol;
  5165. CStylePropertyMaxHeight() : CStyleProperty( CStylePropertyMaxHeight::symbol )
  5166. {
  5167. }
  5168. virtual void MergeTo( CStyleProperty *pTarget ) const
  5169. {
  5170. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  5171. {
  5172. AssertMsg( false, "Mismatched types to CStylePropertyMaxHeight::MergeTo" );
  5173. return;
  5174. }
  5175. CStylePropertyMaxHeight *p = (CStylePropertyMaxHeight*)pTarget;
  5176. p->m_maxHeight = m_maxHeight;
  5177. }
  5178. // Can this property support animation?
  5179. virtual bool BCanTransition() { return true; }
  5180. // Interpolation func for animation of this property
  5181. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  5182. {
  5183. float flParentWidth, flParentHeight, flParentPerspective;
  5184. GetParentSizeAvailable( pPanel, flParentWidth, flParentHeight, flParentPerspective );
  5185. const CStylePropertyMaxHeight *p = (const CStylePropertyMaxHeight *)&target;
  5186. m_maxHeight = LerpUILength( flProgress, m_maxHeight, p->m_maxHeight, flParentHeight );
  5187. }
  5188. // Parses string and sets value
  5189. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5190. {
  5191. bool bSuccess = CSSHelpers::BParseIntoUILengthForSizing( &m_maxHeight, pchString, NULL );
  5192. return bSuccess;
  5193. }
  5194. // called when we are ready to apply any scaling factor to the values
  5195. virtual void ApplyUIScaleFactor( float flScaleFactor )
  5196. {
  5197. m_maxHeight.ScaleLengthValue( flScaleFactor );
  5198. }
  5199. // Gets string representation of property
  5200. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5201. {
  5202. CSSHelpers::AppendUILength( pfmtBuffer, m_maxHeight );
  5203. }
  5204. // Comparison function
  5205. virtual bool operator==(const CStyleProperty &other) const
  5206. {
  5207. if( GetPropertySymbol() != other.GetPropertySymbol() )
  5208. return false;
  5209. const CStylePropertyMaxHeight &rhs = (const CStylePropertyMaxHeight &)other;
  5210. return (m_maxHeight == rhs.m_maxHeight);
  5211. }
  5212. // Layout pieces that can be invalidated when the property is applied to a panel
  5213. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  5214. {
  5215. if( !pCompareProperty || !(*this == *pCompareProperty) )
  5216. return k_EStyleInvalidateLayoutSizeAndPosition;
  5217. return k_EStyleInvalidateLayoutNone;
  5218. }
  5219. CUILength m_maxHeight;
  5220. };
  5221. //-----------------------------------------------------------------------------
  5222. // Purpose: Width property
  5223. //-----------------------------------------------------------------------------
  5224. class CStylePropertyVisible : public CStyleProperty
  5225. {
  5226. public:
  5227. static const CStyleSymbol symbol;
  5228. CStylePropertyVisible() : CStyleProperty( CStylePropertyVisible::symbol )
  5229. {
  5230. m_bVisible = true;
  5231. }
  5232. virtual void MergeTo( CStyleProperty *pTarget ) const
  5233. {
  5234. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  5235. {
  5236. AssertMsg( false, "Mismatched types to CStylePropertyHeight::MergeTo" );
  5237. return;
  5238. }
  5239. CStylePropertyVisible *p = (CStylePropertyVisible *)pTarget;
  5240. p->m_bVisible = m_bVisible;
  5241. }
  5242. // Can this property support animation?
  5243. virtual bool BCanTransition() { return false; }
  5244. // Interpolation func for animation of this property
  5245. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  5246. // Parses string and sets value
  5247. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5248. {
  5249. if( V_stricmp( "visible", pchString ) == 0 )
  5250. {
  5251. m_bVisible = true;
  5252. return true;
  5253. }
  5254. else if( V_stricmp( "collapse", pchString ) == 0 )
  5255. {
  5256. m_bVisible = false;
  5257. return true;
  5258. }
  5259. return false;
  5260. }
  5261. // Gets string representation of property
  5262. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5263. {
  5264. pfmtBuffer->Append( m_bVisible ? "visible" : "collapse" );
  5265. }
  5266. // Return a description for this property which will be shown in the debugger
  5267. virtual const char *GetDescription( CStyleSymbol symProperty )
  5268. {
  5269. return "Controls if the panel is visible and is included in panel layout. "
  5270. "Possible values:<br>"
  5271. "\"visible\" - panel is visible and included in layout (default)<br>"
  5272. "\"collapse\" - panel is invisible and not included in layout";
  5273. }
  5274. // Comparison function
  5275. virtual bool operator==(const CStyleProperty &other) const
  5276. {
  5277. if( GetPropertySymbol() != other.GetPropertySymbol() )
  5278. return false;
  5279. const CStylePropertyVisible &rhs = (const CStylePropertyVisible&)other;
  5280. return (m_bVisible == rhs.m_bVisible);
  5281. }
  5282. // Layout pieces that can be invalidated when the property is applied to a panel
  5283. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  5284. {
  5285. if( !pCompareProperty )
  5286. {
  5287. if( !m_bVisible )
  5288. return k_EStyleInvalidateLayoutSizeAndPosition;
  5289. else
  5290. return k_EStyleInvalidateLayoutNone;
  5291. }
  5292. if( !(*this == *pCompareProperty) )
  5293. return k_EStyleInvalidateLayoutSizeAndPosition;
  5294. return k_EStyleInvalidateLayoutNone;
  5295. }
  5296. bool m_bVisible;
  5297. };
  5298. //-----------------------------------------------------------------------------
  5299. // Purpose: Flow property
  5300. //-----------------------------------------------------------------------------
  5301. class CStylePropertyFlowChildren : public CStyleProperty
  5302. {
  5303. public:
  5304. static const CStyleSymbol symbol;
  5305. CStylePropertyFlowChildren() : CStyleProperty( CStylePropertyFlowChildren::symbol )
  5306. {
  5307. m_eFlowDirection = k_EFlowNone;
  5308. }
  5309. virtual void MergeTo( CStyleProperty *pTarget ) const
  5310. {
  5311. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  5312. {
  5313. AssertMsg( false, "Mismatched types to CStylePropertyFlow::MergeTo" );
  5314. return;
  5315. }
  5316. CStylePropertyFlowChildren *p = (CStylePropertyFlowChildren *)pTarget;
  5317. p->m_eFlowDirection = m_eFlowDirection;
  5318. }
  5319. // Can this property support animation?
  5320. virtual bool BCanTransition() { return false; }
  5321. // Interpolation func for animation of this property
  5322. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  5323. // Parses string and sets value
  5324. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5325. {
  5326. if( V_stricmp( "none", pchString ) == 0 )
  5327. m_eFlowDirection = k_EFlowNone;
  5328. else if( V_stricmp( "down", pchString ) == 0 )
  5329. m_eFlowDirection = k_EFlowDown;
  5330. else if( V_stricmp( "right", pchString ) == 0 )
  5331. m_eFlowDirection = k_EFlowRight;
  5332. else if ( V_stricmp( "down-wrap", pchString ) == 0 )
  5333. m_eFlowDirection = k_EFlowDownWrap;
  5334. else if ( V_stricmp( "right-wrap", pchString ) == 0 )
  5335. m_eFlowDirection = k_EFlowRightWrap;
  5336. else
  5337. return false;
  5338. return true;
  5339. }
  5340. // Gets string representation of property
  5341. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5342. {
  5343. if( m_eFlowDirection == k_EFlowNone )
  5344. pfmtBuffer->Append( "none" );
  5345. else if( m_eFlowDirection == k_EFlowDown )
  5346. pfmtBuffer->Append( "down" );
  5347. else if( m_eFlowDirection == k_EFlowRight )
  5348. pfmtBuffer->Append( "right" );
  5349. else if ( m_eFlowDirection == k_EFlowDownWrap )
  5350. pfmtBuffer->Append( "down-wrap" );
  5351. else if ( m_eFlowDirection == k_EFlowRightWrap )
  5352. pfmtBuffer->Append( "right-wrap" );
  5353. }
  5354. // Comparison function
  5355. virtual bool operator==(const CStyleProperty &other) const
  5356. {
  5357. if( GetPropertySymbol() != other.GetPropertySymbol() )
  5358. return false;
  5359. const CStylePropertyFlowChildren &rhs = (const CStylePropertyFlowChildren&)other;
  5360. return (m_eFlowDirection == rhs.m_eFlowDirection);
  5361. }
  5362. // Layout pieces that can be invalidated when the property is applied to a panel
  5363. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  5364. {
  5365. if( !pCompareProperty || !(*this == *pCompareProperty) )
  5366. return k_EStyleInvalidateLayoutSizeAndPosition;
  5367. return k_EStyleInvalidateLayoutNone;
  5368. }
  5369. EFlowDirection m_eFlowDirection;
  5370. };
  5371. //-----------------------------------------------------------------------------
  5372. // Purpose: base class for margin/padding
  5373. //-----------------------------------------------------------------------------
  5374. template < class T >
  5375. class CStylePropertyDimensionsBase : public CStyleProperty
  5376. {
  5377. public:
  5378. CStylePropertyDimensionsBase() : CStyleProperty( T::symbol )
  5379. {
  5380. }
  5381. virtual void MergeTo( CStyleProperty *pTarget ) const
  5382. {
  5383. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  5384. {
  5385. AssertMsg( false, "Mismatched types to CStylePropertyDimensionsBase::MergeTo" );
  5386. return;
  5387. }
  5388. T *p = (T *)pTarget;
  5389. if( !p->m_left.IsSet() )
  5390. p->m_left = m_left;
  5391. if( !p->m_top.IsSet() )
  5392. p->m_top = m_top;
  5393. if( !p->m_right.IsSet() )
  5394. p->m_right = m_right;
  5395. if( !p->m_bottom.IsSet() )
  5396. p->m_bottom = m_bottom;
  5397. }
  5398. // Can this property support animation?
  5399. virtual bool BCanTransition() { return false; }
  5400. // Interpolation func for animation of this property
  5401. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  5402. // Parses string and sets value
  5403. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5404. {
  5405. if( symParsedName == T::symbol )
  5406. {
  5407. // we support 1 to 4 values specified.
  5408. if( CSSHelpers::BParseIntoUILength( &m_top, pchString, &pchString ) )
  5409. {
  5410. if( CSSHelpers::BParseIntoUILength( &m_right, pchString, &pchString ) )
  5411. {
  5412. if( CSSHelpers::BParseIntoUILength( &m_bottom, pchString, &pchString ) )
  5413. {
  5414. if( CSSHelpers::BParseIntoUILength( &m_left, pchString, &pchString ) )
  5415. {
  5416. // got all 4
  5417. }
  5418. else
  5419. {
  5420. m_left = m_right;
  5421. }
  5422. }
  5423. else
  5424. {
  5425. m_left = m_right;
  5426. m_bottom = m_top;
  5427. }
  5428. }
  5429. else
  5430. {
  5431. m_right = m_top;
  5432. m_left = m_right;
  5433. m_bottom = m_top;
  5434. }
  5435. return true;
  5436. }
  5437. return false;
  5438. }
  5439. else if( symParsedName == T::symbolLeft )
  5440. {
  5441. return CSSHelpers::BParseIntoUILength( &m_left, pchString, NULL );
  5442. }
  5443. else if( symParsedName == T::symbolTop )
  5444. {
  5445. return CSSHelpers::BParseIntoUILength( &m_top, pchString, NULL );
  5446. }
  5447. else if( symParsedName == T::symbolBottom )
  5448. {
  5449. return CSSHelpers::BParseIntoUILength( &m_bottom, pchString, NULL );
  5450. }
  5451. else if( symParsedName == T::symbolRight )
  5452. {
  5453. return CSSHelpers::BParseIntoUILength( &m_right, pchString, NULL );
  5454. }
  5455. return false;
  5456. }
  5457. // called when we are ready to apply any scaling factor to the values
  5458. virtual void ApplyUIScaleFactor( float flScaleFactor )
  5459. {
  5460. m_left.ScaleLengthValue( flScaleFactor );
  5461. m_top.ScaleLengthValue( flScaleFactor );
  5462. m_bottom.ScaleLengthValue( flScaleFactor );
  5463. m_right.ScaleLengthValue( flScaleFactor );
  5464. }
  5465. // Gets string representation of property
  5466. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5467. {
  5468. CSSHelpers::AppendUILength( pfmtBuffer, m_top );
  5469. pfmtBuffer->Append( " " );
  5470. CSSHelpers::AppendUILength( pfmtBuffer, m_right );
  5471. pfmtBuffer->Append( " " );
  5472. CSSHelpers::AppendUILength( pfmtBuffer, m_bottom );
  5473. pfmtBuffer->Append( " " );
  5474. CSSHelpers::AppendUILength( pfmtBuffer, m_left );
  5475. }
  5476. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  5477. // by looking at lower weight styles
  5478. virtual bool BFullySet()
  5479. {
  5480. return (m_left.IsSet() && m_top.IsSet() && m_bottom.IsSet() && m_right.IsSet());
  5481. }
  5482. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  5483. virtual void ResolveDefaultValues()
  5484. {
  5485. if( !m_left.IsSet() )
  5486. m_left.SetLength( 0 );
  5487. if( !m_top.IsSet() )
  5488. m_top.SetLength( 0 );
  5489. if( !m_right.IsSet() )
  5490. m_right.SetLength( 0 );
  5491. if( !m_bottom.IsSet() )
  5492. m_bottom.SetLength( 0 );
  5493. }
  5494. // Comparison function
  5495. virtual bool operator==(const CStyleProperty &other) const
  5496. {
  5497. if( GetPropertySymbol() != other.GetPropertySymbol() )
  5498. return false;
  5499. const CStylePropertyDimensionsBase<T> &rhs = (const CStylePropertyDimensionsBase<T> &)other;
  5500. return (m_left == rhs.m_left && m_top == rhs.m_top && m_right == rhs.m_right && m_bottom == rhs.m_bottom);
  5501. }
  5502. // Layout pieces that can be invalidated when the property is applied to a panel
  5503. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  5504. {
  5505. if( !pCompareProperty || !(*this == *pCompareProperty) )
  5506. return k_EStyleInvalidateLayoutSizeAndPosition;
  5507. return k_EStyleInvalidateLayoutNone;
  5508. }
  5509. CUILength m_left;
  5510. CUILength m_top;
  5511. CUILength m_right;
  5512. CUILength m_bottom;
  5513. };
  5514. //-----------------------------------------------------------------------------
  5515. // Purpose: Animation properties
  5516. //-----------------------------------------------------------------------------
  5517. const float k_flFloatInfiniteIteration = FLT_MAX;
  5518. class CStylePropertyAnimationProperties : public CStyleProperty
  5519. {
  5520. public:
  5521. static const CStyleSymbol symbol;
  5522. static const CStyleSymbol symbolName;
  5523. static const CStyleSymbol symbolDuration;
  5524. static const CStyleSymbol symbolTiming;
  5525. static const CStyleSymbol symbolIteration;
  5526. static const CStyleSymbol symbolDirection;
  5527. static const CStyleSymbol symbolDelay;
  5528. CStylePropertyAnimationProperties() : CStyleProperty( CStylePropertyAnimationProperties::symbol )
  5529. {
  5530. m_bNone = false;
  5531. }
  5532. virtual void MergeTo( CStyleProperty *pTarget ) const
  5533. {
  5534. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  5535. {
  5536. AssertMsg( false, "Mismatched types to CStylePropertyAnimationProperties::MergeTo" );
  5537. return;
  5538. }
  5539. CStylePropertyAnimationProperties *p = (CStylePropertyAnimationProperties *)pTarget;
  5540. // if the other property is already set to none, don't merge
  5541. if( p->m_bNone )
  5542. return;
  5543. // if other does not yet have names set, and we are none, set other to none
  5544. if( m_bNone && (p->m_vecAnimationProperties.Count() == 0 || !p->m_vecAnimationProperties[0].m_symName.IsValid()) )
  5545. {
  5546. p->m_bNone = true;
  5547. p->m_vecAnimationProperties.RemoveAll();
  5548. return;
  5549. }
  5550. // bugbug cboyd - need to think about what to do when property counts dont match. currently, we do not change the number of properties in the
  5551. // target when a property name has been set as that count should override ours
  5552. bool bPropertiesSet = (p->m_vecAnimationProperties.Count() > 0) ? p->m_vecAnimationProperties[0].m_symName.IsValid() : false;
  5553. // add properties to target to match our count
  5554. if( !bPropertiesSet )
  5555. {
  5556. p->m_vecAnimationProperties.EnsureCapacity( m_vecAnimationProperties.Count() );
  5557. for( int i = p->m_vecAnimationProperties.Count(); i < m_vecAnimationProperties.Count(); i++ )
  5558. p->AddNewProperty();
  5559. }
  5560. // set all unset properties on target
  5561. FOR_EACH_VEC( m_vecAnimationProperties, i )
  5562. {
  5563. // we have more properties than the other guy. Stop processing.
  5564. if( bPropertiesSet && p->m_vecAnimationProperties.Count() <= i )
  5565. break;
  5566. AnimationProperty_t &animOther = p->m_vecAnimationProperties[i];
  5567. const AnimationProperty_t &animUs = m_vecAnimationProperties[i];
  5568. if( !animOther.m_symName.IsValid() )
  5569. animOther.m_symName = animUs.m_symName;
  5570. if( animOther.m_flDuration == k_flFloatNotSet )
  5571. animOther.m_flDuration = animUs.m_flDuration;
  5572. if( animOther.m_eTimingFunction == k_EAnimationUnset )
  5573. {
  5574. animOther.m_eTimingFunction = animUs.m_eTimingFunction;
  5575. animOther.m_CubicBezier = animUs.m_CubicBezier;
  5576. }
  5577. if( animOther.m_flDelay == k_flFloatNotSet )
  5578. animOther.m_flDelay = animUs.m_flDelay;
  5579. if( animOther.m_eAnimationDirection == k_EAnimationDirectionUnset )
  5580. animOther.m_eAnimationDirection = animUs.m_eAnimationDirection;
  5581. if( animOther.m_flIteration == k_flFloatNotSet )
  5582. animOther.m_flIteration = animUs.m_flIteration;
  5583. }
  5584. }
  5585. virtual bool BCanTransition() { return false; }
  5586. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  5587. void AddNewProperty()
  5588. {
  5589. int iVec = m_vecAnimationProperties.AddToTail();
  5590. AnimationProperty_t &transition = m_vecAnimationProperties[iVec];
  5591. // copy other set properties forward
  5592. if( iVec == 0 )
  5593. {
  5594. transition.m_flDuration = k_flFloatNotSet;
  5595. transition.m_eTimingFunction = k_EAnimationUnset;
  5596. Vector2D vec[4];
  5597. panorama::GetAnimationCurveControlPoints( transition.m_eTimingFunction, vec );
  5598. transition.m_CubicBezier.SetControlPoints( vec );
  5599. transition.m_flIteration = k_flFloatNotSet;
  5600. transition.m_eAnimationDirection = k_EAnimationDirectionUnset;
  5601. transition.m_flDelay = k_flFloatNotSet;
  5602. }
  5603. else
  5604. {
  5605. transition = m_vecAnimationProperties[iVec - 1];
  5606. transition.m_symName = UTL_INVAL_SYMBOL;
  5607. }
  5608. }
  5609. void SetAnimation( const char *pchAnimationName, float flDuration, float flDelay, EAnimationTimingFunction eTimingFunc, CCubicBezierCurve< Vector2D > cubicBezier, EAnimationDirection eDirection, float flIterations )
  5610. {
  5611. m_bNone = false;
  5612. m_vecAnimationProperties.RemoveAll();
  5613. AnimationProperty_t animation;
  5614. animation.m_symName = pchAnimationName;
  5615. animation.m_eTimingFunction = eTimingFunc;
  5616. animation.m_CubicBezier = cubicBezier;
  5617. animation.m_eAnimationDirection = eDirection;
  5618. animation.m_flDuration = flDuration;
  5619. animation.m_flDelay = flDelay;
  5620. animation.m_flIteration = flIterations;
  5621. m_vecAnimationProperties.AddToTail( animation );
  5622. }
  5623. // Parses string and sets value
  5624. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5625. {
  5626. static CPanoramaSymbol k_symNone = "none";
  5627. if( symParsedName == symbol )
  5628. {
  5629. m_vecAnimationProperties.RemoveAll();
  5630. // transition property format: name duration timing-function delay iteration-count animation-direction [,*]
  5631. m_bNone = false;
  5632. while( *pchString != '\0' )
  5633. {
  5634. AnimationProperty_t animation;
  5635. // get the animation name
  5636. char rgchName[k_nCSSPropertyNameMax];
  5637. if( !CSSHelpers::BParseIdent( rgchName, V_ARRAYSIZE( rgchName ), pchString, &pchString ) )
  5638. return false;
  5639. animation.m_symName = CPanoramaSymbol( rgchName );
  5640. if( animation.m_symName == k_symNone )
  5641. return false;
  5642. // get rest
  5643. if( !CSSHelpers::BParseTime( &animation.m_flDuration, pchString, &pchString ) ||
  5644. !CSSHelpers::BParseTimingFunction( &animation.m_eTimingFunction, &animation.m_CubicBezier, pchString, &pchString ) ||
  5645. !CSSHelpers::BParseTime( &animation.m_flDelay, pchString, &pchString ) ||
  5646. !BParseIterationCount( &animation.m_flIteration, pchString, &pchString ) ||
  5647. !CSSHelpers::BParseAnimationDirectionFunction( &animation.m_eAnimationDirection, pchString, &pchString ) )
  5648. {
  5649. return false;
  5650. }
  5651. m_vecAnimationProperties.AddToTail( animation );
  5652. // see if there is another transition property
  5653. if( !CSSHelpers::BSkipComma( pchString, &pchString ) )
  5654. {
  5655. // end of list.. should be an empty string
  5656. pchString = CSSHelpers::SkipSpaces( pchString );
  5657. return (pchString[0] == '\0');
  5658. }
  5659. }
  5660. return true;
  5661. }
  5662. else if( symParsedName == symbolName )
  5663. {
  5664. // comma separated list of keyframe names
  5665. CUtlVector< CPanoramaSymbol > vecNames;
  5666. if( !CSSHelpers::BParseCommaSepList( &vecNames, CSSHelpers::BParseIdentToSymbol, pchString ) )
  5667. return false;
  5668. // we also support 'none'
  5669. if( vecNames.Count() == 1 && vecNames[0] == k_symNone )
  5670. {
  5671. m_bNone = true;
  5672. return true;
  5673. }
  5674. // if we have less properties specified than other params, error
  5675. if( m_vecAnimationProperties.Count() > vecNames.Count() )
  5676. return false;
  5677. m_vecAnimationProperties.EnsureCapacity( vecNames.Count() );
  5678. FOR_EACH_VEC( vecNames, i )
  5679. {
  5680. if( vecNames[i] == k_symNone )
  5681. return false;
  5682. // new property?
  5683. if( m_vecAnimationProperties.Count() <= i )
  5684. AddNewProperty();
  5685. m_vecAnimationProperties[i].m_symName = vecNames[i];
  5686. }
  5687. return true;
  5688. }
  5689. else if( symParsedName == symbolDuration )
  5690. {
  5691. return BParseAndAddProperty( &AnimationProperty_t::m_flDuration, CSSHelpers::BParseTime, pchString );
  5692. }
  5693. else if( symParsedName == symbolDelay )
  5694. {
  5695. return BParseAndAddProperty( &AnimationProperty_t::m_flDelay, CSSHelpers::BParseTime, pchString );
  5696. }
  5697. else if( symParsedName == symbolTiming )
  5698. {
  5699. return BParseAndAddTimingFunction( CSSHelpers::BParseTimingFunction, pchString );
  5700. }
  5701. else if( symParsedName == symbolIteration )
  5702. {
  5703. return BParseAndAddProperty( &AnimationProperty_t::m_flIteration, BParseIterationCount, pchString );
  5704. }
  5705. else if( symParsedName == symbolDirection )
  5706. {
  5707. return BParseAndAddProperty( &AnimationProperty_t::m_eAnimationDirection, CSSHelpers::BParseAnimationDirectionFunction, pchString );
  5708. }
  5709. return false;
  5710. }
  5711. // Gets string representation of property
  5712. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5713. {
  5714. if( m_vecAnimationProperties.Count() == 0 || m_bNone )
  5715. {
  5716. pfmtBuffer->Append( "none" );
  5717. return;
  5718. }
  5719. FOR_EACH_VEC( m_vecAnimationProperties, i )
  5720. {
  5721. if( i > 0 )
  5722. pfmtBuffer->Append( ",\n" );
  5723. const AnimationProperty_t &prop = m_vecAnimationProperties[i];
  5724. pfmtBuffer->Append( prop.m_symName.String() );
  5725. pfmtBuffer->Append( " " );
  5726. CSSHelpers::AppendTime( pfmtBuffer, prop.m_flDuration );
  5727. if( prop.m_eTimingFunction != k_EAnimationCustomBezier )
  5728. pfmtBuffer->AppendFormat( " %s ", PchNameFromEAnimationTimingFunction( prop.m_eTimingFunction ) );
  5729. else
  5730. pfmtBuffer->AppendFormat( " cubic-bezier( %1.3f, %1.3f, %1.3f, %1.3f ) ",
  5731. prop.m_CubicBezier.ControlPoint( 1 ).x,
  5732. prop.m_CubicBezier.ControlPoint( 1 ).y,
  5733. prop.m_CubicBezier.ControlPoint( 2 ).x,
  5734. prop.m_CubicBezier.ControlPoint( 2 ).y );
  5735. CSSHelpers::AppendTime( pfmtBuffer, prop.m_flDelay );
  5736. pfmtBuffer->Append( " " );
  5737. // iteration count
  5738. if( prop.m_flIteration == k_flFloatInfiniteIteration )
  5739. pfmtBuffer->Append( "infinite" );
  5740. else
  5741. CSSHelpers::AppendFloat( pfmtBuffer, prop.m_flIteration );
  5742. // direction func
  5743. pfmtBuffer->Append( " " );
  5744. if( prop.m_eAnimationDirection == k_EAnimationDirectionNormal )
  5745. pfmtBuffer->Append( "normal" );
  5746. else if( prop.m_eAnimationDirection == k_EAnimationDirectionAlternate )
  5747. pfmtBuffer->Append( "alternate" );
  5748. else if ( prop.m_eAnimationDirection == k_EAnimationDirectionAlternateReverse )
  5749. pfmtBuffer->Append( "alternate-reverse" );
  5750. else if( prop.m_eAnimationDirection == k_EAnimationDirectionReverse )
  5751. pfmtBuffer->Append( "reverse" );
  5752. else if( prop.m_eAnimationDirection == k_EAnimationDirectionUnset )
  5753. pfmtBuffer->Append( "unset" );
  5754. else
  5755. AssertMsg( false, "Unknown animation direction" );
  5756. }
  5757. }
  5758. template < typename T >
  5759. bool BParseAndAddProperty( T AnimationProperty_t::*pProp, bool( *func )(T*, const char *, const char **), const char *pchString )
  5760. {
  5761. // parse comma separated list
  5762. CUtlVector< T > vec;
  5763. if( !CSSHelpers::BParseCommaSepList( &vec, func, pchString ) || vec.Count() == 0 )
  5764. return false;
  5765. FOR_EACH_VEC( vec, i )
  5766. {
  5767. // new property?
  5768. if( m_vecAnimationProperties.Count() <= i )
  5769. AddNewProperty();
  5770. m_vecAnimationProperties[i].*pProp = vec[i];
  5771. }
  5772. // if provided list is less than the total number of properties, fill in rest with last value
  5773. for( int i = vec.Count(); i < m_vecAnimationProperties.Count(); i++ )
  5774. m_vecAnimationProperties[i].*pProp = m_vecAnimationProperties[i - 1].*pProp;
  5775. return true;
  5776. }
  5777. bool BParseAndAddTimingFunction( bool( *func )(EAnimationTimingFunction *, CCubicBezierCurve<Vector2D> *, const char *, const char **), const char *pchString )
  5778. {
  5779. // parse comma separated list
  5780. CUtlVector< EAnimationTimingFunction > vec;
  5781. CUtlVector< CCubicBezierCurve< Vector2D > > vec2;
  5782. if( !CSSHelpers::BParseCommaSepList( &vec, &vec2, func, pchString ) || vec.Count() == 0 )
  5783. return false;
  5784. FOR_EACH_VEC( vec, i )
  5785. {
  5786. // new property?
  5787. if( m_vecAnimationProperties.Count() <= i )
  5788. AddNewProperty();
  5789. m_vecAnimationProperties[i].m_eTimingFunction = vec[i];
  5790. m_vecAnimationProperties[i].m_CubicBezier = vec2[i];
  5791. }
  5792. // if provided list is less than the total number of properties, fill in rest with last value
  5793. for( int i = vec.Count(); i < m_vecAnimationProperties.Count(); i++ )
  5794. {
  5795. m_vecAnimationProperties[i].m_eTimingFunction = m_vecAnimationProperties[i - 1].m_eTimingFunction;
  5796. m_vecAnimationProperties[i].m_CubicBezier = m_vecAnimationProperties[i - 1].m_CubicBezier;
  5797. }
  5798. return true;
  5799. }
  5800. static bool BParseIterationCount( float *pflValue, const char *pchString, const char **pchAfterParse )
  5801. {
  5802. pchString = CSSHelpers::SkipSpaces( pchString );
  5803. // special case handling for infinite
  5804. if( V_strnicmp( pchString, "infinite", V_strlen( "infinite" ) ) == 0 )
  5805. {
  5806. *pflValue = k_flFloatInfiniteIteration;
  5807. if( pchAfterParse )
  5808. *pchAfterParse = pchString + V_strlen( "infinite" );
  5809. return true;
  5810. }
  5811. // should be a number
  5812. return CSSHelpers::BParseNumber( pflValue, pchString, pchAfterParse );
  5813. }
  5814. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found by looking at lower weight styles
  5815. virtual bool BFullySet()
  5816. {
  5817. if( m_bNone )
  5818. return true;
  5819. if( m_vecAnimationProperties.Count() < 1 )
  5820. return false;
  5821. // if the first transition property is fully set, all other transition properties should be set
  5822. AnimationProperty_t &animationProperty = m_vecAnimationProperties[0];
  5823. return (animationProperty.m_symName.IsValid() &&
  5824. animationProperty.m_flDuration != k_flFloatNotSet &&
  5825. animationProperty.m_eTimingFunction != k_EAnimationUnset &&
  5826. animationProperty.m_flIteration != k_flFloatNotSet &&
  5827. animationProperty.m_eAnimationDirection != k_EAnimationDirectionUnset &&
  5828. animationProperty.m_flDelay != k_flFloatNotSet);
  5829. }
  5830. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  5831. virtual void ResolveDefaultValues()
  5832. {
  5833. if( m_vecAnimationProperties.Count() < 1 )
  5834. return;
  5835. // if property names aren't set or transition time isn't set (would default to 0), remove all and exit
  5836. AnimationProperty_t &firstProperty = m_vecAnimationProperties[0];
  5837. if( !firstProperty.m_symName.IsValid() || firstProperty.m_flDuration == k_flFloatNotSet )
  5838. {
  5839. m_vecAnimationProperties.RemoveAll();
  5840. return;
  5841. }
  5842. // set defaults
  5843. FOR_EACH_VEC( m_vecAnimationProperties, i )
  5844. {
  5845. AnimationProperty_t &animationProperty = m_vecAnimationProperties[i];
  5846. if( animationProperty.m_eTimingFunction == k_EAnimationUnset )
  5847. {
  5848. animationProperty.m_eTimingFunction = k_EAnimationEase;
  5849. Vector2D vec[4];
  5850. panorama::GetAnimationCurveControlPoints( animationProperty.m_eTimingFunction, vec );
  5851. animationProperty.m_CubicBezier.SetControlPoints( vec );
  5852. }
  5853. if( animationProperty.m_flIteration == k_flFloatNotSet )
  5854. animationProperty.m_flIteration = 1;
  5855. if( animationProperty.m_eAnimationDirection == k_EAnimationDirectionUnset )
  5856. animationProperty.m_eAnimationDirection = k_EAnimationDirectionNormal;
  5857. if( animationProperty.m_flDelay == k_flFloatNotSet )
  5858. animationProperty.m_flDelay = 0;
  5859. }
  5860. }
  5861. // Comparison function
  5862. virtual bool operator==(const CStyleProperty &other) const
  5863. {
  5864. if( GetPropertySymbol() != other.GetPropertySymbol() )
  5865. return false;
  5866. const CStylePropertyAnimationProperties &rhs = (const CStylePropertyAnimationProperties &)other;
  5867. if( m_bNone != rhs.m_bNone )
  5868. return false;
  5869. if( m_vecAnimationProperties.Count() != rhs.m_vecAnimationProperties.Count() )
  5870. return false;
  5871. FOR_EACH_VEC( m_vecAnimationProperties, i )
  5872. {
  5873. if( m_vecAnimationProperties[i] != rhs.m_vecAnimationProperties[i] )
  5874. return false;
  5875. }
  5876. return true;
  5877. }
  5878. // Layout pieces that can be invalidated when the property is applied to a panel
  5879. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  5880. #ifdef DBGFLAG_VALIDATE
  5881. virtual void Validate( CValidator &validator, const tchar *pchName )
  5882. {
  5883. VALIDATE_SCOPE();
  5884. ValidateObj( m_vecAnimationProperties );
  5885. CStyleProperty::Validate( validator, pchName );
  5886. }
  5887. #endif
  5888. CUtlVector< AnimationProperty_t > m_vecAnimationProperties;
  5889. bool m_bNone;
  5890. };
  5891. //-----------------------------------------------------------------------------
  5892. // Purpose: Padding property
  5893. //-----------------------------------------------------------------------------
  5894. class CStylePropertyPadding : public CStylePropertyDimensionsBase < CStylePropertyPadding >
  5895. {
  5896. public:
  5897. static const CStyleSymbol symbol;
  5898. static const CStyleSymbol symbolLeft;
  5899. static const CStyleSymbol symbolTop;
  5900. static const CStyleSymbol symbolBottom;
  5901. static const CStyleSymbol symbolRight;
  5902. CStylePropertyPadding() : CStylePropertyDimensionsBase<CStylePropertyPadding>() {}
  5903. };
  5904. //-----------------------------------------------------------------------------
  5905. // Purpose: Margin property
  5906. //-----------------------------------------------------------------------------
  5907. class CStylePropertyMargin : public CStylePropertyDimensionsBase < CStylePropertyMargin >
  5908. {
  5909. public:
  5910. static const CStyleSymbol symbol;
  5911. static const CStyleSymbol symbolLeft;
  5912. static const CStyleSymbol symbolTop;
  5913. static const CStyleSymbol symbolBottom;
  5914. static const CStyleSymbol symbolRight;
  5915. CStylePropertyMargin() : CStylePropertyDimensionsBase<CStylePropertyMargin>() {}
  5916. };
  5917. //-----------------------------------------------------------------------------
  5918. // Purpose: -s2-mix-blend-mode property
  5919. //-----------------------------------------------------------------------------
  5920. class CStylePropertyMixBlendMode : public CStyleProperty
  5921. {
  5922. public:
  5923. static const CStyleSymbol symbol;
  5924. CStylePropertyMixBlendMode() : CStyleProperty( CStylePropertyMixBlendMode::symbol )
  5925. {
  5926. m_bSet = false;
  5927. m_eMixBlendMode = k_EMixBlendModeNormal;
  5928. }
  5929. virtual void MergeTo( CStyleProperty *pTarget ) const
  5930. {
  5931. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  5932. {
  5933. AssertMsg( false, "Mismatched types to CStylePropertyMixBlendMode::MergeTo" );
  5934. return;
  5935. }
  5936. CStylePropertyMixBlendMode *p = (CStylePropertyMixBlendMode *)pTarget;
  5937. if( !p->m_bSet )
  5938. {
  5939. p->m_eMixBlendMode = m_eMixBlendMode;
  5940. p->m_bSet = m_bSet;
  5941. }
  5942. }
  5943. // Can this property support animation?
  5944. virtual bool BCanTransition() { return false; }
  5945. // Interpolation func for animation of this property
  5946. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  5947. {
  5948. }
  5949. // Parses string and sets value
  5950. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  5951. {
  5952. pchString = CSSHelpers::SkipSpaces( pchString );
  5953. if( V_strnicmp( pchString, "normal", V_ARRAYSIZE( "normal" ) ) == 0 )
  5954. {
  5955. m_eMixBlendMode = k_EMixBlendModeNormal;
  5956. m_bSet = true;
  5957. return true;
  5958. }
  5959. else if( V_strnicmp( pchString, "multiply", V_ARRAYSIZE( "multiply" ) ) == 0 )
  5960. {
  5961. m_eMixBlendMode = k_EMixBlendModeMultiply;
  5962. m_bSet = true;
  5963. return true;
  5964. }
  5965. else if( V_strnicmp( pchString, "screen", V_ARRAYSIZE( "screen" ) ) == 0 )
  5966. {
  5967. m_eMixBlendMode = k_EMixBlendModeScreen;
  5968. m_bSet = true;
  5969. return true;
  5970. }
  5971. return false;
  5972. }
  5973. // Gets string representation of property
  5974. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  5975. {
  5976. if( m_eMixBlendMode == k_EMixBlendModeNormal )
  5977. pfmtBuffer->Append( "normal" );
  5978. else if( m_eMixBlendMode == k_EMixBlendModeMultiply )
  5979. pfmtBuffer->Append( "multiply" );
  5980. else if( m_eMixBlendMode == k_EMixBlendModeScreen )
  5981. pfmtBuffer->Append( "screen" );
  5982. }
  5983. // Return a description for this property which will be shown in the debugger
  5984. virtual const char *GetDescription( CStyleSymbol symProperty )
  5985. {
  5986. if( symProperty == symbol )
  5987. {
  5988. return "Controls blending mode for the panel. See CSS mix-blend-mode docs on web, except normal for us is with alpha blending.<br><br>"
  5989. "<b>Examples:</b>"
  5990. "<pre>"
  5991. "-s2-mix-blend-mode: normal;\n"
  5992. "-s2-mix-blend-mode: multiply;\n"
  5993. "-s2-mix-blend-mode: screen;"
  5994. "</pre>";
  5995. }
  5996. return "";
  5997. }
  5998. // Comparison function
  5999. virtual bool operator==(const CStyleProperty &other) const
  6000. {
  6001. if( GetPropertySymbol() != other.GetPropertySymbol() )
  6002. return false;
  6003. const CStylePropertyMixBlendMode &rhs = (const CStylePropertyMixBlendMode &)other;
  6004. return (m_eMixBlendMode == rhs.m_eMixBlendMode && m_bSet == rhs.m_bSet);
  6005. }
  6006. // Layout pieces that can be invalidated when the property is applied to a panel
  6007. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  6008. EMixBlendMode m_eMixBlendMode;
  6009. bool m_bSet;
  6010. };
  6011. //-----------------------------------------------------------------------------
  6012. // Purpose: texture-sampling
  6013. //-----------------------------------------------------------------------------
  6014. class CStylePropertyTextureSampleMode : public CStyleProperty
  6015. {
  6016. public:
  6017. static const CStyleSymbol symbol;
  6018. CStylePropertyTextureSampleMode() : CStyleProperty( CStylePropertyTextureSampleMode::symbol )
  6019. {
  6020. m_bSet = false;
  6021. m_eTextureSampleMode = k_ETextureSampleModeNormal;
  6022. }
  6023. virtual void MergeTo( CStyleProperty *pTarget ) const
  6024. {
  6025. if ( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  6026. {
  6027. AssertMsg( false, "Mismatched types to CStylePropertyTextureSampleMode::MergeTo" );
  6028. return;
  6029. }
  6030. CStylePropertyTextureSampleMode *p = (CStylePropertyTextureSampleMode *)pTarget;
  6031. if ( !p->m_bSet )
  6032. {
  6033. p->m_eTextureSampleMode = m_eTextureSampleMode;
  6034. p->m_bSet = m_bSet;
  6035. }
  6036. }
  6037. // Can this property support animation?
  6038. virtual bool BCanTransition() { return false; }
  6039. // Interpolation func for animation of this property
  6040. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ )
  6041. {
  6042. }
  6043. // Parses string and sets value
  6044. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  6045. {
  6046. pchString = CSSHelpers::SkipSpaces( pchString );
  6047. if ( V_strnicmp( pchString, "normal", V_ARRAYSIZE( "normal" ) ) == 0 )
  6048. {
  6049. m_eTextureSampleMode = k_ETextureSampleModeNormal;
  6050. m_bSet = true;
  6051. return true;
  6052. }
  6053. else if ( V_strnicmp( pchString, "alpha-only", V_ARRAYSIZE( "alpha-only" ) ) == 0 )
  6054. {
  6055. m_eTextureSampleMode = k_ETextureSampleModeAlphaOnly;
  6056. m_bSet = true;
  6057. return true;
  6058. }
  6059. return false;
  6060. }
  6061. // Gets string representation of property
  6062. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  6063. {
  6064. if ( m_eTextureSampleMode == k_ETextureSampleModeNormal )
  6065. pfmtBuffer->Append( "normal" );
  6066. else if ( m_eTextureSampleMode == k_ETextureSampleModeAlphaOnly )
  6067. pfmtBuffer->Append( "alpha-only" );
  6068. }
  6069. // Return a description for this property which will be shown in the debugger
  6070. virtual const char *GetDescription( CStyleSymbol symProperty )
  6071. {
  6072. if ( symProperty == symbol )
  6073. {
  6074. return "Controls texture sampling mode for the panel. Set to alpha-only to use the textures alpha data across all 3 color channels.<br><br>"
  6075. "<b>Examples:</b>"
  6076. "<pre>"
  6077. "texture-sampling: normal;\n"
  6078. "texture-sampling: alpha-only;"
  6079. "</pre>";
  6080. }
  6081. return "";
  6082. }
  6083. // Comparison function
  6084. virtual bool operator==(const CStyleProperty &other) const
  6085. {
  6086. if ( GetPropertySymbol() != other.GetPropertySymbol() )
  6087. return false;
  6088. const CStylePropertyTextureSampleMode &rhs = (const CStylePropertyTextureSampleMode &)other;
  6089. return (m_eTextureSampleMode == rhs.m_eTextureSampleMode && m_bSet == rhs.m_bSet);
  6090. }
  6091. // Layout pieces that can be invalidated when the property is applied to a panel
  6092. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  6093. ETextureSampleMode m_eTextureSampleMode;
  6094. bool m_bSet;
  6095. };
  6096. //-----------------------------------------------------------------------------
  6097. // Purpose: Align property
  6098. //-----------------------------------------------------------------------------
  6099. class CStylePropertyAlign : public CStyleProperty
  6100. {
  6101. public:
  6102. static const CStyleSymbol symbol;
  6103. static const CStyleSymbol symbolHorizontal;
  6104. static const CStyleSymbol symbolVertical;
  6105. CStylePropertyAlign() : CStyleProperty( CStylePropertyAlign::symbol )
  6106. {
  6107. m_eHorizontalAlignment = k_EHorizontalAlignmentUnset;
  6108. m_eVerticalAlignment = k_EVerticalAlignmentUnset;
  6109. }
  6110. virtual void MergeTo( CStyleProperty *pTarget ) const
  6111. {
  6112. if( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  6113. {
  6114. AssertMsg( false, "Mismatched types to CStylePropertyAlign::MergeTo" );
  6115. return;
  6116. }
  6117. CStylePropertyAlign *p = (CStylePropertyAlign *)pTarget;
  6118. if( p->m_eHorizontalAlignment == k_EHorizontalAlignmentUnset )
  6119. p->m_eHorizontalAlignment = m_eHorizontalAlignment;
  6120. if( p->m_eVerticalAlignment == k_EVerticalAlignmentUnset )
  6121. p->m_eVerticalAlignment = m_eVerticalAlignment;
  6122. }
  6123. // Can this property support animation?
  6124. virtual bool BCanTransition() { return false; }
  6125. // Interpolation func for animation of this property
  6126. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  6127. // Parses string and sets value
  6128. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  6129. {
  6130. if( symParsedName == symbol )
  6131. {
  6132. return CSSHelpers::BParseHorizontalAlignment( &m_eHorizontalAlignment, pchString, &pchString ) && CSSHelpers::BParseVerticalAlignment( &m_eVerticalAlignment, pchString, &pchString );
  6133. }
  6134. else if( symParsedName == symbolHorizontal )
  6135. {
  6136. return CSSHelpers::BParseHorizontalAlignment( &m_eHorizontalAlignment, pchString, &pchString );
  6137. }
  6138. else if( symParsedName == symbolVertical )
  6139. {
  6140. return CSSHelpers::BParseVerticalAlignment( &m_eVerticalAlignment, pchString, &pchString );
  6141. }
  6142. return false;
  6143. }
  6144. // Gets string representation of property
  6145. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  6146. {
  6147. pfmtBuffer->AppendFormat( "%s %s", PchNameFromEHorizontalAlignment( m_eHorizontalAlignment ), PchNameFromEVerticalAlignment( m_eVerticalAlignment ) );
  6148. }
  6149. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  6150. // by looking at lower weight styles
  6151. virtual bool BFullySet()
  6152. {
  6153. return (m_eHorizontalAlignment != k_EHorizontalAlignmentUnset && m_eVerticalAlignment != k_EVerticalAlignmentUnset);
  6154. }
  6155. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  6156. virtual void ResolveDefaultValues()
  6157. {
  6158. if( m_eHorizontalAlignment == k_EHorizontalAlignmentUnset )
  6159. m_eHorizontalAlignment = k_EHorizontalAlignmentLeft;
  6160. if( m_eVerticalAlignment == k_EVerticalAlignmentUnset )
  6161. m_eVerticalAlignment = k_EVerticalAlignmentTop;
  6162. }
  6163. // Comparison function
  6164. virtual bool operator==(const CStyleProperty &other) const
  6165. {
  6166. if( GetPropertySymbol() != other.GetPropertySymbol() )
  6167. return false;
  6168. const CStylePropertyAlign &rhs = (const CStylePropertyAlign &)other;
  6169. return (m_eHorizontalAlignment == rhs.m_eHorizontalAlignment && m_eVerticalAlignment == rhs.m_eVerticalAlignment);
  6170. }
  6171. // Layout pieces that can be invalidated when the property is applied to a panel
  6172. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  6173. {
  6174. if( !pCompareProperty || !(*this == *pCompareProperty) )
  6175. return k_EStyleInvalidateLayoutPosition;
  6176. return k_EStyleInvalidateLayoutNone;
  6177. }
  6178. EHorizontalAlignment m_eHorizontalAlignment;
  6179. EVerticalAlignment m_eVerticalAlignment;
  6180. };
  6181. //-----------------------------------------------------------------------------
  6182. // Purpose: Context UI Position property base class
  6183. //-----------------------------------------------------------------------------
  6184. class CStylePropertyContextUIPosition : public CStyleProperty
  6185. {
  6186. public:
  6187. CStylePropertyContextUIPosition( CStyleSymbol symPropertyName ) : CStyleProperty( symPropertyName )
  6188. {
  6189. for ( EContextUIPosition &ePosition : m_ePositions )
  6190. {
  6191. ePosition = k_EContextUIPositionUnset;
  6192. }
  6193. }
  6194. virtual void MergeTo( CStyleProperty *pTarget ) const
  6195. {
  6196. if ( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  6197. {
  6198. AssertMsg( false, "Mismatched types to CStylePropertyTooltipPosition::MergeTo" );
  6199. return;
  6200. }
  6201. CStylePropertyContextUIPosition *p = ( CStylePropertyContextUIPosition * )pTarget;
  6202. for ( int i = 0; i < V_ARRAYSIZE( m_ePositions ); ++i )
  6203. {
  6204. if ( p->m_ePositions[ i ] == k_EContextUIPositionUnset )
  6205. p->m_ePositions[ i ] = m_ePositions[ i ];
  6206. }
  6207. }
  6208. // Can this property support animation?
  6209. virtual bool BCanTransition() { return false; }
  6210. // Interpolation func for animation of this property
  6211. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  6212. // Parses string and sets value
  6213. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  6214. {
  6215. char rgchPosition[ 128 ];
  6216. int i = 0;
  6217. while ( *pchString != '\0' )
  6218. {
  6219. if ( !CSSHelpers::BParseIdent( rgchPosition, V_ARRAYSIZE( rgchPosition ), pchString, &pchString ) )
  6220. return i != 0;
  6221. if ( i >= V_ARRAYSIZE( m_ePositions ) )
  6222. return false;
  6223. if ( V_stricmp( rgchPosition, "left" ) == 0 )
  6224. m_ePositions[ i ] = k_EContextUIPositionLeft;
  6225. else if ( V_stricmp( rgchPosition, "top" ) == 0 )
  6226. m_ePositions[ i ] = k_EContextUIPositionTop;
  6227. else if ( V_stricmp( rgchPosition, "right" ) == 0 )
  6228. m_ePositions[ i ] = k_EContextUIPositionRight;
  6229. else if ( V_stricmp( rgchPosition, "bottom" ) == 0 )
  6230. m_ePositions[ i ] = k_EContextUIPositionBottom;
  6231. else
  6232. return false;
  6233. ++i;
  6234. }
  6235. return true;
  6236. }
  6237. // Gets string representation of property
  6238. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  6239. {
  6240. bool bFirst = true;
  6241. for ( EContextUIPosition ePosition : m_ePositions )
  6242. {
  6243. if ( bFirst )
  6244. {
  6245. bFirst = false;
  6246. }
  6247. else
  6248. {
  6249. pfmtBuffer->Append( " " );
  6250. }
  6251. pfmtBuffer->AppendFormat( "%s", PchNameFromEContextUIPosition( ePosition ) );
  6252. }
  6253. }
  6254. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  6255. // by looking at lower weight styles
  6256. virtual bool BFullySet()
  6257. {
  6258. for ( EContextUIPosition ePosition : m_ePositions )
  6259. {
  6260. if ( ePosition == k_EContextUIPositionUnset )
  6261. return false;
  6262. }
  6263. return true;
  6264. }
  6265. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  6266. virtual void ResolveDefaultValues()
  6267. {
  6268. ResolveDefaultPositions( m_ePositions );
  6269. }
  6270. static void ResolveDefaultPositions( EContextUIPosition( &ePositions )[ 4 ] )
  6271. {
  6272. // By default, pick "right" if it's not set
  6273. if ( ePositions[ 0 ] == k_EContextUIPositionUnset )
  6274. {
  6275. ePositions[ 0 ] = k_EContextUIPositionRight;
  6276. }
  6277. // By default, just swap which side the tooltip is on for the second option
  6278. if ( ePositions[ 1 ] == k_EContextUIPositionUnset || ePositions[ 1 ] == ePositions[ 0 ] )
  6279. {
  6280. if ( ePositions[ 0 ] == k_EContextUIPositionLeft )
  6281. ePositions[ 1 ] = k_EContextUIPositionRight;
  6282. else if ( ePositions[ 0 ] == k_EContextUIPositionRight )
  6283. ePositions[ 1 ] = k_EContextUIPositionLeft;
  6284. else if ( ePositions[ 0 ] == k_EContextUIPositionTop )
  6285. ePositions[ 1 ] = k_EContextUIPositionBottom;
  6286. else // eTooltipPositions[ 0 ] == k_EContextUIPositionBottom
  6287. ePositions[ 1 ] = k_EContextUIPositionTop;
  6288. }
  6289. // The third spot is normally the opposite of the first spot, unless those are both already used. Then it's just right or bottom.
  6290. if ( ePositions[ 2 ] == k_EContextUIPositionUnset || ( ePositions[ 2 ] == ePositions[ 0 ] || ePositions[ 2 ] == ePositions[ 1 ] ) )
  6291. {
  6292. if ( ( ePositions[ 0 ] == k_EContextUIPositionLeft && ePositions[ 1 ] == k_EContextUIPositionRight ) ||
  6293. ( ePositions[ 0 ] == k_EContextUIPositionRight && ePositions[ 1 ] == k_EContextUIPositionLeft ) )
  6294. {
  6295. ePositions[ 2 ] = k_EContextUIPositionBottom;
  6296. }
  6297. else if ( ( ePositions[ 0 ] == k_EContextUIPositionTop && ePositions[ 1 ] == k_EContextUIPositionBottom ) ||
  6298. ( ePositions[ 0 ] == k_EContextUIPositionBottom && ePositions[ 1 ] == k_EContextUIPositionTop ) )
  6299. {
  6300. ePositions[ 2 ] = k_EContextUIPositionRight;
  6301. }
  6302. else
  6303. {
  6304. if ( ePositions[ 0 ] == k_EContextUIPositionLeft )
  6305. ePositions[ 2 ] = k_EContextUIPositionRight;
  6306. else if ( ePositions[ 0 ] == k_EContextUIPositionRight )
  6307. ePositions[ 2 ] = k_EContextUIPositionLeft;
  6308. else if ( ePositions[ 0 ] == k_EContextUIPositionTop )
  6309. ePositions[ 2 ] = k_EContextUIPositionBottom;
  6310. else // eTooltipPositions[ 0 ] == k_EContextUIPositionBottom
  6311. ePositions[ 2 ] = k_EContextUIPositionTop;
  6312. }
  6313. }
  6314. // The last spot is just whatever is still leftover
  6315. if ( ePositions[ 3 ] == k_EContextUIPositionUnset || ( ePositions[ 3 ] == ePositions[ 0 ] || ePositions[ 3 ] == ePositions[ 1 ] || ePositions[ 3 ] == ePositions[ 2 ] ) )
  6316. {
  6317. CUtlVector< EContextUIPosition > vecPositions( 0, 4 );
  6318. const EContextUIPosition arrAllPositions[] = { k_EContextUIPositionLeft, k_EContextUIPositionTop, k_EContextUIPositionRight, k_EContextUIPositionBottom };
  6319. vecPositions.CopyArray( arrAllPositions, V_ARRAYSIZE( arrAllPositions ) );
  6320. for ( int i = 0; i < 3; ++i )
  6321. {
  6322. vecPositions.FindAndFastRemove( ePositions[ i ] );
  6323. }
  6324. ePositions[ 3 ] = vecPositions[ 0 ];
  6325. }
  6326. }
  6327. // Comparison function
  6328. virtual bool operator==( const CStyleProperty &other ) const
  6329. {
  6330. if ( GetPropertySymbol() != other.GetPropertySymbol() )
  6331. return false;
  6332. const CStylePropertyContextUIPosition &rhs = ( const CStylePropertyContextUIPosition & )other;
  6333. for ( int i = 0; i < V_ARRAYSIZE( m_ePositions ); ++i )
  6334. {
  6335. if ( m_ePositions[ i ] != rhs.m_ePositions[ i ] )
  6336. return false;
  6337. }
  6338. return true;
  6339. }
  6340. // Layout pieces that can be invalidated when the property is applied to a panel
  6341. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  6342. EContextUIPosition m_ePositions[ 4 ];
  6343. };
  6344. //-----------------------------------------------------------------------------
  6345. // Purpose: Tooltip Position property
  6346. //-----------------------------------------------------------------------------
  6347. class CStylePropertyTooltipPosition : public CStylePropertyContextUIPosition
  6348. {
  6349. public:
  6350. static const CStyleSymbol symbol;
  6351. CStylePropertyTooltipPosition() : CStylePropertyContextUIPosition( CStylePropertyTooltipPosition::symbol )
  6352. {
  6353. }
  6354. // Return a description for this property which will be shown in the debugger
  6355. virtual const char *GetDescription( CStyleSymbol symProperty )
  6356. {
  6357. return "Specifies where to position a tooltip relative to this panel. Valid options include 'left', 'top', 'right', and 'bottom'. "
  6358. "List up to 4 positions to determine the order that positions are tried if the tooltip doesn't fully fit on screen. Default "
  6359. "is 'right left bottom top'. If less than 4 positions are specified, the tooltip first tries the opposite of the specified "
  6360. "position along the same axis before switching to the other axis.<br><br>"
  6361. "<b>Examples:</b>"
  6362. "<pre>"
  6363. "tooltip-position: bottom;\n"
  6364. "tooltip-position: left bottom;"
  6365. "</pre>";
  6366. }
  6367. };
  6368. //-----------------------------------------------------------------------------
  6369. // Purpose: Context Menu Position property
  6370. //-----------------------------------------------------------------------------
  6371. class CStylePropertyContextMenuPosition : public CStylePropertyContextUIPosition
  6372. {
  6373. public:
  6374. static const CStyleSymbol symbol;
  6375. CStylePropertyContextMenuPosition() : CStylePropertyContextUIPosition( CStylePropertyContextMenuPosition::symbol )
  6376. {
  6377. }
  6378. // Return a description for this property which will be shown in the debugger
  6379. virtual const char *GetDescription( CStyleSymbol symProperty )
  6380. {
  6381. return "Specifies where to position a context menu relative to this panel. Valid options include 'left', 'top', 'right', and 'bottom'. "
  6382. "List up to 4 positions to determine the order that positions are tried if the context menu doesn't fully fit on screen. Default "
  6383. "is 'right left bottom top'. If less than 4 positions are specified, the context menu first tries the opposite of the specified "
  6384. "position along the same axis before switching to the other axis.<br><br>"
  6385. "<b>Examples:</b>"
  6386. "<pre>"
  6387. "context-menu-position: bottom;\n"
  6388. "context-menu-position: left bottom;"
  6389. "</pre>";
  6390. }
  6391. };
  6392. //-----------------------------------------------------------------------------
  6393. // Purpose: Base class for ContextUI Component Position properties
  6394. //-----------------------------------------------------------------------------
  6395. class CStylePropertyContextUIComponentPosition : public CStyleProperty
  6396. {
  6397. public:
  6398. CStylePropertyContextUIComponentPosition( CStyleSymbol symPropertyName ) : CStyleProperty( symPropertyName )
  6399. {
  6400. }
  6401. virtual void MergeTo( CStyleProperty *pTarget ) const
  6402. {
  6403. if ( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  6404. {
  6405. AssertMsg( false, "Mismatched types to CStylePropertyTooltipComponentPosition::MergeTo" );
  6406. return;
  6407. }
  6408. CStylePropertyContextUIComponentPosition *p = ( CStylePropertyContextUIComponentPosition * )pTarget;
  6409. if ( !p->m_HorizontalPosition.IsSet() )
  6410. {
  6411. p->m_HorizontalPosition = m_HorizontalPosition;
  6412. }
  6413. if ( !p->m_VerticalPosition.IsSet() )
  6414. {
  6415. p->m_VerticalPosition = m_VerticalPosition;
  6416. }
  6417. }
  6418. // Can this property support animation?
  6419. virtual bool BCanTransition() { return false; }
  6420. // Interpolation func for animation of this property
  6421. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  6422. // Parses string and sets value
  6423. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  6424. {
  6425. return CSSHelpers::BParseIntoTwoUILengths( &m_HorizontalPosition, &m_VerticalPosition, pchString, &pchString );
  6426. }
  6427. // Gets string representation of property
  6428. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  6429. {
  6430. CSSHelpers::AppendUILength( pfmtBuffer, m_HorizontalPosition );
  6431. pfmtBuffer->Append( " " );
  6432. CSSHelpers::AppendUILength( pfmtBuffer, m_VerticalPosition );
  6433. }
  6434. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  6435. // by looking at lower weight styles
  6436. virtual bool BFullySet()
  6437. {
  6438. return m_HorizontalPosition.IsSet() && m_VerticalPosition.IsSet();
  6439. }
  6440. // Comparison function
  6441. virtual bool operator==( const CStyleProperty &other ) const
  6442. {
  6443. if ( GetPropertySymbol() != other.GetPropertySymbol() )
  6444. return false;
  6445. const CStylePropertyContextUIComponentPosition &rhs = ( const CStylePropertyContextUIComponentPosition & )other;
  6446. return m_HorizontalPosition == rhs.m_HorizontalPosition && m_VerticalPosition == rhs.m_VerticalPosition;
  6447. }
  6448. // Layout pieces that can be invalidated when the property is applied to a panel
  6449. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const { return k_EStyleInvalidateLayoutNone; }
  6450. CUILength m_HorizontalPosition;
  6451. CUILength m_VerticalPosition;
  6452. };
  6453. //-----------------------------------------------------------------------------
  6454. // Purpose: ContextUI Body Position property base class
  6455. //-----------------------------------------------------------------------------
  6456. class CStylePropertyContextUIBodyPosition : public CStylePropertyContextUIComponentPosition
  6457. {
  6458. public:
  6459. CStylePropertyContextUIBodyPosition( CStyleSymbol symPropertyName ) : CStylePropertyContextUIComponentPosition( symPropertyName )
  6460. {
  6461. }
  6462. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  6463. virtual void ResolveDefaultValues()
  6464. {
  6465. ResolveDefaultBodyPosition( m_HorizontalPosition, m_VerticalPosition );
  6466. }
  6467. static void ResolveDefaultBodyPosition( CUILength &horizontalPosition, CUILength &verticalPosition )
  6468. {
  6469. if ( !horizontalPosition.IsSet() )
  6470. {
  6471. horizontalPosition.SetPercent( 0.0f );
  6472. }
  6473. if ( !verticalPosition.IsSet() )
  6474. {
  6475. verticalPosition.SetPercent( 0.0f );
  6476. }
  6477. }
  6478. };
  6479. //-----------------------------------------------------------------------------
  6480. // Purpose: Tooltip Body Position property
  6481. //-----------------------------------------------------------------------------
  6482. class CStylePropertyTooltipBodyPosition : public CStylePropertyContextUIBodyPosition
  6483. {
  6484. public:
  6485. static const CStyleSymbol symbol;
  6486. CStylePropertyTooltipBodyPosition() : CStylePropertyContextUIBodyPosition( CStylePropertyTooltipBodyPosition::symbol )
  6487. {
  6488. }
  6489. // Return a description for this property which will be shown in the debugger
  6490. virtual const char *GetDescription( CStyleSymbol symProperty )
  6491. {
  6492. return "Specifies where to position the body of a tooltip relative to this panel. The first value controls how the body is "
  6493. "aligned horizontally when the tooltip is to the top or bottom of the panel, and the second value controls how the body is "
  6494. "aligned vertically when the tooltip is to the left or right of the panel. 0% means left/top aligned, 50% means "
  6495. "center/middle aligned, and 100% means right/bottom aligned. Default is '0% 0%'.<br><br>"
  6496. "<b>Example:</b>"
  6497. "<pre>"
  6498. "tooltip-body-position: 50% 100%;"
  6499. "</pre>";
  6500. }
  6501. };
  6502. //-----------------------------------------------------------------------------
  6503. // Purpose: Context Menu Body Position property
  6504. //-----------------------------------------------------------------------------
  6505. class CStylePropertyContextMenuBodyPosition : public CStylePropertyContextUIBodyPosition
  6506. {
  6507. public:
  6508. static const CStyleSymbol symbol;
  6509. CStylePropertyContextMenuBodyPosition() : CStylePropertyContextUIBodyPosition( CStylePropertyContextMenuBodyPosition::symbol )
  6510. {
  6511. }
  6512. // Return a description for this property which will be shown in the debugger
  6513. virtual const char *GetDescription( CStyleSymbol symProperty )
  6514. {
  6515. return "Specifies where to position the body of a context menu relative to this panel. The first value controls how the body is "
  6516. "aligned horizontally when the context menu is to the top or bottom of the panel, and the second value controls how the body is "
  6517. "aligned vertically when the context menu is to the left or right of the panel. 0% means left/top aligned, 50% means "
  6518. "center/middle aligned, and 100% means right/bottom aligned. Default is '0% 0%'.<br><br>"
  6519. "<b>Example:</b>"
  6520. "<pre>"
  6521. "context-menu-body-position: 50% 100%;"
  6522. "</pre>";
  6523. }
  6524. };
  6525. //-----------------------------------------------------------------------------
  6526. // Purpose: ContextUI Arrow Position property base class
  6527. //-----------------------------------------------------------------------------
  6528. class CStylePropertyContextUIArrowPosition : public CStylePropertyContextUIComponentPosition
  6529. {
  6530. public:
  6531. CStylePropertyContextUIArrowPosition( CStyleSymbol symPropertyName ) : CStylePropertyContextUIComponentPosition( symPropertyName )
  6532. {
  6533. }
  6534. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  6535. virtual void ResolveDefaultValues()
  6536. {
  6537. ResolveDefaultArrowPosition( m_HorizontalPosition, m_VerticalPosition );
  6538. }
  6539. static void ResolveDefaultArrowPosition( CUILength &horizontalPosition, CUILength &verticalPosition )
  6540. {
  6541. if ( !horizontalPosition.IsSet() )
  6542. {
  6543. horizontalPosition.SetPercent( 50.0f );
  6544. }
  6545. if ( !verticalPosition.IsSet() )
  6546. {
  6547. verticalPosition.SetPercent( 50.0f );
  6548. }
  6549. }
  6550. };
  6551. //-----------------------------------------------------------------------------
  6552. // Purpose: Tooltip Arrow Position property
  6553. //-----------------------------------------------------------------------------
  6554. class CStylePropertyTooltipArrowPosition : public CStylePropertyContextUIArrowPosition
  6555. {
  6556. public:
  6557. static const CStyleSymbol symbol;
  6558. CStylePropertyTooltipArrowPosition() : CStylePropertyContextUIArrowPosition( CStylePropertyTooltipArrowPosition::symbol )
  6559. {
  6560. }
  6561. // Return a description for this property which will be shown in the debugger
  6562. virtual const char *GetDescription( CStyleSymbol symProperty )
  6563. {
  6564. return "Specifies where to point the arrow of a tooltip at on this panel. The first value controls how the arrow is "
  6565. "positioned horizontally when the tooltip is to the top or bottom of the panel, and the second value controls how the arrow is "
  6566. "positioned vertically when the tooltip is to the left or right of the panel. Default is '50% 50%'.<br><br>"
  6567. "<b>Example:</b>"
  6568. "<pre>"
  6569. "tooltip-arrow-position: 25% 50%;"
  6570. "</pre>";
  6571. }
  6572. };
  6573. //-----------------------------------------------------------------------------
  6574. // Purpose: Context Menu Arrow Position property
  6575. //-----------------------------------------------------------------------------
  6576. class CStylePropertyContextMenuArrowPosition : public CStylePropertyContextUIArrowPosition
  6577. {
  6578. public:
  6579. static const CStyleSymbol symbol;
  6580. CStylePropertyContextMenuArrowPosition() : CStylePropertyContextUIArrowPosition( CStylePropertyContextMenuArrowPosition::symbol )
  6581. {
  6582. }
  6583. // Return a description for this property which will be shown in the debugger
  6584. virtual const char *GetDescription( CStyleSymbol symProperty )
  6585. {
  6586. return "Specifies where to point the arrow of a context menu at on this panel. The first value controls how the arrow is "
  6587. "positioned horizontally when the context menu is to the top or bottom of the panel, and the second value controls how the arrow is "
  6588. "positioned vertically when the context menu is to the left or right of the panel. Default is '50% 50%'.<br><br>"
  6589. "<b>Example:</b>"
  6590. "<pre>"
  6591. "context-menu-arrow-position: 25% 50%;"
  6592. "</pre>";
  6593. }
  6594. };
  6595. //-----------------------------------------------------------------------------
  6596. // Purpose: Sound property base class
  6597. //-----------------------------------------------------------------------------
  6598. class CStylePropertySound : public CStyleProperty
  6599. {
  6600. public:
  6601. CStylePropertySound( CStyleSymbol symPropertyName ) : CStyleProperty( symPropertyName )
  6602. {
  6603. }
  6604. virtual void MergeTo( CStyleProperty *pTarget ) const
  6605. {
  6606. if ( pTarget->GetPropertySymbol() != GetPropertySymbol() )
  6607. {
  6608. AssertMsg( false, "Mismatched types to CStylePropertySound::MergeTo" );
  6609. return;
  6610. }
  6611. CStylePropertySound *p = ( CStylePropertySound * )pTarget;
  6612. if ( p->m_strSoundName.IsEmpty() )
  6613. p->m_strSoundName = m_strSoundName;
  6614. }
  6615. // Can this property support animation?
  6616. virtual bool BCanTransition() { return false; }
  6617. // Interpolation func for animation of this property
  6618. virtual void Interpolate( IUIPanel *pPanel, const CStyleProperty &target, float flProgress /* 0.0->1.0 */ ) {}
  6619. // Parses string and sets value
  6620. virtual bool BSetFromString( CStyleSymbol symParsedName, const char *pchString )
  6621. {
  6622. return CSSHelpers::BParseQuotedString( m_strSoundName, pchString );
  6623. }
  6624. // Gets string representation of property
  6625. virtual void ToString( CFmtStr1024 *pfmtBuffer ) const
  6626. {
  6627. pfmtBuffer->AppendFormat( "\"%s\"", m_strSoundName.Get() );
  6628. }
  6629. // When applying styles to an element, used to determine if all data for this property has been set or if more fields should be found
  6630. // by looking at lower weight styles
  6631. virtual bool BFullySet()
  6632. {
  6633. return !m_strSoundName.IsEmpty();
  6634. }
  6635. // called when applied to a panel. Gives the style an opportunity to change any unset values to defaults
  6636. virtual void ResolveDefaultValues()
  6637. {
  6638. }
  6639. // Comparison function
  6640. virtual bool operator==( const CStyleProperty &other ) const
  6641. {
  6642. if ( GetPropertySymbol() != other.GetPropertySymbol() )
  6643. return false;
  6644. const CStylePropertySound &rhs = ( const CStylePropertySound & )other;
  6645. return m_strSoundName == rhs.m_strSoundName;
  6646. }
  6647. // Layout pieces that can be invalidated when the property is applied to a panel
  6648. virtual EStyleInvalidateLayout GetInvalidateLayout( CStyleProperty *pCompareProperty ) const
  6649. {
  6650. return k_EStyleInvalidateLayoutNone;
  6651. }
  6652. CUtlString m_strSoundName;
  6653. };
  6654. //-----------------------------------------------------------------------------
  6655. // Purpose: Entrance sound property
  6656. //-----------------------------------------------------------------------------
  6657. class CStylePropertyEntranceSound : public CStylePropertySound
  6658. {
  6659. public:
  6660. static const CStyleSymbol symbol;
  6661. CStylePropertyEntranceSound() : CStylePropertySound( CStylePropertyEntranceSound::symbol )
  6662. {
  6663. }
  6664. // Return a description for this property which will be shown in the debugger
  6665. virtual const char *GetDescription( CStyleSymbol symProperty )
  6666. {
  6667. return "Specifies a sound name to play when this selector is applied.<br><br>"
  6668. "<b>Example:</b>"
  6669. "<pre>"
  6670. "sound: \"whoosh_in\";"
  6671. "</pre>";
  6672. }
  6673. };
  6674. //-----------------------------------------------------------------------------
  6675. // Purpose: Exit sound property
  6676. //-----------------------------------------------------------------------------
  6677. class CStylePropertyExitSound : public CStylePropertySound
  6678. {
  6679. public:
  6680. static const CStyleSymbol symbol;
  6681. CStylePropertyExitSound() : CStylePropertySound( CStylePropertyExitSound::symbol )
  6682. {
  6683. }
  6684. // Return a description for this property which will be shown in the debugger
  6685. virtual const char *GetDescription( CStyleSymbol symProperty )
  6686. {
  6687. return "Specifies a sound name to play when this selector is removed.<br><br>"
  6688. "<b>Example:</b>"
  6689. "<pre>"
  6690. "sound-out: \"whoosh_out\";"
  6691. "</pre>";
  6692. }
  6693. };
  6694. } // namespace panorama
  6695. #endif // STYLEPROPERTIES_H