propagate unhandled key( DALI_KEY_SEARCH )
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / text-effects-style.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // FILE HEADER
19 #include <dali-toolkit/internal/text/text-effects-style.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
23 #include <dali-toolkit/internal/text/property-string-parser.h>
24
25 namespace Dali
26 {
27
28 namespace Toolkit
29 {
30
31 namespace Text
32 {
33
34 namespace
35 {
36 const std::string COLOR_KEY( "color" );
37 const std::string OFFSET_KEY( "offset" );
38 const std::string WIDTH_KEY( "width" );
39 const std::string HEIGHT_KEY( "height" );
40 const std::string ENABLE_KEY( "enable" );
41 const std::string TRUE_TOKEN( "true" );
42 const std::string FALSE_TOKEN( "false" );
43 }
44
45 bool ParseShadowProperties( const Property::Map& shadowPropertiesMap,
46                             bool& colorDefined,
47                             Vector4& color,
48                             bool& offsetDefined,
49                             Vector2& offset )
50 {
51   const unsigned int numberOfItems = shadowPropertiesMap.Count();
52
53   // Parses and applies the style.
54   for( unsigned int index = 0u; index < numberOfItems; ++index )
55   {
56     const KeyValuePair& valueGet = shadowPropertiesMap.GetKeyValue( index );
57
58     if( COLOR_KEY == valueGet.first.stringKey )
59     {
60       /// Color key.
61       colorDefined = true;
62
63       const std::string colorStr = valueGet.second.Get<std::string>();
64
65       Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color );
66     }
67     else if( OFFSET_KEY == valueGet.first.stringKey )
68     {
69       /// Offset key.
70       offsetDefined = true;
71
72       const std::string offsetStr = valueGet.second.Get<std::string>();
73
74       StringToVector2( offsetStr.c_str(), offsetStr.size(), offset );
75     }
76   }
77
78   return 0u == numberOfItems;
79 }
80
81 bool ParseUnderlineProperties( const Property::Map& underlinePropertiesMap,
82                                bool& enabled,
83                                bool& colorDefined,
84                                Vector4& color,
85                                bool& heightDefined,
86                                float& height )
87 {
88   const unsigned int numberOfItems = underlinePropertiesMap.Count();
89
90   // Parses and applies the style.
91   for( unsigned int index = 0u; index < numberOfItems; ++index )
92   {
93     const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue( index );
94
95     if( ENABLE_KEY == valueGet.first.stringKey )
96     {
97       /// Enable key.
98       const std::string enableStr = valueGet.second.Get<std::string>();
99       enabled = Text::TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() );
100     }
101     else if( COLOR_KEY == valueGet.first.stringKey )
102     {
103       /// Color key.
104       colorDefined = true;
105
106       const std::string colorStr = valueGet.second.Get<std::string>();
107
108       Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color );
109     }
110     else if( HEIGHT_KEY == valueGet.first.stringKey )
111     {
112       /// Height key.
113       heightDefined = true;
114
115       const std::string heightStr = valueGet.second.Get<std::string>();
116
117       height = StringToFloat( heightStr.c_str() );
118     }
119   }
120
121   return 0u == numberOfItems;
122 }
123
124 bool ParseOutlineProperties( const Property::Map& underlinePropertiesMap,
125                                bool& colorDefined,
126                                Vector4& color,
127                                bool& widthDefined,
128                                float& width )
129 {
130   const unsigned int numberOfItems = underlinePropertiesMap.Count();
131
132   // Parses and applies the style.
133   for( unsigned int index = 0u; index < numberOfItems; ++index )
134   {
135     const KeyValuePair& valueGet = underlinePropertiesMap.GetKeyValue( index );
136
137     if( COLOR_KEY == valueGet.first.stringKey )
138     {
139       /// Color key.
140       colorDefined = true;
141       color = valueGet.second.Get<Vector4>();
142     }
143     else if( WIDTH_KEY == valueGet.first.stringKey )
144     {
145       /// Width key.
146       widthDefined = true;
147       width = valueGet.second.Get<float>();
148     }
149   }
150
151   return 0u == numberOfItems;
152 }
153
154 bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
155 {
156   bool update = false;
157
158   if( controller )
159   {
160     switch( type )
161     {
162       case EffectStyle::DEFAULT:
163       {
164         const Property::Map& propertiesMap = value.Get<Property::Map>();
165
166         bool enabled = false;
167         bool colorDefined = false;
168         Vector4 color;
169         bool heightDefined = false;
170         float height = 0.f;
171
172         bool empty = true;
173
174         if ( propertiesMap.Empty() )
175         {
176           // Map empty so check if a string provided
177           const std::string propertyString = value.Get<std::string>();
178
179           if ( !propertyString.empty() )
180           {
181             Property::Map parsedStringMap;
182             Text::ParsePropertyString( propertyString, parsedStringMap );
183
184             empty = ParseUnderlineProperties( parsedStringMap,
185                                               enabled,
186                                               colorDefined,
187                                               color,
188                                               heightDefined,
189                                               height );
190
191             controller->UnderlineSetByString( !empty);
192           }
193         }
194         else
195         {
196            empty = ParseUnderlineProperties( propertiesMap,
197                                              enabled,
198                                              colorDefined,
199                                              color,
200                                              heightDefined,
201                                              height );
202
203            controller->UnderlineSetByString( false );
204         }
205
206         if( !empty )
207         {
208           if( enabled != controller->IsUnderlineEnabled() )
209           {
210             controller->SetUnderlineEnabled( enabled );
211             update = true;
212           }
213
214           // Sets the default underline values.
215           if( colorDefined && ( controller->GetUnderlineColor() != color ) )
216           {
217             controller->SetUnderlineColor( color );
218             update = true;
219           }
220
221           if( heightDefined && ( fabsf( controller->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) )
222           {
223             controller->SetUnderlineHeight( height );
224             update = true;
225           }
226         }
227         else
228         {
229           // Disable underline.
230           if( controller->IsUnderlineEnabled() )
231           {
232             controller->SetUnderlineEnabled( false );
233             update = true;
234           }
235         }
236         break;
237       }
238       case EffectStyle::INPUT:
239       {
240         const std::string& underlineProperties = value.Get<std::string>();
241
242         controller->SetInputUnderlineProperties( underlineProperties );
243         break;
244       }
245     } // switch
246   } // if( controller )
247
248   return update;
249 }
250
251 void GetUnderlineProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
252 {
253   if( controller )
254   {
255     switch( type )
256     {
257       case EffectStyle::DEFAULT:
258       {
259         const bool enabled = controller->IsUnderlineEnabled();
260         const Vector4& color = controller->GetUnderlineColor();
261         const float height = controller->GetUnderlineHeight();
262
263         if ( controller->IsUnderlineSetByString() )
264         {
265           std::string underlineProperties = "{\"enable\":";
266           const std::string enabledStr = enabled ? "true" : "false";
267           underlineProperties += "\"" + enabledStr + "\",";
268
269           std::string colorStr;
270           Vector4ToColorString( color, colorStr );
271           underlineProperties += "\"color\":\"" + colorStr + "\",";
272
273           std::string heightStr;
274           FloatToString( height, heightStr );
275           underlineProperties += "\"height\":\"" + heightStr + "\"}";
276
277           value = underlineProperties;
278         }
279         else
280         {
281           Property::Map map;
282
283           const std::string enabledStr = enabled ? TRUE_TOKEN : FALSE_TOKEN;
284           map.Insert( ENABLE_KEY, enabledStr );
285
286           std::string colorStr;
287           Vector4ToColorString( color, colorStr );
288           map.Insert( COLOR_KEY, colorStr );
289
290           std::string heightStr;
291           FloatToString( height, heightStr );
292           map.Insert( HEIGHT_KEY, heightStr );
293
294           value = map;
295         }
296
297         break;
298       }
299       case EffectStyle::INPUT:
300       {
301         value = controller->GetInputUnderlineProperties();
302         break;
303       }
304     }
305   }
306 }
307
308 bool SetShadowProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
309 {
310   bool update = false;
311
312   if( controller )
313   {
314     switch( type )
315     {
316       case EffectStyle::DEFAULT:
317       {
318         const Property::Map& propertiesMap = value.Get<Property::Map>();
319
320         bool colorDefined = false;
321         Vector4 color;
322         bool offsetDefined = false;
323         Vector2 offset;
324
325         bool empty = true;
326
327         if ( propertiesMap.Empty() )
328         {
329            // Map empty so check if a string provided
330            const std::string propertyString = value.Get<std::string>();
331
332            Property::Map parsedStringMap;
333            Text::ParsePropertyString( propertyString, parsedStringMap );
334
335            empty = ParseShadowProperties( parsedStringMap,
336                                           colorDefined,
337                                           color,
338                                           offsetDefined,
339                                           offset );
340
341            controller->ShadowSetByString( !empty );
342
343         }
344         else
345         {
346           empty = ParseShadowProperties( propertiesMap,
347                                          colorDefined,
348                                          color,
349                                          offsetDefined,
350                                          offset );
351
352           controller->ShadowSetByString( false );
353         }
354
355         if( !empty )
356         {
357           // Sets the default shadow values.
358           if( colorDefined && ( controller->GetShadowColor() != color ) )
359           {
360             controller->SetShadowColor( color );
361             update = true;
362           }
363
364           if( offsetDefined && ( controller->GetShadowOffset() != offset ) )
365           {
366             controller->SetShadowOffset( offset );
367             update = true;
368           }
369         }
370         else
371         {
372           // Disable shadow.
373           if( Vector2::ZERO != controller->GetShadowOffset() )
374           {
375             controller->SetShadowOffset( Vector2::ZERO );
376           }
377         }
378         break;
379       }
380       case EffectStyle::INPUT:
381       {
382         const std::string& shadowString = value.Get<std::string>();
383
384         controller->SetInputShadowProperties( shadowString );
385         break;
386       }
387     } // switch
388   } // if( controller )
389
390   return update;
391 }
392
393 void GetShadowProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
394 {
395   if( controller )
396   {
397     switch( type )
398     {
399       case EffectStyle::DEFAULT:
400       {
401         const Vector4& color = controller->GetShadowColor();
402         const Vector2& offset = controller->GetShadowOffset();
403
404         if ( controller->IsShadowSetByString() )
405         {
406           std::string shadowProperties = "{";
407
408           std::string colorStr;
409           Vector4ToColorString( color, colorStr );
410           shadowProperties += "\"color\":\"" + colorStr + "\",";
411
412           std::string offsetStr;
413           Vector2ToString( offset, offsetStr );
414           shadowProperties += "\"offset\":\"" + offsetStr + "\"}";
415
416           value = shadowProperties;
417         }
418         else
419         {
420           Property::Map map;
421
422           std::string colorStr;
423           Vector4ToColorString( color, colorStr );
424           map.Insert( COLOR_KEY, colorStr );
425
426           std::string offsetStr;
427           Vector2ToString( offset, offsetStr );
428           map.Insert( OFFSET_KEY, offsetStr );
429
430           value = map;
431         }
432         break;
433       }
434       case EffectStyle::INPUT:
435       {
436         value = controller->GetInputShadowProperties();
437         break;
438       }
439     }
440   }
441 }
442
443 bool SetEmbossProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
444 {
445   bool update = false;
446
447   if( controller )
448   {
449     const std::string properties = value.Get< std::string >();
450
451     switch( type )
452     {
453       case EffectStyle::DEFAULT:
454       {
455         // Stores the default emboss's properties string to be recovered by the GetEmbossProperties() function.
456         controller->SetDefaultEmbossProperties( properties );
457         break;
458       }
459       case EffectStyle::INPUT:
460       {
461         // Stores the input emboss's properties string to be recovered by the GetEmbossProperties() function.
462         controller->SetInputEmbossProperties( properties );
463         break;
464       }
465     }
466   }
467
468   return update;
469 }
470
471 void GetEmbossProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
472 {
473   if( controller )
474   {
475     switch( type )
476     {
477       case EffectStyle::DEFAULT:
478       {
479         value = controller->GetDefaultEmbossProperties();
480         break;
481       }
482       case EffectStyle::INPUT:
483       {
484         value = controller->GetInputEmbossProperties();
485         break;
486       }
487     }
488   }
489 }
490
491 bool SetOutlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type )
492 {
493   bool update = false;
494
495   if( controller )
496   {
497     switch( type )
498     {
499       case EffectStyle::DEFAULT:
500       {
501         const Property::Map& propertiesMap = value.Get<Property::Map>();
502
503         bool colorDefined = false;
504         Vector4 color;
505         bool widthDefined = false;
506         float width = 0.f;
507
508         bool empty = true;
509
510         if ( propertiesMap.Empty() )
511         {
512            // Map empty so check if a string provided
513            // This is purely to maintain backward compatibility, but we don't parse the string to be a property map.
514            const std::string propertyString = value.Get<std::string>();
515
516            // Stores the default outline's properties string to be recovered by the GetOutlineProperties() function.
517            controller->SetDefaultOutlineProperties( propertyString );
518
519            controller->OutlineSetByString( true );
520         }
521         else
522         {
523            empty = ParseOutlineProperties( propertiesMap,
524                                            colorDefined,
525                                            color,
526                                            widthDefined,
527                                            width );
528
529            controller->OutlineSetByString( false );
530         }
531
532         if( !empty )
533         {
534           // Sets the default outline values.
535           if( colorDefined && ( controller->GetOutlineColor() != color ) )
536           {
537             controller->SetOutlineColor( color );
538             update = true;
539           }
540
541           if( widthDefined && ( fabsf( controller->GetOutlineWidth() - width ) > Math::MACHINE_EPSILON_1000 ) )
542           {
543             controller->SetOutlineWidth( width );
544             update = true;
545           }
546         }
547         else
548         {
549           // Disable outline
550           if( fabsf( controller->GetOutlineWidth() ) > Math::MACHINE_EPSILON_1000 )
551           {
552             controller->SetOutlineWidth( 0.0f );
553             update = true;
554           }
555         }
556         break;
557       }
558       case EffectStyle::INPUT:
559       {
560         const std::string& outlineProperties = value.Get<std::string>();
561
562         controller->SetInputOutlineProperties( outlineProperties );
563         break;
564       }
565     } // switch
566   } // if( controller )
567
568   return update;
569 }
570
571 void GetOutlineProperties( ControllerPtr controller, Property::Value& value, EffectStyle::Type type )
572 {
573   if( controller )
574   {
575     switch( type )
576     {
577       case EffectStyle::DEFAULT:
578       {
579         if ( controller->IsOutlineSetByString() )
580         {
581           value = controller->GetDefaultOutlineProperties();
582           break;
583         }
584         else
585         {
586           const Vector4& color = controller->GetOutlineColor();
587           const float width = controller->GetOutlineWidth();
588
589           Property::Map map;
590
591           std::string colorStr;
592           Vector4ToColorString( color, colorStr );
593           map.Insert( COLOR_KEY, colorStr );
594
595           std::string widthStr;
596           FloatToString( width, widthStr );
597           map.Insert( WIDTH_KEY, widthStr );
598
599           value = map;
600
601           break;
602         }
603       }
604       case EffectStyle::INPUT:
605       {
606         value = controller->GetInputOutlineProperties();
607         break;
608       }
609     }
610   }
611 }
612
613 } // namespace Text
614
615 } // namespace Toolkit
616
617 } // namespace Dali