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