Merge "Change keep running reasons to enum from exported symbols to avoid external...
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / image-actor-impl.cpp
1 /*
2  * Copyright (c) 2014 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 // CLASS HEADER
19 #include <dali/internal/event/actors/image-actor-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/internal/event/images/nine-patch-image-impl.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/internal/event/common/property-index-ranges.h>
25 #include <dali/internal/event/images/image-connector.h>
26 #include <dali/public-api/scripting/scripting.h>
27
28 namespace Dali
29 {
30
31 const Property::Index ImageActor::PIXEL_AREA           = Internal::DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
32 const Property::Index ImageActor::STYLE                = Internal::DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT + 1;
33 const Property::Index ImageActor::BORDER               = Internal::DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT + 2;
34 const Property::Index ImageActor::IMAGE                = Internal::DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT + 3;
35
36 namespace Internal
37 {
38
39 namespace
40 {
41
42 BaseHandle Create()
43 {
44   return Dali::ImageActor::New();
45 }
46
47 TypeRegistration mType( typeid(Dali::ImageActor), typeid(Dali::RenderableActor), Create );
48
49 const Internal::PropertyDetails DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[] =
50 {
51   // Name            Type              writable animatable constraint-input
52   { "pixel-area",   Property::RECTANGLE, true,    false,   true },  // PIXEL_AREA
53   { "style",        Property::STRING,    true,    false,   true },  // STYLE
54   { "border",       Property::VECTOR4,   true,    false,   true },  // BORDER
55   { "image",        Property::MAP,       true,    false,   false }, // IMAGE
56 };
57 const int DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT = sizeof( DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS ) / sizeof( DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[0] );
58
59 ImageActor::Style StyleEnum(const std::string &s)
60 {
61   if(s == "STYLE_NINE_PATCH")
62   {
63     return Dali::ImageActor::STYLE_NINE_PATCH;
64   }
65   else if(s == "STYLE_NINE_PATCH_NO_CENTER")
66   {
67     return Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER;
68   }
69   else // if(s == "QUAD")
70   {
71     return Dali::ImageActor::STYLE_QUAD;
72   }
73 }
74
75 std::string StyleString(const ImageActor::Style style)
76 {
77   if(style == Dali::ImageActor::STYLE_NINE_PATCH)
78   {
79     return "STYLE_NINE_PATCH";
80   }
81   else if(style == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER)
82   {
83     return "STYLE_NINE_PATCH_NO_CENTER";
84   }
85   else // if(s == "QUAD")
86   {
87     return "STYLE_QUAD";
88   }
89 }
90 }
91
92 ImageActorPtr ImageActor::New()
93 {
94   ImageActorPtr actor( new ImageActor );
95
96   // Second-phase construction of base class
97   actor->Initialize();
98
99   // Create the attachment
100   actor->mImageAttachment = ImageAttachment::New( *actor->mNode );
101   actor->Attach( *actor->mImageAttachment );
102
103   return actor;
104 }
105
106 void ImageActor::OnInitialize()
107 {
108 }
109
110 void ImageActor::SetImage( ImagePtr& image )
111 {
112   ImagePtr currentImage = mImageAttachment->GetImage();
113   // early exit if it's the same image as we already have
114   if ( currentImage == image )
115   {
116     return;
117   }
118
119   // NOTE! image might be pointing to NULL, which is fine as in that case app wants to just remove the image
120   ImagePtr newImage( image );
121   // if image is not NULL, check for 9 patch
122   if( newImage )
123   {
124     // Automatically convert nine-patch images to cropped bitmap
125     NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() );
126     if( ninePatchImage )
127     {
128       newImage = ninePatchImage->CreateCroppedBitmapImage();
129       SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
130       SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true );
131     }
132   }
133   // set the actual image (normal or 9 patch) and natural size based on that
134   mImageAttachment->SetImage( newImage );
135   SetNaturalSize();
136 }
137
138 ImagePtr ImageActor::GetImage()
139 {
140   return mImageAttachment->GetImage();
141 }
142
143 void ImageActor::SetToNaturalSize()
144 {
145   mUsingNaturalSize = true;
146
147   SetNaturalSize();
148 }
149
150 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
151 {
152   mImageAttachment->SetPixelArea( pixelArea );
153
154   SetNaturalSize();
155 }
156
157 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
158 {
159   return mImageAttachment->GetPixelArea();
160 }
161
162 bool ImageActor::IsPixelAreaSet() const
163 {
164   return mImageAttachment->IsPixelAreaSet();
165 }
166
167 void ImageActor::ClearPixelArea()
168 {
169   mImageAttachment->ClearPixelArea();
170
171   if( mUsingNaturalSize )
172   {
173     ImagePtr image = mImageAttachment->GetImage();
174     if( image )
175     {
176       mInternalSetSize = true;
177       SetSize( image->GetNaturalSize() );
178       mInternalSetSize = false;
179     }
180   }
181 }
182
183 void ImageActor::SetStyle( Style style )
184 {
185   mImageAttachment->SetStyle( style );
186 }
187
188 ImageActor::Style ImageActor::GetStyle() const
189 {
190   return mImageAttachment->GetStyle();
191 }
192
193 void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels )
194 {
195   mImageAttachment->SetNinePatchBorder( border, inPixels );
196 }
197
198 Vector4 ImageActor::GetNinePatchBorder() const
199 {
200   return mImageAttachment->GetNinePatchBorder();
201 }
202
203 ImageAttachment& ImageActor::GetImageAttachment()
204 {
205   return *mImageAttachment;
206 }
207
208 RenderableAttachment& ImageActor::GetRenderableAttachment() const
209 {
210   DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" );
211   return *mImageAttachment;
212 }
213
214 ImageActor::ImageActor()
215 : RenderableActor(),
216   mUsingNaturalSize(true),
217   mInternalSetSize(false)
218 {
219 }
220
221 ImageActor::~ImageActor()
222 {
223 }
224
225 void ImageActor::SetNaturalSize()
226 {
227   if( mUsingNaturalSize )
228   {
229     mInternalSetSize = true;
230     SetSize( CalculateNaturalSize() );
231     mInternalSetSize = false;
232   }
233 }
234
235 Vector3 ImageActor::GetNaturalSize() const
236 {
237   Vector2 naturalSize( CalculateNaturalSize() );
238   return Vector3( naturalSize.width, naturalSize.height, CalculateSizeZ( naturalSize ) );
239 }
240
241 Vector2 ImageActor::CalculateNaturalSize() const
242 {
243   // if no image then natural size is 0
244   Vector2 size( 0.0f, 0.0f );
245
246   ImagePtr image = mImageAttachment->GetImage();
247   if( image )
248   {
249     if( IsPixelAreaSet() )
250     {
251       PixelArea area(GetPixelArea());
252       size.width = area.width;
253       size.height = area.height;
254     }
255     else
256     {
257       size = image->GetNaturalSize();
258     }
259   }
260
261   return size;
262 }
263
264 void ImageActor::OnSizeSet( const Vector3& targetSize )
265 {
266   if( !mInternalSetSize )
267   {
268     mUsingNaturalSize = false;
269   }
270 }
271
272 void ImageActor::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
273 {
274   mUsingNaturalSize = false;
275 }
276
277 void ImageActor::OnStageConnectionInternal()
278 {
279 }
280
281 void ImageActor::OnStageDisconnectionInternal()
282 {
283 }
284
285 unsigned int ImageActor::GetDefaultPropertyCount() const
286 {
287   return RenderableActor::GetDefaultPropertyCount() + DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT;
288 }
289
290 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
291 {
292   RenderableActor::GetDefaultPropertyIndices( indices ); // RenderableActor class properties
293
294   indices.reserve( indices.size() + DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT );
295
296   int index = DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
297   for ( int i = 0; i < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT; ++i, ++index )
298   {
299     indices.push_back( index );
300   }
301 }
302
303 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
304 {
305   if( index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT )
306   {
307     return RenderableActor::IsDefaultPropertyWritable(index);
308   }
309   else
310   {
311     index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
312     if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
313     {
314       return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[ index ].writable;
315     }
316   }
317   return false;
318 }
319
320 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
321 {
322   if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
323   {
324     return RenderableActor::IsDefaultPropertyAnimatable(index);
325   }
326   else
327   {
328     index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
329     if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
330     {
331       return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[ index ].animatable;
332     }
333   }
334   return false;
335 }
336
337 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
338 {
339   if( index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT )
340   {
341     return RenderableActor::IsDefaultPropertyAConstraintInput(index);
342   }
343   else
344   {
345     index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
346     if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
347     {
348       return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[ index ].constraintInput;
349     }
350   }
351   return false;
352 }
353
354 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
355 {
356   if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
357   {
358     return RenderableActor::GetDefaultPropertyType(index);
359   }
360   else
361   {
362     index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
363
364     if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
365     {
366       return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[index].type;
367     }
368     else
369     {
370       // index out-of-bounds
371       return Property::NONE;
372     }
373   }
374 }
375
376 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
377 {
378   if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
379   {
380     return RenderableActor::GetDefaultPropertyName(index);
381   }
382   else
383   {
384     index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
385
386     if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
387     {
388       return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[index].name;
389     }
390     else
391     {
392       // index out-of-bounds
393       return NULL;
394     }
395   }
396 }
397
398 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
399 {
400   Property::Index index = Property::INVALID_INDEX;
401
402   // Look for name in default properties
403   for( int i = 0; i < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT; ++i )
404   {
405     const Internal::PropertyDetails* property = &DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[ i ];
406     if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
407     {
408       index = i + DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
409       break;
410     }
411   }
412
413   // If not found, check in base class
414   if( Property::INVALID_INDEX == index )
415   {
416     index = RenderableActor::GetDefaultPropertyIndex( name );
417   }
418   return index;
419 }
420
421 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
422 {
423   if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
424   {
425     RenderableActor::SetDefaultProperty(index, propertyValue);
426   }
427   else
428   {
429     switch(index)
430     {
431       case Dali::ImageActor::PIXEL_AREA:
432       {
433         SetPixelArea(propertyValue.Get<Rect<int> >());
434         break;
435       }
436       case Dali::ImageActor::STYLE:
437       {
438         SetStyle(StyleEnum(propertyValue.Get<std::string>()));
439         break;
440       }
441       case Dali::ImageActor::BORDER:
442       {
443         SetNinePatchBorder( propertyValue.Get<Vector4>(), true /*in pixels*/ );
444         break;
445       }
446       case Dali::ImageActor::IMAGE:
447       {
448         Dali::Image img = Scripting::NewImage( propertyValue );
449         if(img)
450         {
451           ImagePtr image( &GetImplementation(img) );
452           SetImage( image );
453         }
454         else
455         {
456           DALI_LOG_WARNING("Cannot create image from property value\n");
457         }
458         break;
459       }
460       default:
461       {
462         DALI_LOG_WARNING("Unknown property (%d)\n", index);
463         break;
464       }
465     } // switch(index)
466
467   } // else
468 }
469
470 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
471 {
472   Property::Value ret;
473   if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
474   {
475     ret = RenderableActor::GetDefaultProperty(index);
476   }
477   else
478   {
479     switch(index)
480     {
481       case Dali::ImageActor::PIXEL_AREA:
482       {
483         Rect<int> r = GetPixelArea();
484         ret = r;
485         break;
486       }
487       case Dali::ImageActor::STYLE:
488       {
489         ret = StyleString(GetStyle());
490         break;
491       }
492       case Dali::ImageActor::BORDER:
493       {
494         ret = GetNinePatchBorder();
495         break;
496       }
497       case Dali::ImageActor::IMAGE:
498       {
499         Property::Map map;
500         Scripting::CreatePropertyMap( Dali::Image( mImageAttachment->GetImage().Get() ), map );
501         ret = Property::Value( map );
502         break;
503       }
504       default:
505       {
506         DALI_LOG_WARNING("Unknown property (%d)\n", index);
507         break;
508       }
509     } // switch(index)
510   }
511
512   return ret;
513 }
514
515 } // namespace Internal
516
517 } // namespace Dali