2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/actors/image-actor-impl.h>
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>
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;
44 return Dali::ImageActor::New();
47 TypeRegistration mType( typeid(Dali::ImageActor), typeid(Dali::RenderableActor), Create );
49 const Internal::PropertyDetails DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[] =
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
57 const int DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT = sizeof( DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS ) / sizeof( DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[0] );
59 ImageActor::Style StyleEnum(const std::string &s)
61 if(s == "STYLE_NINE_PATCH")
63 return Dali::ImageActor::STYLE_NINE_PATCH;
65 else if(s == "STYLE_NINE_PATCH_NO_CENTER")
67 return Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER;
69 else // if(s == "QUAD")
71 return Dali::ImageActor::STYLE_QUAD;
75 std::string StyleString(const ImageActor::Style style)
77 if(style == Dali::ImageActor::STYLE_NINE_PATCH)
79 return "STYLE_NINE_PATCH";
81 else if(style == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER)
83 return "STYLE_NINE_PATCH_NO_CENTER";
85 else // if(s == "QUAD")
92 ImageActorPtr ImageActor::New()
94 ImageActorPtr actor( new ImageActor );
96 // Second-phase construction of base class
99 // Create the attachment
100 actor->mImageAttachment = ImageAttachment::New( *actor->mStage, *actor->mNode );
101 actor->Attach( *actor->mImageAttachment );
106 void ImageActor::OnInitialize()
110 void ImageActor::SetImage( ImagePtr& image )
112 ImagePtr currentImage = mImageAttachment->GetImage();
113 // early exit if it's the same image as we already have
114 if ( currentImage == image )
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
124 // Automatically convert nine-patch images to cropped bitmap
125 NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() );
128 newImage = ninePatchImage->CreateCroppedBufferImage();
129 SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
130 SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true );
133 // set the actual image (normal or 9 patch) and natural size based on that
134 mImageAttachment->SetImage( newImage );
138 ImagePtr ImageActor::GetImage()
140 return mImageAttachment->GetImage();
143 void ImageActor::SetToNaturalSize()
145 mUsingNaturalSize = true;
150 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
152 mImageAttachment->SetPixelArea( pixelArea );
157 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
159 return mImageAttachment->GetPixelArea();
162 bool ImageActor::IsPixelAreaSet() const
164 return mImageAttachment->IsPixelAreaSet();
167 void ImageActor::ClearPixelArea()
169 mImageAttachment->ClearPixelArea();
171 if( mUsingNaturalSize )
173 ImagePtr image = mImageAttachment->GetImage();
176 mInternalSetSize = true;
177 SetSize( image->GetNaturalSize() );
178 mInternalSetSize = false;
183 void ImageActor::SetStyle( Style style )
185 mImageAttachment->SetStyle( style );
188 ImageActor::Style ImageActor::GetStyle() const
190 return mImageAttachment->GetStyle();
193 void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels )
195 mImageAttachment->SetNinePatchBorder( border, inPixels );
198 Vector4 ImageActor::GetNinePatchBorder() const
200 return mImageAttachment->GetNinePatchBorder();
203 ImageAttachment& ImageActor::GetImageAttachment()
205 return *mImageAttachment;
208 RenderableAttachment& ImageActor::GetRenderableAttachment() const
210 DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" );
211 return *mImageAttachment;
214 ImageActor::ImageActor()
216 mUsingNaturalSize(true),
217 mInternalSetSize(false)
221 ImageActor::~ImageActor()
225 void ImageActor::SetNaturalSize()
227 if( mUsingNaturalSize )
229 mInternalSetSize = true;
230 SetSize( CalculateNaturalSize() );
231 mInternalSetSize = false;
235 Vector3 ImageActor::GetNaturalSize() const
237 Vector2 naturalSize( CalculateNaturalSize() );
238 return Vector3( naturalSize.width, naturalSize.height, CalculateSizeZ( naturalSize ) );
241 Vector2 ImageActor::CalculateNaturalSize() const
243 // if no image then natural size is 0
244 Vector2 size( 0.0f, 0.0f );
246 ImagePtr image = mImageAttachment->GetImage();
249 if( IsPixelAreaSet() )
251 PixelArea area(GetPixelArea());
252 size.width = area.width;
253 size.height = area.height;
257 size = image->GetNaturalSize();
264 void ImageActor::OnSizeSet( const Vector3& targetSize )
266 if( !mInternalSetSize )
268 mUsingNaturalSize = false;
272 void ImageActor::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
274 mUsingNaturalSize = false;
277 void ImageActor::OnStageConnectionInternal()
281 void ImageActor::OnStageDisconnectionInternal()
285 unsigned int ImageActor::GetDefaultPropertyCount() const
287 return RenderableActor::GetDefaultPropertyCount() + DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT;
290 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
292 RenderableActor::GetDefaultPropertyIndices( indices ); // RenderableActor class properties
294 indices.reserve( indices.size() + DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT );
296 int index = DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
297 for ( int i = 0; i < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT; ++i, ++index )
299 indices.push_back( index );
303 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
305 if( index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT )
307 return RenderableActor::IsDefaultPropertyWritable(index);
311 index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
312 if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
314 return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[ index ].writable;
320 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
322 if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
324 return RenderableActor::IsDefaultPropertyAnimatable(index);
328 index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
329 if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
331 return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[ index ].animatable;
337 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
339 if( index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT )
341 return RenderableActor::IsDefaultPropertyAConstraintInput(index);
345 index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
346 if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
348 return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[ index ].constraintInput;
354 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
356 if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
358 return RenderableActor::GetDefaultPropertyType(index);
362 index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
364 if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
366 return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[index].type;
370 // index out-of-bounds
371 return Property::NONE;
376 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
378 if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
380 return RenderableActor::GetDefaultPropertyName(index);
384 index -= DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
386 if ( ( index >= 0 ) && ( index < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT ) )
388 return DEFAULT_IMAGE_ACTOR_PROPERTY_DETAILS[index].name;
392 // index out-of-bounds
398 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
400 Property::Index index = Property::INVALID_INDEX;
402 // Look for name in default properties
403 for( int i = 0; i < DEFAULT_IMAGE_ACTOR_PROPERTY_COUNT; ++i )
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
408 index = i + DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT;
413 // If not found, check in base class
414 if( Property::INVALID_INDEX == index )
416 index = RenderableActor::GetDefaultPropertyIndex( name );
421 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
423 if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
425 RenderableActor::SetDefaultProperty(index, propertyValue);
431 case Dali::ImageActor::PIXEL_AREA:
433 SetPixelArea(propertyValue.Get<Rect<int> >());
436 case Dali::ImageActor::STYLE:
438 SetStyle(StyleEnum(propertyValue.Get<std::string>()));
441 case Dali::ImageActor::BORDER:
443 SetNinePatchBorder( propertyValue.Get<Vector4>(), true /*in pixels*/ );
446 case Dali::ImageActor::IMAGE:
448 Dali::Image img = Scripting::NewImage( propertyValue );
451 ImagePtr image( &GetImplementation(img) );
456 DALI_LOG_WARNING("Cannot create image from property value\n");
462 DALI_LOG_WARNING("Unknown property (%d)\n", index);
470 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
473 if(index < DEFAULT_RENDERABLE_ACTOR_PROPERTY_MAX_COUNT)
475 ret = RenderableActor::GetDefaultProperty(index);
481 case Dali::ImageActor::PIXEL_AREA:
483 Rect<int> r = GetPixelArea();
487 case Dali::ImageActor::STYLE:
489 ret = StyleString(GetStyle());
492 case Dali::ImageActor::BORDER:
494 ret = GetNinePatchBorder();
497 case Dali::ImageActor::IMAGE:
500 Scripting::CreatePropertyMap( Dali::Image( mImageAttachment->GetImage().Get() ), map );
501 ret = Property::Value( map );
506 DALI_LOG_WARNING("Unknown property (%d)\n", index);
515 } // namespace Internal