|
1 /* |
|
2 * Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Common utility functions |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "xnchilditeratorbuilder.h" |
|
20 #include "xnnodeappif.h" |
|
21 #include "xnproperty.h" |
|
22 #include "xndomlist.h" |
|
23 #include "mxndomlistitem.h" |
|
24 #include "xndomproperty.h" |
|
25 #include "xndompropertyvalue.h" |
|
26 #include "xnuiengineappif.h" |
|
27 |
|
28 #include <AknsItemID.h> |
|
29 #include <AknsUtils.h> |
|
30 #include <AknsSkinInstance.h> |
|
31 #include <gulicon.h> |
|
32 #include <SVGEngineInterfaceImpl.h> |
|
33 #include <gdi.h> |
|
34 #include <mifconvdefs.h> |
|
35 #include "xnnode.h" |
|
36 |
|
37 #include "aixmluiutils.h" |
|
38 #include "aixmluiconstants.h" |
|
39 #include "csspropertymap.h" |
|
40 #include "aipolicyelement.h" |
|
41 #include "transaction.h" |
|
42 #include "debug.h" |
|
43 |
|
44 #include "xnbreadthfirsttreeiterator.h" |
|
45 namespace |
|
46 { |
|
47 |
|
48 /** |
|
49 * CSS Property value update types. |
|
50 */ |
|
51 enum TPropertyUpdateType |
|
52 { |
|
53 EAbsoluteValue = 0, |
|
54 EAddition, |
|
55 ESubtraction, |
|
56 EIncrementalAddition, |
|
57 EIncrementalSubtraction |
|
58 }; |
|
59 |
|
60 /** |
|
61 * |
|
62 */ |
|
63 _LIT8( KAdditionOperator, "+" ); |
|
64 |
|
65 _LIT8( KIncrementalAdditionOperator, "++" ); |
|
66 |
|
67 _LIT8( KSubtractionOperator, "-" ); |
|
68 |
|
69 _LIT8( KIncrementalSubtractionOperator, "--" ); |
|
70 |
|
71 const TInt KLenAddSubOperator = 1; |
|
72 |
|
73 const TInt KLenIncrementalOperator = 2; |
|
74 |
|
75 _LIT( KMIFExtension, ".mif" ); |
|
76 |
|
77 // _LIT( KSVGExtension, ".svg" ); |
|
78 |
|
79 _LIT( KHashmark, "#" ); |
|
80 |
|
81 const TUint8 KDoubleQuote = '"'; |
|
82 |
|
83 const TUint8 KSingleQuote = '\''; |
|
84 |
|
85 const TInt KLenDoubleQuotes = 2; |
|
86 const TInt KDepthT = 1; |
|
87 |
|
88 class TIconProvider : public MAknIconFileProvider |
|
89 { |
|
90 public: |
|
91 /** |
|
92 * Constructor |
|
93 * @param aFile File handle to use |
|
94 */ |
|
95 TIconProvider(RFile& aFile) : iFile(aFile) |
|
96 { |
|
97 } |
|
98 public: |
|
99 |
|
100 /** |
|
101 * Destructor. |
|
102 */ |
|
103 virtual ~TIconProvider() |
|
104 { |
|
105 iFile.Close(); |
|
106 } |
|
107 // Functions from base classes |
|
108 /** |
|
109 * From MAknIconFileProvider Returns an open file handle to the icon file. |
|
110 * This method should leave if an icon file with specified type does |
|
111 * not exist. That may be the case e.g. with MBM file, |
|
112 * if there are no bitmap icons. |
|
113 * |
|
114 * Note! RFs::ShareProtected must be called to the RFs instance used |
|
115 * for opening the file. |
|
116 * |
|
117 * @param aFile Icon file should be opened in this file handle, which |
|
118 * is an empty file handle, when the AknIcon framework calls this method. |
|
119 * The AknIcon framework takes care of closing the file handle after |
|
120 * having used it. |
|
121 * @param aType Icon file type. |
|
122 */ |
|
123 virtual void RetrieveIconFileHandleL( |
|
124 RFile& aFile, const TIconFileType /*aType*/ ) |
|
125 { |
|
126 aFile.Duplicate(iFile); |
|
127 } |
|
128 |
|
129 /** |
|
130 * From MAknIconFileProvider With this method, AknIcon framework informs that it does not use |
|
131 * this MAknIconFileProvider instance any more. After this call, |
|
132 * it is ok to delete the object. This can be implemented simply |
|
133 * e.g. by deleting self in this callback. |
|
134 * Normally, this callback is invoked when the icon in question |
|
135 * is deleted. |
|
136 * Note, however, that if the same MAknIconFileProvider instance is |
|
137 * supplied in multiple CreateIcon calls, then it must be accessible |
|
138 * by AknIcon framework until it has signalled a matching amount |
|
139 * of these callbacks. |
|
140 */ |
|
141 virtual void Finished() |
|
142 { |
|
143 iFile.Close(); |
|
144 delete this; |
|
145 } |
|
146 private: |
|
147 // file to use |
|
148 RFile iFile; |
|
149 }; |
|
150 |
|
151 /** |
|
152 * Tests if string ends with given pattern |
|
153 * |
|
154 * @param aString input string |
|
155 * @param aPattern test pattern |
|
156 * @return ETrue if string ends with given pattern. |
|
157 */ |
|
158 TBool EndsWith( const TDesC8& aString, const TDesC8& aPattern ) |
|
159 { |
|
160 return ( aString.Right( aPattern.Length() ) == aPattern ); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Tests if string ends with given pattern |
|
165 * |
|
166 * @param aString input string |
|
167 * @param aPattern test pattern |
|
168 * @return ETrue if string ends with given pattern. |
|
169 */ |
|
170 TBool EndsWith( const TDesC& aString, const TDesC& aPattern ) |
|
171 { |
|
172 return ( aString.Right( aPattern.Length() ) == aPattern ); |
|
173 } |
|
174 /** |
|
175 * Removes pattern from the end of string. Function does not validate |
|
176 * that the pattern is in the end of string. It just cuts out the number |
|
177 * of aPattern length characters from the string. |
|
178 * |
|
179 * @param aString input string |
|
180 * @param aPattern pattern |
|
181 * @return string without pattern. |
|
182 */ |
|
183 TPtrC8 Strip( const TDesC8& aString, const TDesC8& aPattern ) |
|
184 { |
|
185 return aString.Left( aString.Length() - aPattern.Length() ); |
|
186 } |
|
187 |
|
188 /** |
|
189 * Selects a proper string data value type |
|
190 */ |
|
191 CXnDomPropertyValue::TPrimitiveValueType SelectStringDataType( |
|
192 const TDesC8& aPropertyName, |
|
193 const TDesC8& aPropertyValue ) |
|
194 { |
|
195 if ( aPropertyName == XnPropertyNames::style::common::KDisplay |
|
196 && ( aPropertyValue == XnPropertyNames::style::common::display::KBlock |
|
197 || aPropertyValue == XnPropertyNames::style::common::display::KNone ) ) |
|
198 { |
|
199 return CXnDomPropertyValue::EString; |
|
200 } |
|
201 |
|
202 if ( aPropertyName == XnPropertyNames::style::common::KVisibility |
|
203 && ( aPropertyValue == XnPropertyNames::style::common::visibility::KVisible |
|
204 || aPropertyValue == XnPropertyNames::style::common::visibility::KHidden ) ) |
|
205 { |
|
206 return CXnDomPropertyValue::EString; |
|
207 } |
|
208 if ( aPropertyName == XnPropertyNames::style::common::KNavIndex ) |
|
209 { |
|
210 return CXnDomPropertyValue::EIdent; |
|
211 } |
|
212 |
|
213 return CXnDomPropertyValue::EUnknown; |
|
214 } |
|
215 |
|
216 /** |
|
217 * Validates string |
|
218 */ |
|
219 TBool IsValidCssString( const TDesC8& aString ) |
|
220 { |
|
221 // Null string or unquoted string is not a CSS string |
|
222 if ( aString.Length() < KLenDoubleQuotes ) |
|
223 { |
|
224 return EFalse; |
|
225 } |
|
226 |
|
227 const TUint8 quotationMark( aString[0] ); |
|
228 if ( ( quotationMark == KDoubleQuote || quotationMark == KSingleQuote ) |
|
229 && aString[ aString.Length() - 1 ] == quotationMark ) |
|
230 { |
|
231 return ETrue; |
|
232 } |
|
233 |
|
234 return EFalse; |
|
235 } |
|
236 |
|
237 /** |
|
238 * Removes extra quotes from strings. Assumes that the string is quoted. |
|
239 */ |
|
240 TPtrC8 RemoveQuotes( const TDesC8& aString ) |
|
241 { |
|
242 return aString.Mid( 1, aString.Length() - KLenDoubleQuotes ); |
|
243 } |
|
244 |
|
245 /** |
|
246 * Parses a primitive data type of a string. |
|
247 * |
|
248 * @param aInputValue[in] input value with primitive type information. |
|
249 * @param aStringValue[out] value without type information. |
|
250 * @param aFloatValue value as float if type is a numerical type. |
|
251 * @param aPrimitiveType[out] primitive type. |
|
252 * @param aUpdateType[out] update type |
|
253 */ |
|
254 void ParseCSSValue( const TDesC8& aInputValue, |
|
255 TPtrC8& aStringValue, |
|
256 TReal& aFloatValue, |
|
257 CXnDomPropertyValue::TPrimitiveValueType& aPrimitiveType, |
|
258 TPropertyUpdateType& aUpdateType ) |
|
259 { |
|
260 aPrimitiveType = CXnDomPropertyValue::EUnknown; |
|
261 aUpdateType = EAbsoluteValue; |
|
262 |
|
263 TPtrC8 unit; |
|
264 |
|
265 // Recognise type |
|
266 |
|
267 if ( EndsWith( aInputValue, AiUiDef::xml::css::KPercentage ) ) |
|
268 { |
|
269 unit.Set( AiUiDef::xml::css::KPercentage ); |
|
270 aPrimitiveType = CXnDomPropertyValue::EPercentage; |
|
271 } |
|
272 else if ( EndsWith( aInputValue, AiUiDef::xml::css::KPixel ) ) |
|
273 { |
|
274 unit.Set( AiUiDef::xml::css::KPixel ); |
|
275 aPrimitiveType = CXnDomPropertyValue::EPx; |
|
276 } |
|
277 else if ( EndsWith( aInputValue, AiUiDef::xml::css::KUnitValue ) ) |
|
278 { |
|
279 unit.Set( AiUiDef::xml::css::KUnitValue ); |
|
280 aPrimitiveType = CXnDomPropertyValue::EUnitValue; |
|
281 } |
|
282 else if ( IsValidCssString( aInputValue ) ) |
|
283 { |
|
284 aPrimitiveType = CXnDomPropertyValue::EString; |
|
285 aStringValue.Set( RemoveQuotes( aInputValue ) ); |
|
286 return; |
|
287 } |
|
288 |
|
289 // Validate type |
|
290 switch ( aPrimitiveType ) |
|
291 { |
|
292 // Supported float types |
|
293 case CXnDomPropertyValue::EPercentage: |
|
294 case CXnDomPropertyValue::EPx: |
|
295 case CXnDomPropertyValue::EUnitValue: // fallthrough |
|
296 { |
|
297 // Remove unit |
|
298 aStringValue.Set( Strip( aInputValue, unit ) ); |
|
299 |
|
300 // Determine update type |
|
301 if ( aStringValue.Find( KIncrementalAdditionOperator ) == 0 ) |
|
302 { |
|
303 aUpdateType = EIncrementalAddition; |
|
304 |
|
305 // Remove sign |
|
306 aStringValue.Set( aStringValue.Mid( KLenIncrementalOperator ) ); |
|
307 } |
|
308 else if ( aStringValue.Find( KAdditionOperator ) == 0 ) |
|
309 { |
|
310 aUpdateType = EAddition; |
|
311 |
|
312 // Remove sign |
|
313 aStringValue.Set( aStringValue.Mid( KLenAddSubOperator ) ); |
|
314 } |
|
315 else if ( aStringValue.Find( KIncrementalSubtractionOperator ) == 0 ) |
|
316 { |
|
317 // Use addition, so only one sign has to be removed |
|
318 aUpdateType = EAddition; |
|
319 |
|
320 aStringValue.Set( aStringValue.Mid( KLenAddSubOperator ) ); |
|
321 } |
|
322 else if ( aStringValue.Find( KSubtractionOperator ) == 0 ) |
|
323 { |
|
324 // Use addition, so sign does not have to be removed |
|
325 aUpdateType = EAddition; |
|
326 } |
|
327 |
|
328 if ( TLex8( aStringValue ).Val( aFloatValue ) != KErrNone ) |
|
329 { |
|
330 // Not a numerical value. Restore value |
|
331 aPrimitiveType = CXnDomPropertyValue::EUnknown; |
|
332 aUpdateType = EAbsoluteValue; |
|
333 aStringValue.Set( aInputValue ); |
|
334 } |
|
335 |
|
336 break; |
|
337 } |
|
338 |
|
339 // string types |
|
340 default: |
|
341 { |
|
342 aStringValue.Set( aInputValue ); |
|
343 break; |
|
344 } |
|
345 |
|
346 } |
|
347 } |
|
348 |
|
349 /** |
|
350 * Updates property value |
|
351 * |
|
352 * @param aValue property value to update. |
|
353 * @param aStringValue new value as string |
|
354 * @param aFloatValue new value as float (for number types) |
|
355 * @param aPrimitiveType type of value |
|
356 * @param aUpdateType type to update the value. |
|
357 */ |
|
358 void UpdatePropertyValueL( CXnDomPropertyValue& aValue, |
|
359 const TDesC8& aStringValue, |
|
360 const TReal& aFloatValue, |
|
361 CXnDomPropertyValue::TPrimitiveValueType aPrimitiveType, |
|
362 TPropertyUpdateType aUpdateType ) |
|
363 { |
|
364 switch ( aPrimitiveType ) |
|
365 { |
|
366 // Supported float types |
|
367 case CXnDomPropertyValue::EPercentage: |
|
368 case CXnDomPropertyValue::EPx: |
|
369 case CXnDomPropertyValue::EUnitValue: // fallthrough |
|
370 { |
|
371 TReal floatValue( aFloatValue ); |
|
372 // Select update type |
|
373 switch ( aUpdateType ) |
|
374 { |
|
375 case EAddition: // fallthrough |
|
376 case EIncrementalAddition: |
|
377 { |
|
378 floatValue += aValue.FloatValueL(); |
|
379 break; |
|
380 } |
|
381 |
|
382 case ESubtraction: // fallthrough |
|
383 case EIncrementalSubtraction: |
|
384 { |
|
385 floatValue = aValue.FloatValueL() - aFloatValue; |
|
386 break; |
|
387 } |
|
388 |
|
389 case EAbsoluteValue: |
|
390 default: |
|
391 { |
|
392 break; |
|
393 } |
|
394 } |
|
395 |
|
396 // Set new value as float |
|
397 aValue.SetFloatValueL( aPrimitiveType, floatValue ); |
|
398 |
|
399 break; |
|
400 } |
|
401 |
|
402 // string types |
|
403 case CXnDomPropertyValue::EUnknown: |
|
404 { |
|
405 // Use current type |
|
406 aPrimitiveType = Max( aValue.PrimitiveValueType(), CXnDomPropertyValue::EUnknown ); |
|
407 |
|
408 // Fall through to update... |
|
409 } |
|
410 |
|
411 default: // fallthrough |
|
412 { |
|
413 if( aPrimitiveType == CXnDomPropertyValue::ENumber ) |
|
414 { |
|
415 TReal floatValue; |
|
416 TLex8( aStringValue ).Val( floatValue ); |
|
417 aValue.SetFloatValueL( aPrimitiveType, floatValue ); |
|
418 } |
|
419 else |
|
420 { |
|
421 // Set new value as string |
|
422 aValue.SetStringValueL( aPrimitiveType, aStringValue ); |
|
423 } |
|
424 break; |
|
425 } |
|
426 } |
|
427 } |
|
428 |
|
429 /** |
|
430 * Creates a new property. |
|
431 * |
|
432 * @param aUiElement ui element to hold the property. |
|
433 * @param aPropertyName name of the property. |
|
434 * @param aPropertyValue value of the property. |
|
435 */ |
|
436 void CreatePropertyL( CXnNodeAppIf& aUiElement, |
|
437 const TDesC8& aPropertyName, |
|
438 const TDesC8& aPropertyValue ) |
|
439 { |
|
440 // Create new property value and property |
|
441 CXnDomPropertyValue* value = CXnDomPropertyValue::NewL( |
|
442 aUiElement.UiEngineL()->StringPool() ); |
|
443 CleanupStack::PushL( value ); |
|
444 |
|
445 CXnProperty* property = CXnProperty::NewL( |
|
446 aPropertyName, |
|
447 value, |
|
448 aUiElement.UiEngineL()->StringPool() ); |
|
449 CleanupStack::Pop( value ); |
|
450 CleanupStack::PushL( property ); |
|
451 |
|
452 // Parse CSS value |
|
453 TPtrC8 stringValue; |
|
454 TReal floatValue( 0 ); |
|
455 CXnDomPropertyValue::TPrimitiveValueType primitiveType( |
|
456 CXnDomPropertyValue::EUnknown ); |
|
457 TPropertyUpdateType updateType( EAbsoluteValue ); |
|
458 |
|
459 ParseCSSValue( aPropertyValue, |
|
460 stringValue, |
|
461 floatValue, |
|
462 primitiveType, |
|
463 updateType ); |
|
464 |
|
465 if ( primitiveType == CXnDomPropertyValue::EUnknown ) |
|
466 { |
|
467 primitiveType = SelectStringDataType( aPropertyName, aPropertyValue ); |
|
468 } |
|
469 |
|
470 // Update CSS value |
|
471 UpdatePropertyValueL( *value, |
|
472 stringValue, |
|
473 floatValue, |
|
474 primitiveType, |
|
475 updateType ); |
|
476 |
|
477 // Add property to UI element |
|
478 aUiElement.SetPropertyL( property ); |
|
479 |
|
480 CleanupStack::Pop( property ); |
|
481 } |
|
482 |
|
483 |
|
484 // Icon utilities |
|
485 |
|
486 _LIT( KSkin, "skin" ); |
|
487 const TUint KLeftParenthesis = '('; |
|
488 |
|
489 /** |
|
490 * Resolves skin item id from pattern SKIN( <majorId> <minorId> (<colourGroupId>) ). |
|
491 * The colourGroupId in the syntax is optional, and if no value found then |
|
492 * aColourValue will be -1 |
|
493 * |
|
494 * @param aItemId skin item id to fill |
|
495 * @param aColourValue colour value to fill. |
|
496 * @param aPath skin item id string |
|
497 * |
|
498 * @return ETrue if id was succesfully parsed. |
|
499 */ |
|
500 TBool ResolveSkinItemId( TAknsItemID& aItemId, TInt& aColourValue, const TDesC& aPath ) |
|
501 { |
|
502 // Syntax: skin( <major> <minor> ) |
|
503 TInt pos = aPath.FindF( KSkin ); |
|
504 aColourValue = -1; |
|
505 if( pos != KErrNotFound ) |
|
506 { |
|
507 // Skip skin token |
|
508 pos += KSkin().Length(); |
|
509 |
|
510 // Initialize lexer |
|
511 TLex lex( aPath.Mid( pos ) ); |
|
512 lex.SkipSpace(); |
|
513 |
|
514 // Check left parenthesis |
|
515 if (lex.Get() != KLeftParenthesis ) |
|
516 { |
|
517 return EFalse; |
|
518 } |
|
519 |
|
520 lex.SkipSpace(); |
|
521 |
|
522 TInt majorId( 0 ); |
|
523 TInt minorId( 0 ); |
|
524 |
|
525 // Resolve major id |
|
526 TInt error = lex.Val( majorId ); |
|
527 |
|
528 // Resolve minor id |
|
529 lex.SkipSpace(); |
|
530 error |= lex.Val( minorId ); |
|
531 |
|
532 // initilize skin item id object |
|
533 aItemId.Set( majorId, minorId ); |
|
534 |
|
535 lex.SkipSpace(); |
|
536 TInt colorError = lex.Val( aColourValue ); |
|
537 if ( colorError != KErrNone || aColourValue < 0) |
|
538 { |
|
539 aColourValue = -1; |
|
540 } |
|
541 |
|
542 // Check error |
|
543 return ( error == KErrNone ); |
|
544 } |
|
545 |
|
546 return EFalse; |
|
547 } |
|
548 |
|
549 /** |
|
550 * Resolves MIF files filename and id from syntax |
|
551 * mif_filename.mif#id. If the syntax is incorrect |
|
552 * aId is -1 and filename zeroed and EFalse is returned |
|
553 * |
|
554 * @param aPath The path to extract the data from |
|
555 * @param aId Id to fill |
|
556 * @param aFilename Filename to fill |
|
557 * @return ETrue if id was succesfully parsed. |
|
558 */ |
|
559 TBool ResolveMifIdAndPathL( const TDesC& aPath, TInt& aId, TDes& aFilename ) |
|
560 { |
|
561 // Syntax: mif_filename.mif#index |
|
562 TInt pos = aPath.FindF( KHashmark ); |
|
563 aFilename.Zero(); |
|
564 if( pos != KErrNotFound ) |
|
565 { |
|
566 aFilename = (aPath.Left(pos)); |
|
567 if ( ! EndsWith( aFilename, KMIFExtension ) ) |
|
568 { |
|
569 aFilename.Zero(); |
|
570 return EFalse; |
|
571 } |
|
572 |
|
573 TLex lex(aPath.Mid(pos+1)); |
|
574 TInt error = lex.Val(aId); |
|
575 if ( error != KErrNone ) |
|
576 { |
|
577 aId = -1; |
|
578 return EFalse; |
|
579 } |
|
580 return ETrue; |
|
581 } |
|
582 return EFalse; |
|
583 |
|
584 |
|
585 |
|
586 } |
|
587 |
|
588 /** |
|
589 * Loads a bitmap icon from a MIF-file loaded to Xuikon by using |
|
590 * <FileResource> tag |
|
591 * |
|
592 * @param aNode Resource node |
|
593 * @param aFilename The filename to load |
|
594 * @param aBitmap The bitmap to fill |
|
595 * @param aBitmapMask The mask to fill |
|
596 * @param aMifId The id of the icon in the MIF-file |
|
597 * |
|
598 * @return KErrNone if loading was successful KErrNotFound if not |
|
599 */ |
|
600 TInt LoadMIFBitmapL( CXnNodeAppIf &aNode, |
|
601 const TDesC &aPath, |
|
602 CFbsBitmap*& aBitmap, |
|
603 CFbsBitmap*& aBitmapMask, |
|
604 TInt aMifId ) |
|
605 { |
|
606 RFile tempFile; |
|
607 |
|
608 if ( aMifId < 0 ) |
|
609 { |
|
610 return KErrNotFound; |
|
611 } |
|
612 |
|
613 TInt err = aNode.UiEngineL()->GetThemeResource( aPath, tempFile ); |
|
614 |
|
615 if ( err != KErrNone ) |
|
616 { |
|
617 tempFile.Close(); |
|
618 return err; |
|
619 } |
|
620 |
|
621 //Requires an open RFile handle |
|
622 TIconProvider *iconProvider = |
|
623 new (ELeave) TIconProvider(tempFile); |
|
624 |
|
625 CleanupStack::PushL( iconProvider ); |
|
626 // Mask is next after bitmap |
|
627 AknIconUtils::CreateIconL(aBitmap,aBitmapMask, *iconProvider, |
|
628 aMifId+KMifIdFirst,aMifId+KMifIdFirst+1); |
|
629 |
|
630 CleanupStack::Pop(iconProvider); // iconProvider |
|
631 |
|
632 return KErrNone; |
|
633 } |
|
634 } |
|
635 |
|
636 namespace AiXmlUiController |
|
637 { |
|
638 |
|
639 RPointerArray< CXnNodeAppIf > |
|
640 FindPropertyElementL( CXnNodeAppIf& aUiElement, const TDesC8& aPropertyClass ) |
|
641 { |
|
642 CXnBreadthFirstTreeIterator< CXnNodeAppIf >* iterator = |
|
643 CXnBreadthFirstTreeIterator< CXnNodeAppIf >::NewL( aUiElement, |
|
644 KDepthT ); |
|
645 CleanupDeletePushL( iterator ); |
|
646 |
|
647 RPointerArray< CXnNodeAppIf > nodes; |
|
648 |
|
649 CleanupClosePushL( nodes ); |
|
650 |
|
651 CXnNodeAppIf* child = iterator->Value() ; |
|
652 |
|
653 while ( child ) |
|
654 { |
|
655 CXnProperty* classProperty = child->GetPropertyL( |
|
656 XnPropertyNames::common::KClass ); |
|
657 |
|
658 if ( classProperty && ( classProperty->StringValue() == aPropertyClass ) ) |
|
659 { |
|
660 User::LeaveIfError( nodes.Append( child ) ); |
|
661 } |
|
662 |
|
663 child = iterator->NextL(); |
|
664 } |
|
665 |
|
666 CleanupStack::Pop( &nodes ); |
|
667 |
|
668 CleanupStack::PopAndDestroy( iterator ); |
|
669 |
|
670 return nodes; |
|
671 } |
|
672 |
|
673 void FindPropertyElementL( RPointerArray< CXnNodeAppIf >& aArray, CXnNodeAppIf& aUiElement, const TDesC8& aPropertyClass ) |
|
674 { |
|
675 CXnBreadthFirstTreeIterator< CXnNodeAppIf >* iterator = |
|
676 CXnBreadthFirstTreeIterator< CXnNodeAppIf >::NewL( aUiElement, |
|
677 KDepthT ); |
|
678 CleanupDeletePushL( iterator ); |
|
679 |
|
680 CXnNodeAppIf* child = iterator->Value(); |
|
681 |
|
682 while ( child ) |
|
683 { |
|
684 CXnProperty* classProperty = child->GetPropertyL( |
|
685 XnPropertyNames::common::KClass ); |
|
686 |
|
687 if ( classProperty && ( classProperty->StringValue() == aPropertyClass ) ) |
|
688 { |
|
689 User::LeaveIfError( aArray.Append( child ) ); |
|
690 } |
|
691 |
|
692 child = iterator->NextL(); |
|
693 } |
|
694 |
|
695 CleanupStack::PopAndDestroy( iterator ); |
|
696 } |
|
697 |
|
698 HBufC* PropertyValueL( const CXnNodeAppIf& aUiElement, |
|
699 const TDesC8& aPropertyName ) |
|
700 { |
|
701 CXnProperty* property = aUiElement.GetPropertyL( aPropertyName ); |
|
702 |
|
703 if ( property ) |
|
704 { |
|
705 return property->StringValueL(); |
|
706 } |
|
707 |
|
708 return NULL; |
|
709 } |
|
710 |
|
711 const TDesC8* PropertyValue( const CXnNodeAppIf& aUiElement, |
|
712 const TDesC8& aPropertyName ) |
|
713 { |
|
714 CXnProperty* property = NULL; |
|
715 TRAP_IGNORE( property = aUiElement.GetPropertyL( aPropertyName ) ); |
|
716 |
|
717 if ( property ) |
|
718 { |
|
719 return &property->StringValue(); |
|
720 } |
|
721 |
|
722 return NULL; |
|
723 } |
|
724 |
|
725 void SetPropertyL( CXnNodeAppIf& aUiElement, |
|
726 const TDesC8& aPropertyName, |
|
727 const TDesC8& aPropertyValue, |
|
728 CCssPropertyMap& aPropertyMap ) |
|
729 { |
|
730 CXnProperty* property = aUiElement.GetPropertyL( aPropertyName ); |
|
731 |
|
732 if ( !property ) |
|
733 { |
|
734 // Create new property |
|
735 CreatePropertyL( aUiElement, aPropertyName, aPropertyValue ); |
|
736 return; |
|
737 } |
|
738 |
|
739 // Clone property for update |
|
740 property = property->CloneL(); |
|
741 CleanupStack::PushL( property ); |
|
742 |
|
743 CXnDomProperty* domProperty = property->Property(); |
|
744 MXnDomListItem* item = domProperty->PropertyValueList().First(); |
|
745 |
|
746 CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( item ); |
|
747 |
|
748 if ( value ) |
|
749 { |
|
750 TPtrC8 stringValue; |
|
751 TReal floatValue(0); |
|
752 |
|
753 CXnDomPropertyValue::TPrimitiveValueType primitiveType( |
|
754 CXnDomPropertyValue::EUnknown ); |
|
755 TPropertyUpdateType updateType( EAbsoluteValue ); |
|
756 |
|
757 ParseCSSValue( aPropertyValue, |
|
758 stringValue, |
|
759 floatValue, |
|
760 primitiveType, |
|
761 updateType ); |
|
762 |
|
763 if ( primitiveType == CXnDomPropertyValue::EUnknown ) |
|
764 { |
|
765 primitiveType = SelectStringDataType( aPropertyName, aPropertyValue ); |
|
766 } |
|
767 |
|
768 if ( updateType != EAbsoluteValue && |
|
769 updateType != EIncrementalAddition && |
|
770 updateType != EIncrementalSubtraction ) |
|
771 { |
|
772 // Use original value from property map |
|
773 const TDesC8* elementId = PropertyValue( aUiElement, |
|
774 XnPropertyNames::common::KId ); |
|
775 CXnDomPropertyValue* original = NULL; |
|
776 if( elementId ) |
|
777 { |
|
778 original = aPropertyMap.FindPropertyValue( |
|
779 *elementId, |
|
780 aPropertyName ); |
|
781 } |
|
782 else |
|
783 { |
|
784 User::Leave( KErrNotSupported ); |
|
785 } |
|
786 |
|
787 if ( original ) |
|
788 { |
|
789 // Clone original value |
|
790 value = original->CloneL(); |
|
791 CleanupStack::PopAndDestroy( property ); // Old clone |
|
792 CleanupStack::PushL( value ); |
|
793 property = CXnProperty::NewL( aPropertyName, |
|
794 value, |
|
795 aUiElement.UiEngineL()->StringPool() ); |
|
796 CleanupStack::Pop( value ); |
|
797 CleanupStack::PushL( property ); |
|
798 } |
|
799 else |
|
800 { |
|
801 // store original value |
|
802 aPropertyMap.StorePropertyValueL( *elementId, *property ); |
|
803 } |
|
804 } |
|
805 |
|
806 UpdatePropertyValueL( *value, |
|
807 stringValue, |
|
808 floatValue, |
|
809 primitiveType, |
|
810 updateType ); |
|
811 |
|
812 aUiElement.SetPropertyL( property ); |
|
813 CleanupStack::Pop( property ); |
|
814 } |
|
815 else |
|
816 { |
|
817 User::Leave( KErrNotSupported ); |
|
818 } |
|
819 } |
|
820 |
|
821 void SetPropertiesToHashMapL( RArray<TAiPolicyElement>& aArray, |
|
822 CCssPropertyMap& aPropertyMap, |
|
823 RPropertyHashMap& aPropertyHashMap ) |
|
824 { |
|
825 TBool propertyAdded = EFalse; |
|
826 if( !aArray.Count() ) |
|
827 { |
|
828 return; |
|
829 } |
|
830 |
|
831 CXnNodeAppIf& uiElement = aArray[0].Target(); |
|
832 RPointerArray<CXnProperty>* propertyArray = NULL; |
|
833 |
|
834 propertyArray = aPropertyHashMap.Find( uiElement ); |
|
835 |
|
836 if( !propertyArray ) |
|
837 { |
|
838 // Create new one. |
|
839 propertyArray = new(ELeave) RPropertyArray; |
|
840 CleanupStack::PushL( propertyArray ); |
|
841 aPropertyHashMap.InsertL( &uiElement, propertyArray ); |
|
842 CleanupStack::Pop( propertyArray ); |
|
843 } |
|
844 |
|
845 for( TInt i = 0; i < aArray.Count(); ++i ) |
|
846 { |
|
847 const TDesC8& propertyName = aArray[i].Name(); |
|
848 const TDesC8& propertyValue = aArray[i].Value(); |
|
849 |
|
850 CXnProperty* property = uiElement.GetPropertyL( propertyName ); |
|
851 |
|
852 if ( !property ) |
|
853 { |
|
854 // Create new property |
|
855 CreatePropertyL( uiElement, propertyName, propertyValue ); |
|
856 propertyAdded = ETrue; |
|
857 continue; |
|
858 } |
|
859 |
|
860 // Clone property for update |
|
861 property = property->CloneL(); |
|
862 CleanupStack::PushL( property ); |
|
863 |
|
864 CXnDomProperty* domProperty = property->Property(); |
|
865 MXnDomListItem* item = domProperty->PropertyValueList().First(); |
|
866 |
|
867 CXnDomPropertyValue* value = static_cast< CXnDomPropertyValue* >( item ); |
|
868 |
|
869 if ( value ) |
|
870 { |
|
871 TPtrC8 stringValue; |
|
872 TReal floatValue(0); |
|
873 |
|
874 CXnDomPropertyValue::TPrimitiveValueType primitiveType( |
|
875 CXnDomPropertyValue::EUnknown ); |
|
876 TPropertyUpdateType updateType( EAbsoluteValue ); |
|
877 |
|
878 ParseCSSValue( propertyValue, |
|
879 stringValue, |
|
880 floatValue, |
|
881 primitiveType, |
|
882 updateType ); |
|
883 |
|
884 if ( primitiveType == CXnDomPropertyValue::EUnknown ) |
|
885 { |
|
886 primitiveType = SelectStringDataType( propertyName, propertyValue ); |
|
887 } |
|
888 |
|
889 if ( updateType != EAbsoluteValue ) |
|
890 { |
|
891 // Use original value from property map |
|
892 const TDesC8* elementId = PropertyValue( uiElement, |
|
893 XnPropertyNames::common::KId ); |
|
894 CXnDomPropertyValue* original = NULL; |
|
895 if( elementId ) |
|
896 { |
|
897 original = aPropertyMap.FindPropertyValue( |
|
898 *elementId, |
|
899 propertyName ); |
|
900 } |
|
901 else |
|
902 { |
|
903 User::Leave( KErrNotSupported ); |
|
904 } |
|
905 |
|
906 if ( original ) |
|
907 { |
|
908 // Clone original value |
|
909 value = original->CloneL(); |
|
910 CleanupStack::PopAndDestroy( property ); // Old clone |
|
911 CleanupStack::PushL( value ); |
|
912 property = CXnProperty::NewL( propertyName, |
|
913 value, |
|
914 uiElement.UiEngineL()->StringPool() ); |
|
915 CleanupStack::Pop( value ); |
|
916 CleanupStack::PushL( property ); |
|
917 } |
|
918 else |
|
919 { |
|
920 // store original value |
|
921 aPropertyMap.StorePropertyValueL( *elementId, *property ); |
|
922 } |
|
923 } |
|
924 |
|
925 UpdatePropertyValueL( *value, |
|
926 stringValue, |
|
927 floatValue, |
|
928 primitiveType, |
|
929 updateType ); |
|
930 propertyArray->AppendL( property ); |
|
931 CleanupStack::Pop( property ); |
|
932 } |
|
933 } |
|
934 |
|
935 if( !propertyAdded && !propertyArray->Count() ) |
|
936 { |
|
937 User::Leave( KErrNotSupported ); |
|
938 } |
|
939 } |
|
940 |
|
941 void SetPropertyArraysL( RPropertyHashMap& aPropertyHashMap ) |
|
942 { |
|
943 TPtrHashMapIter<CXnNodeAppIf, RPropertyArray> iter( aPropertyHashMap ); |
|
944 iter.Reset(); |
|
945 |
|
946 const CXnNodeAppIf* targetNode = (const CXnNodeAppIf*)iter.NextKey(); |
|
947 |
|
948 while( targetNode ) |
|
949 { |
|
950 CXnNodeAppIf* targetNonConst = const_cast<CXnNodeAppIf*>(targetNode); |
|
951 RPointerArray<CXnProperty>* propertyArray = aPropertyHashMap.Find(*targetNode); |
|
952 if( propertyArray ) |
|
953 { |
|
954 targetNonConst->SetPropertyArrayL( propertyArray ); // Assumes ownership |
|
955 // of CXnProperty's in the array |
|
956 // but not the array itself. |
|
957 propertyArray->Close(); // Close and delete the array to free all memory. |
|
958 delete propertyArray; |
|
959 aPropertyHashMap.Remove( targetNode ); // Remove the key from hash map |
|
960 // as the array is now destroyed. |
|
961 iter.Reset(); // Reset the iterator to avoid panic. |
|
962 } |
|
963 targetNode = (CXnNodeAppIf*)iter.NextKey(); |
|
964 } |
|
965 |
|
966 } |
|
967 |
|
968 CGulIcon* LoadIconLC( CXnNodeAppIf& aResource ) |
|
969 { |
|
970 // Resolve icon path |
|
971 HBufC* pathBuffer = PropertyValueL( aResource, XnPropertyNames::image::KPath ); |
|
972 CleanupStack::PushL( pathBuffer ); |
|
973 |
|
974 LeaveIfNull( pathBuffer, KErrNotFound ); |
|
975 |
|
976 CFbsBitmap *bitmap = NULL; |
|
977 CFbsBitmap *mask = NULL; |
|
978 CGulIcon* icon = NULL; |
|
979 |
|
980 TFileName fileName; |
|
981 TInt mifId(0); |
|
982 |
|
983 //Assume that the filetype is not supported |
|
984 TInt err = KErrNotSupported; |
|
985 |
|
986 // Resolve icon id |
|
987 TAknsItemID iconId; |
|
988 |
|
989 // Possible color index |
|
990 TInt colorValue(-1); |
|
991 |
|
992 TBool inSkin = ResolveSkinItemId( iconId, colorValue, *pathBuffer ); |
|
993 |
|
994 // SKIN(<major> <minor> (<optionalColourGroup>)) |
|
995 if ( inSkin ) |
|
996 { |
|
997 // Load from skin |
|
998 MAknsSkinInstance* skin = AknsUtils::SkinInstance(); |
|
999 err = KErrNone; |
|
1000 // Load the icon with colour group support but only if it is valid |
|
1001 // see AknsConstants.h for these |
|
1002 if ( colorValue >= EAknsCIQsnTextColorsCG1 && |
|
1003 colorValue <= EAknsCIQsnTextColorsCG62 ) |
|
1004 { |
|
1005 CFbsBitmap* bitmap = NULL; |
|
1006 CFbsBitmap* mask = NULL; |
|
1007 AknsUtils::CreateColorIconLC( |
|
1008 skin, |
|
1009 iconId, |
|
1010 KAknsIIDQsnTextColors, |
|
1011 colorValue, |
|
1012 bitmap, |
|
1013 mask, |
|
1014 KNullDesC, /* no backup */ |
|
1015 0, /* no backup */ |
|
1016 0, /* no backup */ |
|
1017 KRgbBlack ); |
|
1018 |
|
1019 if ( bitmap ) |
|
1020 { |
|
1021 icon = CGulIcon::NewL( bitmap, mask ); |
|
1022 } |
|
1023 else |
|
1024 { |
|
1025 err = KErrNotFound; |
|
1026 } |
|
1027 CleanupStack::Pop( 2 ); // bitmap, mask |
|
1028 } |
|
1029 // No colour group support |
|
1030 else |
|
1031 { |
|
1032 icon = AknsUtils::CreateGulIconL( skin, iconId, KNullDesC, 0, 0 ); |
|
1033 } |
|
1034 |
|
1035 if ( !icon ) // Syntax correct but icon not found |
|
1036 { |
|
1037 err = KErrNotFound; |
|
1038 } |
|
1039 } |
|
1040 |
|
1041 // MIF-file <filename.mif>#<index_in_mif> |
|
1042 else if ( ResolveMifIdAndPathL( *pathBuffer, mifId, fileName ) ) |
|
1043 { |
|
1044 err = LoadMIFBitmapL( aResource, fileName, bitmap, mask, mifId ); |
|
1045 |
|
1046 if ( err == KErrNone && bitmap ) |
|
1047 { |
|
1048 // Ownership of bitmap and mask transferred to CGulIcon |
|
1049 icon = CGulIcon::NewL( bitmap, mask ); |
|
1050 } |
|
1051 else // Syntax correct but the icon was not found |
|
1052 { |
|
1053 err = KErrNotFound; |
|
1054 } |
|
1055 } |
|
1056 CleanupStack::PopAndDestroy( pathBuffer ); |
|
1057 CleanupStack::PushL( icon ); |
|
1058 |
|
1059 User::LeaveIfError( err ); |
|
1060 return icon; |
|
1061 } |
|
1062 |
|
1063 void SetPropertyToNodeL( |
|
1064 CXnNodeAppIf& aNode, |
|
1065 const TDesC8& aPropertyName, |
|
1066 const TDesC8& aNewValueString ) |
|
1067 { |
|
1068 // Set defined property to defined node. |
|
1069 CXnDomPropertyValue* newValue = CXnDomPropertyValue::NewL(aNode.UiEngineL()->StringPool()); |
|
1070 CleanupStack::PushL(newValue); |
|
1071 newValue->SetStringValueL(CXnDomPropertyValue::EString, aNewValueString); |
|
1072 CXnProperty* prop = CXnProperty::NewL(aPropertyName, newValue, aNode.UiEngineL()->StringPool()); |
|
1073 CleanupStack::PushL(prop); |
|
1074 aNode.SetPropertyL(prop); |
|
1075 CleanupStack::Pop(prop); |
|
1076 CleanupStack::Pop(newValue); |
|
1077 } |
|
1078 |
|
1079 } // namespace AiXmlUiController |