static Dali::SingletonService New();
static Dali::SingletonService Get();
void Register( const std::type_info& info, BaseHandle singleton );
+ void UnregisterAll();
BaseHandle GetSingleton( const std::type_info& info ) const;
private:
}
}
+void SingletonService::UnregisterAll()
+{
+ mSingletonContainer.clear();
+}
+
BaseHandle SingletonService::GetSingleton( const std::type_info& info ) const
{
BaseHandle object;
{
}
+SingletonService SingletonService::New()
+{
+ return Internal::Adaptor::SingletonService::New();
+}
+
SingletonService SingletonService::Get()
{
return Internal::Adaptor::SingletonService::Get();
GetImplementation( *this ).Register( info, singleton );
}
+void SingletonService::UnregisterAll()
+{
+ GetImplementation( *this ).UnregisterAll();
+}
+
BaseHandle SingletonService::GetSingleton( const std::type_info& info ) const
{
return GetImplementation( *this ).GetSingleton( info );
{
public:
SingletonService();
+ static Dali::SingletonService New();
static SingletonService Get();
~SingletonService();
void Register( const std::type_info& info, BaseHandle singleton );
+ void UnregisterAll();
BaseHandle GetSingleton( const std::type_info& info ) const;
public: // Not intended for application developers
Control dummy = Control::New();
Toolkit::Internal::Control& controlImpl = Toolkit::Internal::GetImplementation( dummy );
- // test that style manager is being used, passing an empty handle throws exception
- try
- {
- Dali::Toolkit::StyleManager styleManager;
- controlImpl.OnStyleChange( styleManager, StyleChange::THEME_CHANGE );
- tet_result(TET_FAIL);
- }
- catch (DaliException &exception)
- {
- tet_result(TET_PASS);
- }
+ // test that style manager is being used, passing an empty handle does nothing but does not crash either
+ Dali::Toolkit::StyleManager styleManager;
+ controlImpl.OnStyleChange( styleManager, StyleChange::THEME_CHANGE );
+ // no crash so test passes
+ tet_result(TET_PASS);
END_TEST;
}
// Test "rows" property
DALI_TEST_CHECK( tableView.GetPropertyIndex( PROPERTY_NAME_ROWS ) == TableView::Property::ROWS );
- tableView.SetProperty( TableView::Property::ROWS, 4u );
+ tableView.SetProperty( TableView::Property::ROWS, 4 );
DALI_TEST_CHECK( tableView.GetRows() == 4u );
- DALI_TEST_CHECK( tableView.GetProperty(TableView::Property::ROWS).Get<unsigned int>() == 4u );
+ DALI_TEST_CHECK( tableView.GetProperty(TableView::Property::ROWS).Get<int>() == 4 );
// Test "columns" property
DALI_TEST_CHECK( tableView.GetPropertyIndex( PROPERTY_NAME_COLUMNS ) == TableView::Property::COLUMNS );
- tableView.SetProperty( TableView::Property::COLUMNS, 5u );
+ tableView.SetProperty( TableView::Property::COLUMNS, 5 );
DALI_TEST_CHECK( tableView.GetColumns() == 5u );
- DALI_TEST_CHECK( tableView.GetProperty(TableView::Property::COLUMNS).Get<unsigned int>() == 5u );
+ DALI_TEST_CHECK( tableView.GetProperty(TableView::Property::COLUMNS).Get<int>() == 5 );
// Test "cell-padding" property
DALI_TEST_CHECK( tableView.GetPropertyIndex( PROPERTY_NAME_CELL_PADDING ) == TableView::Property::CELL_PADDING );
const char* const PROPERTY_NAME_DECORATION_BOUNDING_BOX = "decoration-bounding-box";
const char* const PROPERTY_NAME_INPUT_METHOD_SETTINGS = "input-method-settings";
-const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
+const int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
const Vector4 PLACEHOLDER_TEXT_COLOR( 0.8f, 0.8f, 0.8f, 0.8f );
-const Dali::Vector4 LIGHT_BLUE( (0xb2 / 255.0f), (0xeb / 255.0f), (0xf2 / 255.0f), 0.5f ); // The text highlight color.
+const Dali::Vector4 LIGHT_BLUE( 0.75f, 0.96f, 1.f, 1.f ); // The text highlight color.
const unsigned int CURSOR_BLINK_INTERVAL = 500u; // Cursor blink interval
const float TO_MILLISECONDS = 1000.f;
DALI_TEST_CHECK( field );
// Check defaults.
- DALI_TEST_EQUALS( field.GetProperty<unsigned int>( TextField::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<int>( TextField::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string(""), TEST_LOCATION );
DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::PLACEHOLDER_TEXT ), std::string(""), TEST_LOCATION );
DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::PLACEHOLDER_TEXT_FOCUSED ), std::string(""), TEST_LOCATION );
// Check the render backend property.
field.SetProperty( TextField::Property::RENDERING_BACKEND, Text::RENDERING_SHARED_ATLAS );
- DALI_TEST_EQUALS( field.GetProperty<unsigned int>( TextField::Property::RENDERING_BACKEND ), Text::RENDERING_SHARED_ATLAS, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<int>( TextField::Property::RENDERING_BACKEND ), Text::RENDERING_SHARED_ATLAS, TEST_LOCATION );
// Check text property.
field.SetProperty( TextField::Property::TEXT, "Setting Text" );
const char* const PROPERTY_NAME_UNDERLINE_COLOR = "underline-color";
const char* const PROPERTY_NAME_UNDERLINE_HEIGHT = "underline-height";
-const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
+const int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
} // namespace
DALI_TEST_CHECK( label );
// Check defaults
- DALI_TEST_EQUALS( label.GetProperty<unsigned int>( TextLabel::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<int>( TextLabel::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), std::string(""), TEST_LOCATION );
DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_FAMILY ), std::string(""), TEST_LOCATION );
DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_STYLE ), std::string(""), TEST_LOCATION );
DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 0.0f, TEST_LOCATION );
label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Text::RENDERING_SHARED_ATLAS );
- DALI_TEST_EQUALS( label.GetProperty<unsigned int>( TextLabel::Property::RENDERING_BACKEND ), Text::RENDERING_SHARED_ATLAS, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<int>( TextLabel::Property::RENDERING_BACKEND ), Text::RENDERING_SHARED_ATLAS, TEST_LOCATION );
// Check that text can be correctly reset
label.SetProperty( TextLabel::Property::TEXT, "Setting Text" );
# Tizen Profile options
AC_ARG_ENABLE([profile],
- [AC_HELP_STRING([--enable-profile=COMMON,MOBILE,WEARABLE,TV],
+ [AC_HELP_STRING([--enable-profile=UBUNTU,MOBILE,WEARABLE,TV],
[Select the variant of tizen])],
[dali_profile=$enableval],
- [dali_profile=COMMON])
+ [dali_profile=UBUNTU])
+
+# Ensure valid profile selected
+if test "x$dali_profile" != "xUBUNTU" -a "x$dali_profile" != "xMOBILE" -a "x$dali_profile" != "xWEARABLE" -a "x$dali_profile" != "xTV" ; then
+ AC_MSG_ERROR([$enable_profile is an invalid profile])
+fi
if test x$DALI_DATA_RW_DIR != x; then
dataReadWriteDir=${DALI_DATA_RW_DIR}/
dataReadOnlyDir=${prefix}/share/dali/
fi
-DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -DDALI_PROFILE_${enable_profile}"
-AM_CONDITIONAL([COMMON_PROFILE], [test x$enable_profile = xCOMMON])
-AM_CONDITIONAL([MOBILE_PROFILE], [test x$enable_profile = xMOBILE])
+DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -DDALI_PROFILE_${dali_profile}"
+
+# Style paths
+if test "x$dali_profile" = "xUBUNTU"; then
+ STYLE_DIR=../../../dali-toolkit/styles
+fi
+
+if test "x$dali_profile" = "xMOBILE"; then
+ STYLE_DIR=../../../dali-toolkit/styles/mobile
+fi
+
+AC_SUBST(STYLE_DIR)
# v8 version 4+ requires c++11
PKG_CHECK_MODULES(V8, v8 = 3.32.7, [ pkg_check_v8=yes ], [ pkg_check_v8=no ] )
public_api_src_dir = ../../../dali-toolkit/public-api
devel_api_src_dir = ../../../dali-toolkit/devel-api
-if MOBILE_PROFILE
-toolkit_styles_dir = ../../../dali-toolkit/styles/mobile
-else
-toolkit_styles_dir = ../../../dali-toolkit/styles
-endif
+toolkit_styles_dir = $(STYLE_DIR)
include ../../../dali-toolkit/images/file.list
include ../../../dali-toolkit/sounds/file.list
return Control::DownCast<TextSelectionPopup, Internal::TextSelectionPopup>(handle);
}
+void TextSelectionPopup::RaiseAbove( Layer target )
+{
+ GetImpl(*this).RaiseAbove( target );
+}
+
TextSelectionPopup::TextSelectionPopup( Internal::TextSelectionPopup& implementation )
: Control(implementation)
{
*/
static TextSelectionPopup DownCast( BaseHandle handle );
+ /**
+ * @brief Raises the toolbar's layer above the given @e target layer.
+ *
+ * @param[in] target The layer to get above of.
+ */
+ void RaiseAbove( Layer target );
+
public: // Not intended for application developers
/**
GetImpl(*this).ResizeDividers( size );
}
+void TextSelectionToolbar::RaiseAbove( Layer target )
+{
+ GetImpl(*this).RaiseAbove( target );
+}
+
TextSelectionToolbar TextSelectionToolbar::DownCast( BaseHandle handle )
{
return Control::DownCast<TextSelectionToolbar, Internal::TextSelectionToolbar>(handle);
void ResizeDividers( Size& size );
/**
+ * @brief Raises the layer above the given @e target layer.
+ *
+ * @param[in] target The layer to get above of.
+ */
+ void RaiseAbove( Layer target );
+
+ /**
* @brief Downcast a handle to TextSelectionToolbar.
*
* If the BaseHandle points is a TextSelectionToolbar the downcast returns a valid handle.
}
Dali::Atlas atlas = Dali::Atlas::New( width, height, pixelformat );
+ atlas.Clear( Vector4::ZERO );
+ mUploadedImages.PushBack( NULL );
AtlasDescriptor atlasDescriptor;
atlasDescriptor.mAtlas = atlas;
atlasDescriptor.mSize = size;
atlasDescriptor.mPixelFormat = pixelformat;
- atlasDescriptor.mNextFreeBlock = 1u; // indicate next free block will be the first ( +1 )
+ atlasDescriptor.mTotalBlocks = ( width / blockWidth ) * ( height / blockHeight );
+ atlasDescriptor.mAvailableBlocks = atlasDescriptor.mTotalBlocks - 1u;
atlas.UploadedSignal().Connect( this, &AtlasManager::OnUpload );
// What size do we need for this atlas' strip buffer ( assume 32bit pixel format )?
SizeType width = image.GetWidth();
SizeType height = image.GetHeight();
SizeType blockArea = 0;
- SizeType totalBlocks = 0;
SizeType foundAtlas = 0;
SizeType index = 0;
slot.mImageId = 0;
// If there is a preferred atlas then check for room in that first
if ( atlas-- )
{
- foundAtlas = CheckAtlas( atlas, width, height, pixelFormat, blockArea, totalBlocks );
+ foundAtlas = CheckAtlas( atlas, width, height, pixelFormat, blockArea );
}
// Search current atlases to see if there is a good match
-
while( !foundAtlas && index < mAtlasList.size() )
{
- foundAtlas = CheckAtlas( index, width, height, pixelFormat, blockArea, totalBlocks );
+ foundAtlas = CheckAtlas( index, width, height, pixelFormat, blockArea );
++index;
}
}
else
{
- foundAtlas = CheckAtlas( newAtlas, width, height, pixelFormat, blockArea, totalBlocks );
+ foundAtlas = CheckAtlas( newAtlas, width, height, pixelFormat, blockArea );
}
}
- if ( Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy || !foundAtlas-- )
+ if ( !foundAtlas-- || Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy )
{
// Haven't found an atlas for this image!!!!!!
return;
for ( SizeType i = 0; i < blockArea; ++i )
{
// Is there currently a next free block available ?
- if ( mAtlasList[ foundAtlas ].mNextFreeBlock )
+ if ( mAtlasList[ foundAtlas ].mAvailableBlocks )
{
- // Yes, so use this for our next block
- SizeType selectedBlock = mAtlasList[ foundAtlas ].mNextFreeBlock - 1u;
- desc.mBlocksList.PushBack( selectedBlock );
-
- // Any blocks going to be available after this one (adjust to store +1 )?
- selectedBlock++;
- selectedBlock++;
- if ( selectedBlock > totalBlocks )
- {
- // No so start trying to use free blocks list
- selectedBlock = 0;
- }
- mAtlasList[ foundAtlas ].mNextFreeBlock = selectedBlock;
+ // Yes, so select our next block
+ desc.mBlocksList.PushBack( mAtlasList[ foundAtlas ].mTotalBlocks - mAtlasList[ foundAtlas ].mAvailableBlocks-- );
}
else
{
desc.mCount = 1u;
// See if there's a previously freed image ID that we can assign to this new image
- uint32_t imageId = 0;
- for ( uint32_t i = 0; i < mImageList.size(); ++i )
+ uint32_t imageId = 0u;
+ for ( uint32_t i = 0u; i < mImageList.size(); ++i )
{
if ( !mImageList[ i ].mCount )
{
SizeType width,
SizeType height,
Pixel::Format pixelFormat,
- SizeType& blockArea,
- SizeType& totalBlocks )
+ SizeType& blockArea )
{
if ( pixelFormat == mAtlasList[ atlas ].mPixelFormat )
{
- // Check to see if there are any unused blocks in this atlas to accomodate our image
- SizeType blocksInX = mAtlasList[ atlas ].mSize.mWidth / mAtlasList[ atlas ].mSize.mBlockWidth;
- SizeType blocksInY = mAtlasList[ atlas ].mSize.mHeight / mAtlasList[ atlas ].mSize.mBlockHeight;
- totalBlocks = blocksInX * blocksInY;
- SizeType blocksFree = mAtlasList[ atlas ].mNextFreeBlock ?
- totalBlocks - mAtlasList[ atlas ].mNextFreeBlock + 1u :
- mAtlasList[ atlas ].mFreeBlocksList.Size();
-
// Check to see if the image will fit in these blocks, if not we'll need to create a new atlas
- if ( blocksFree
- && width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockWidth
- && height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockHeight )
+ if ( ( mAtlasList[ atlas ].mAvailableBlocks + mAtlasList[ atlas ].mFreeBlocksList.Size() )
+ && width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockWidth
+ && height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockHeight )
{
blockArea = 1u;
return ( atlas + 1u );
}
}
- return 0;
+ return 0u;
}
void AtlasManager::CreateMesh( SizeType atlas,
Toolkit::AtlasManager::Mesh2D& mesh,
AtlasSlotDescriptor& desc )
{
-
Toolkit::AtlasManager::Vertex2D vertex;
uint32_t faceIndex = 0; // TODO change to unsigned short when property type is available
float texelX = 1.0f / static_cast< float >( width );
float texelY = 1.0f / static_cast< float >( height );
+ float halfTexelX = texelX * 0.5f;
+ float halfTexelY = texelY * 0.5f;
+
// Get the normalized size of a block in texels
float texelBlockWidth = texelX * vertexBlockWidth;
float texelBlockHeight = texelY * vertexBlockHeight;
float vertexEdgeHeight = static_cast< float >( imageHeight % blockHeight );
// And in texels
- float texelEdgeWidth = vertexEdgeWidth * texelX;
- float texelEdgeHeight = vertexEdgeHeight * texelY;
+ float texelEdgeWidth = texelX * vertexEdgeWidth;
+ float texelEdgeHeight = texelY * vertexEdgeHeight;
+
+ // We're going to 'blit' half a pixel more on each edge
+ vertexBlockWidth++;
+ vertexEdgeWidth++;
+ vertexBlockHeight++;
+ vertexEdgeHeight++;
// Block by block create the two triangles for the quad
SizeType blockIndex = 0;
float ndcVWidth;
float ndcVHeight;
- Vector2 topLeft = position;
+ // Move back half a pixel
+ Vector2 topLeft = Vector2( position.x - 0.5f, position.y - 0.5f );
for ( SizeType y = 0; y < heightInBlocks; ++y )
{
if ( ( heightInBlocks - 1u ) == y && vertexEdgeHeight > 0.0f )
{
- ndcHeight = texelEdgeHeight;
+ ndcHeight = texelEdgeHeight + texelY;
ndcVHeight = vertexEdgeHeight;
}
else
{
- ndcHeight = texelBlockHeight;
+ ndcHeight = texelBlockHeight + texelY;
ndcVHeight = vertexBlockHeight;
}
float fBlockY = texelBlockHeight * static_cast< float >( block / atlasWidthInBlocks );
// Add on texture filtering compensation
- fBlockX += texelX;
- fBlockY += texelY;
+ fBlockX += halfTexelX;
+ fBlockY += halfTexelY;
if ( ( widthInBlocks - 1u ) == x && vertexEdgeWidth > 0.0f )
{
- ndcWidth = texelEdgeWidth;
+ ndcWidth = texelEdgeWidth + texelX;
ndcVWidth = vertexEdgeWidth;
}
else
{
- ndcWidth = texelBlockWidth;
+ ndcWidth = texelBlockWidth + texelX;
ndcVWidth = vertexBlockWidth;
}
Toolkit::AtlasManager::Mesh2D optimizedMesh;
OptimizeMesh( mesh, optimizedMesh );
}
- //PrintMeshData( mesh );
}
void AtlasManager::PrintMeshData( const Toolkit::AtlasManager::Mesh2D& mesh )
Toolkit::AtlasManager::Vertex2D v = in.mVertices[ in.mIndices[ i ] ];
for ( SizeType j = 0; j < out.mVertices.Size(); ++j )
{
- if ( v.mPosition.x == out.mVertices[ j ].mPosition.x && v.mPosition.y == out.mVertices[ j ].mPosition.y &&
- v.mTexCoords.x == out.mVertices[ j ].mTexCoords.x && v.mTexCoords.y == out.mVertices[ j ].mTexCoords.y )
+ if ( ( fabsf( v.mPosition.x - out.mVertices[ j ].mPosition.x ) < Math::MACHINE_EPSILON_1000 ) &&
+ ( fabsf( v.mPosition.y - out.mVertices[ j ].mPosition.y ) < Math::MACHINE_EPSILON_1000 ) &&
+ ( fabsf( v.mTexCoords.x - out.mVertices[ j ].mTexCoords.x ) < Math::MACHINE_EPSILON_1000 ) &&
+ ( fabsf( v.mTexCoords.y - out.mVertices[ j ].mTexCoords.y ) < Math::MACHINE_EPSILON_1000 ) )
{
// Yes, so store this down as the vertex to use
out.mIndices.PushBack( j );
mUploadedImages.PushBack( const_cast< BufferImage& >( image ).GetBuffer() );
}
- // If this is the first block then we need to keep the first pixel free for underline texture
- if ( block )
+ // Blit top strip
+ if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip,
+ blockOffsetX,
+ blockOffsetY ) )
{
+ DALI_LOG_ERROR("Uploading top strip to Atlas Failed!\n");
+ }
+ else
+ {
+ mUploadedImages.PushBack( NULL );
+ }
- // Blit top strip
- if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip,
- blockOffsetX,
- blockOffsetY ) )
- {
- DALI_LOG_ERROR("Uploading top strip to Atlas Failed!\n");
- }
- else
- {
- mUploadedImages.PushBack( NULL );
- }
-
- // Blit left strip
- if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip,
- blockOffsetX,
- blockOffsetY + SINGLE_PIXEL_PADDING ) )
- {
- DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n");
- }
- else
- {
- mUploadedImages.PushBack( NULL );
- }
+ // Blit left strip
+ if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip,
+ blockOffsetX,
+ blockOffsetY + SINGLE_PIXEL_PADDING ) )
+ {
+ DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n");
+ }
+ else
+ {
+ mUploadedImages.PushBack( NULL );
}
// Blit bottom strip
AtlasManager::SizeType AtlasManager::GetFreeBlocks( AtlasId atlas ) const
{
- if ( atlas && atlas <= mAtlasList.size() )
+ if ( atlas && atlas-- <= mAtlasList.size() )
{
- uint32_t index = atlas - 1u;
- uint32_t width = mAtlasList[ index ].mSize.mWidth;
- uint32_t height = mAtlasList[ index ].mSize.mHeight;
- uint32_t blockWidth = mAtlasList[ index ].mSize.mBlockWidth;
- uint32_t blockHeight = mAtlasList[ index ].mSize.mBlockHeight;
-
- SizeType widthInBlocks = width / blockWidth;
- SizeType heightInBlocks = height / blockHeight;
- uint32_t blockCount = widthInBlocks * heightInBlocks;
-
- // Check free previously unallocated blocks and any free blocks
- if ( mAtlasList[ index ].mNextFreeBlock )
- {
- blockCount -= mAtlasList[ index ].mNextFreeBlock -1u - mAtlasList[ index ].mFreeBlocksList.Size();
- }
- else
- {
- blockCount = mAtlasList[ index ].mFreeBlocksList.Size();
- }
- return blockCount;
+ return ( mAtlasList[ atlas ].mAvailableBlocks + mAtlasList[ atlas ].mFreeBlocksList.Size() );
}
else
{
DALI_LOG_ERROR("Cannot get Atlas from AtlasID ( doesn't exist ).\n");
return Pixel::L8;
}
- return mAtlasList[ atlas -1u ].mPixelFormat;
+ return mAtlasList[ --atlas].mPixelFormat;
}
void AtlasManager::GetMetrics( Toolkit::AtlasManager::Metrics& metrics )
for ( uint32_t i = 0; i < atlasCount; ++i )
{
entry.mSize = mAtlasList[ i ].mSize;
- entry.mTotalBlocks = ( entry.mSize.mWidth / entry.mSize.mBlockWidth ) * ( entry.mSize.mHeight / entry.mSize.mBlockHeight );
- uint32_t reuseBlocks = mAtlasList[ i ].mFreeBlocksList.Size();
- entry.mBlocksUsed = mAtlasList[ i ].mNextFreeBlock ? mAtlasList[ i ].mNextFreeBlock - reuseBlocks - 1u: entry.mTotalBlocks - reuseBlocks;
+ entry.mTotalBlocks = mAtlasList[ i ].mTotalBlocks;
+ entry.mBlocksUsed = entry.mTotalBlocks - mAtlasList[ i ].mAvailableBlocks + mAtlasList[ i ].mFreeBlocksList.Size();
entry.mPixelFormat = GetPixelFormat( i + 1 );
- metrics.mAtlasMetrics.PushBack( entry );
+ metrics.mAtlasMetrics.PushBack( entry );
uint32_t size = entry.mSize.mWidth * entry.mSize.mHeight;
if ( entry.mPixelFormat == Pixel::BGRA8888 )
Material AtlasManager::GetMaterial( AtlasId atlas ) const
{
- if ( atlas && atlas <= mAtlasList.size() )
+ if ( atlas && atlas-- <= mAtlasList.size() )
{
- return mAtlasList[ atlas -1u ].mMaterial;
+ return mAtlasList[ atlas ].mMaterial;
}
Material null;
return null;
Sampler AtlasManager::GetSampler( AtlasId atlas ) const
{
- if ( atlas && atlas <= mAtlasList.size() )
+ if ( atlas && atlas-- <= mAtlasList.size() )
{
- return mAtlasList[ atlas -1u ].mSampler;
+ return mAtlasList[ atlas ].mSampler;
}
Sampler null;
return null;
PixelBuffer* mStripBuffer; // Blank image buffer used to pad upload
Material mMaterial; // material used for atlas texture
Sampler mSampler; // sampler used for atlas texture
- SizeType mNextFreeBlock; // next free block will be placed here ( actually +1 )
+ SizeType mTotalBlocks; // total number of blocks in atlas
+ SizeType mAvailableBlocks; // number of blocks available in atlas
Dali::Vector< SizeType > mFreeBlocksList; // unless there are any previously freed blocks
};
SizeType width,
SizeType height,
Pixel::Format pixelFormat,
- SizeType& blockArea,
- SizeType& totalBlocks );
+ SizeType& blockArea );
void CreateMesh( SizeType atlas,
SizeType imageWidth,
ret = ToString( value.Get<int>() );
break;
}
- case Property::UNSIGNED_INTEGER:
- {
- ret = ToString( value.Get<unsigned int>() );
- break;
- }
case Property::VECTOR2:
{
ret = ToString( value.Get<Vector2>() );
}
break;
}
- case Property::UNSIGNED_INTEGER:
- {
- if( OptionalUnsignedInt v = replacer.IsUnsignedInteger( node) )
- {
- value = *v;
- done = true;
- }
- break;
- }
case Property::VECTOR2:
{
if( OptionalVector2 v = replacer.IsVector2(node) )
return ret;
}
-OptionalUnsignedInt Replacement::IsUnsignedInteger( const TreeNode & node ) const
-{
- OptionalUnsignedInt ret;
- if( OptionalString replace = HasFullReplacement( node ) )
- {
- Property::Value value = GetFullReplacement( *replace );
- if( Property::UNSIGNED_INTEGER == value.GetType() )
- {
- ret = value.Get<unsigned int>();
- }
- }
- else
- {
- if ( OptionalInteger i = ::IsInteger( node ) )
- {
- ret = OptionalUnsignedInt(static_cast<unsigned int>(*i) );
- }
- }
- return ret;
-}
-
OptionalVector2 Replacement::IsVector2( const TreeNode & node ) const
{
OptionalVector2 ret;
* @param node The TreeNode to check
* @return Optional value
*/
- OptionalUnsignedInt IsUnsignedInteger( const TreeNode & node ) const;
-
- /* @brief Check node for a type
- *
- * @param node The TreeNode to check
- * @return Optional value
- */
OptionalVector2 IsVector2( const TreeNode & node ) const;
/* @brief Check node for a type
vertices.SetData( &vertexData[0] );
Property::Map indexFormat;
- indexFormat["indices"] = Property::UNSIGNED_INTEGER;
+ indexFormat["indices"] = Property::INTEGER;
PropertyBuffer indices = PropertyBuffer::New( indexFormat, numIndex );
indices.SetData( &indexData[0] );
{
if( !mTogglableButton )
{
- Toolkit::Button handle( GetOwner() );
-
Pressed();
if( mAutoRepeating )
{
SetUpTimer( mInitialAutoRepeatingDelay );
}
-
- //Emit signal.
- mPressedSignal.Emit( handle );
}
+
+ // The pressed signal should be emitted regardless of toggle mode.
+ Toolkit::Button handle( GetOwner() );
+ mPressedSignal.Emit( handle );
}
void Button::OnButtonUp()
{
mAutoRepeatingTimer.Reset();
}
-
- Toolkit::Button handle( GetOwner() );
-
- //Emit signal.
- mReleasedSignal.Emit( handle );
- mClickedSignal.Emit( handle );
}
+
+ // The clicked and released signals should be emitted regardless of toggle mode.
+ Toolkit::Button handle( GetOwner() );
+ mReleasedSignal.Emit( handle );
+ mClickedSignal.Emit( handle );
}
}
{
if( !mTogglableButton )
{
- Toolkit::Button handle( GetOwner() );
-
Released();
if( mAutoRepeating )
{
mAutoRepeatingTimer.Reset();
}
-
- //Emit signal.
- mReleasedSignal.Emit( handle );
}
+
+ // The released signal should be emitted regardless of toggle mode.
+ Toolkit::Button handle( GetOwner() );
+ mReleasedSignal.Emit( handle );
}
}
unsigned int indexData[18] = { 0,3,1,0,2,3,4,7,5,4,6,7,8,11,9,8,10,11 };
Property::Map indexFormat;
- indexFormat["indices"] = Property::UNSIGNED_INTEGER;
+ indexFormat["indices"] = Property::INTEGER;
PropertyBuffer indices = PropertyBuffer::New( indexFormat, 18u );
indices.SetData( indexData );
// Setup properties, signals and actions using the type-registry.
DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TableView, Toolkit::Control, Create );
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows", UNSIGNED_INTEGER, ROWS )
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns", UNSIGNED_INTEGER, COLUMNS )
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cell-padding", VECTOR2, CELL_PADDING )
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-rows", MAP, LAYOUT_ROWS )
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-columns", MAP, LAYOUT_COLUMNS )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows", INTEGER, ROWS )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns", INTEGER, COLUMNS )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cell-padding", VECTOR2, CELL_PADDING )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-rows", MAP, LAYOUT_ROWS )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-columns", MAP, LAYOUT_COLUMNS )
DALI_TYPE_REGISTRATION_END()
{
case Toolkit::TableView::Property::ROWS:
{
- if( value.Get<unsigned int>() != tableViewImpl.GetRows() )
+ int rows = 0;
+ if( value.Get( rows ) && rows >= 0 )
{
- tableViewImpl.Resize( value.Get<unsigned int>(), tableViewImpl.GetColumns() );
+ if( static_cast<unsigned int>(rows) != tableViewImpl.GetRows() )
+ {
+ tableViewImpl.Resize( rows, tableViewImpl.GetColumns() );
+ }
}
break;
}
case Toolkit::TableView::Property::COLUMNS:
{
- if( value.Get<unsigned int>() != tableViewImpl.GetColumns() )
+ int columns = 0;
+ if( value.Get( columns ) && columns >= 0 )
{
- tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get<unsigned int>() );
+ if( static_cast<unsigned int>( columns ) != tableViewImpl.GetColumns() )
+ {
+ tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get<int>() );
+ }
}
break;
}
{
case Toolkit::TableView::Property::ROWS:
{
- value = tableViewImpl.GetRows();
+ value = static_cast<int>( tableViewImpl.GetRows() );
break;
}
case Toolkit::TableView::Property::COLUMNS:
{
- value = tableViewImpl.GetColumns();
+ value = static_cast<int>( tableViewImpl.GetColumns() );
break;
}
case Toolkit::TableView::Property::CELL_PADDING:
mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
}
- RenderText();
EnableClipping( (Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy), size );
+ RenderText();
}
}
void TextField::RenderText()
{
+ Actor self = Self();
Actor renderableActor;
if( mRenderer )
{
- renderableActor = mRenderer->Render( mController->GetView(), mDepth );
+ renderableActor = mRenderer->Render( mController->GetView(), self.GetHierarchyDepth() );
}
if( renderableActor != mRenderableActor )
mRenderableActor.SetPosition( offset.x, offset.y );
- // Make sure the actor is parented correctly with/without clipping
+ Actor clipRootActor;
if( mClipper )
{
- mClipper->GetRootActor().Add( mRenderableActor );
- }
- else
- {
- Self().Add( mRenderableActor );
+ clipRootActor = mClipper->GetRootActor();
}
for( std::vector<Actor>::const_iterator it = mClippingDecorationActors.begin(),
{
Actor actor = *it;
- if( mClipper )
+ if( clipRootActor )
{
- mClipper->GetRootActor().Add( actor );
+ clipRootActor.Add( actor );
}
else
{
- Self().Add( actor );
+ self.Add( actor );
}
}
mClippingDecorationActors.clear();
+
+ // Make sure the actor is parented correctly with/without clipping
+ if( clipRootActor )
+ {
+ clipRootActor.Add( mRenderableActor );
+ }
+ else
+ {
+ self.Add( mRenderableActor );
+ }
}
}
void TextField::OnStageConnection( int depth )
{
- mDepth = depth;
+ // Call the Control::OnStageConnection() to set the depth of the background.
+ Control::OnStageConnection( depth );
+
+ // Sets the depth to the renderers inside the text's decorator.
+ mDecorator->SetTextDepth( depth );
+
+ // The depth of the text renderer is set in the RenderText() called from OnRelayout().
}
bool TextField::OnTouched( Actor actor, const TouchEvent& event )
: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP ),
- mDepth( 0 ),
mHasBeenStaged( false )
{
}
int mRenderingBackend;
int mExceedPolicy;
- unsigned int mDepth;
bool mHasBeenStaged:1;
};
void TextLabel::RenderText()
{
+ Actor self = Self();
Actor renderableActor;
if( mRenderer )
{
- renderableActor = mRenderer->Render( mController->GetView(), mDepth );
+ renderableActor = mRenderer->Render( mController->GetView(), self.GetHierarchyDepth() );
}
if( renderableActor != mRenderableActor )
const Vector2& alignmentOffset = mController->GetAlignmentOffset();
renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y );
- Self().Add( renderableActor );
+ self.Add( renderableActor );
}
mRenderableActor = renderableActor;
}
void TextLabel::OnStageConnection( int depth )
{
- mDepth = depth;
+ // Call the Control::OnStageConnection() to set the depth of the background.
+ Control::OnStageConnection( depth );
+
+ // The depth of the text renderer is set in the RenderText() called from OnRelayout().
}
void TextLabel::TextChanged()
TextLabel::TextLabel()
: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
mRenderingBackend( DEFAULT_RENDERING_BACKEND ),
- mDepth( 0 ),
mHasBeenStaged( false )
{
}
Text::RendererPtr mRenderer;
Actor mRenderableActor;
int mRenderingBackend;
- unsigned int mDepth;
bool mHasBeenStaged:1;
};
// todo Move this to adaptor??
#define GET_LOCALE_TEXT(string) dgettext("elementary", string)
+const std::string TEXT_SELECTION_POPUP_LABEL = "textselectionpopuplabel";
+
const Dali::Vector4 DEFAULT_POPUP_DIVIDER_COLOR( Dali::Vector4( 0.23f, 0.72f, 0.8f, 0.11f ) );
const Dali::Vector4 DEFAULT_OPTION_ICON( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) );
const Dali::Vector4 DEFAULT_OPTION_PRESSED_COLOR( Dali::Vector4( 0.24f, 0.72f, 0.8f, 0.11f ) );
+const float DEFAULT_CAPTION_POINT_SIZE = 8.0f; // todo This should be from the style sheet not fixed.
+
const std::string DEFAULT_POPUP_BACKGROUND_IMAGE( DALI_IMAGE_DIR "selection-popup-bg#.png" );
const std::string OPTION_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" );
const std::string OPTION_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" );
Dali::Toolkit::TextSelectionPopup handle( *impl );
impl->mEnabledButtons = buttonsToEnable;
-
// Second-phase init of the implementation
// This can only be done after the CustomActor connection has been made...
impl->Initialize();
return value;
}
+void TextSelectionPopup::RaiseAbove( Layer target )
+{
+ if( mToolbar )
+ {
+ mToolbar.RaiseAbove( target );
+ }
+}
+
void TextSelectionPopup::OnInitialize()
{
CreatePopup();
}
+void TextSelectionPopup::OnStageConnection( int depth )
+{
+ // Call the Control::OnStageConnection() to set the depth of the background.
+ Control::OnStageConnection( depth );
+
+ // TextSelectionToolbar::OnStageConnection() will set the depths of all the popup's components.
+}
+
bool TextSelectionPopup::OnCutButtonPressed( Toolkit::Button button )
{
if( mCallbackInterface )
void TextSelectionPopup::CreateOrderedListOfPopupOptions()
{
mOrderListOfButtons.clear();
+ mOrderListOfButtons.reserve( 8u );
// Create button for each possible option using Option priority
if ( !mCutIconImage )
void TextSelectionPopup::AddOption( const ButtonRequirement& button, bool showDivider, bool showIcons, bool showCaption )
{
-
const std::string& name = button.name;
const std::string& caption = button.caption;
Image iconImage = button.icon;
if ( showCaption )
{
Toolkit::TextLabel captionTextLabel = Toolkit::TextLabel::New();
+ captionTextLabel.SetStyleName( TEXT_SELECTION_POPUP_LABEL );
captionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption );
+ captionTextLabel.SetProperty( Toolkit::TextLabel::Property::POINT_SIZE, DEFAULT_CAPTION_POINT_SIZE );
captionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
Toolkit::TextLabel pressedCaptionTextLabel = Toolkit::TextLabel::New();
+ pressedCaptionTextLabel.SetStyleName( TEXT_SELECTION_POPUP_LABEL );
pressedCaptionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption );
+ pressedCaptionTextLabel.SetProperty( Toolkit::TextLabel::Property::POINT_SIZE, DEFAULT_CAPTION_POINT_SIZE );
pressedCaptionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
Padding padding;
optionPressedContainer.AddChild( pressedCaptionTextLabel, Toolkit::TableView::CellPosition(( showIcons&showCaption)?1:0, 0 ) );
}
+ int depth = Self().GetHierarchyDepth();
// 3. Create the icons
if ( showIcons )
{
ImageActor pressedIcon = ImageActor::New( iconImage );
ImageActor icon = ImageActor::New( iconImage );
- icon.SetSortModifier( DECORATION_DEPTH_INDEX - 1 );
- pressedIcon.SetSortModifier( DECORATION_DEPTH_INDEX - 1 );
+ icon.SetSortModifier( DECORATION_DEPTH_INDEX + depth - 1 );
+ pressedIcon.SetSortModifier( DECORATION_DEPTH_INDEX + depth - 1 );
icon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
pressedIcon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
const Size size( mOptionDividerSize.width, 0.0f ); // Height FILL_TO_PARENT
ImageActor divider = Toolkit::CreateSolidColorActor( Color::WHITE );
+#ifdef DECORATOR_DEBUG
+ divider.SetName("Text's popup divider");
+#endif
divider.SetSize( size );
divider.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
divider.SetColor( mDividerColor );
+ divider.SetSortModifier( DECORATION_DEPTH_INDEX + depth );
mToolbar.AddDivider( divider );
}
}
self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
SetBackgroundImage( NinePatchImage::New( DEFAULT_POPUP_BACKGROUND_IMAGE ) );
- if ( !mToolbar )
+ if( !mToolbar )
{
mToolbar = Toolkit::TextSelectionToolbar::New();
mToolbar.SetParentOrigin( ParentOrigin::CENTER );
*/
static Property::Value GetProperty( BaseObject* object, Property::Index index );
+ /**
+ * @copydoc Toolkit::TextSelectionPopup::RaiseAbove()
+ */
+ void RaiseAbove( Layer target );
+
private: // From Control
/**
*/
virtual void OnInitialize();
+ /**
+ * @copydoc Control::OnStageConnection()
+ */
+ virtual void OnStageConnection( int depth );
+
private: // Implementation
/**
#include <dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
// EXTERNAL INCLUDES
mScrollView.SetRulerX( mRulerX );
}
+void TextSelectionToolbar::OnStageConnection( int depth )
+{
+ // Call the Control::OnStageConnection() to set the depth of the background.
+ Control::OnStageConnection( depth );
+
+ // Traverse the dividers and set the depth.
+ for( unsigned int i = 0; i < mDividerIndexes.Count(); ++i )
+ {
+ Actor divider = mTableOfButtons.GetChildAt( Toolkit::TableView::CellPosition( 0, mDividerIndexes[ i ] ) );
+
+ ImageActor dividerImageActor = ImageActor::DownCast( divider );
+ if( dividerImageActor )
+ {
+ dividerImageActor.SetSortModifier( DECORATION_DEPTH_INDEX + depth );
+ }
+ else
+ {
+ // TODO at the moment divider are image actors.
+ }
+ }
+
+ // Texts are controls, they have their own OnStageConnection() implementation.
+ // Icons are inside a TableView. It has it's own OnStageConnection() implementation.
+}
+
void TextSelectionToolbar::SetPopupMaxSize( const Size& maxSize )
{
mMaxSize = maxSize;
self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
// Create Layer and Stencil. Layer enable's clipping when content exceed maximum defined width.
- Layer stencilLayer = Layer::New();
- stencilLayer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
- stencilLayer.SetParentOrigin( ParentOrigin::CENTER );
- stencilLayer.SetMaximumSize( mMaxSize );
+ mStencilLayer = Layer::New();
+ mStencilLayer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+ mStencilLayer.SetParentOrigin( ParentOrigin::CENTER );
+ mStencilLayer.SetMaximumSize( mMaxSize );
ImageActor stencil = CreateSolidColorActor( Color::RED );
stencil.SetDrawMode( DrawMode::STENCIL );
mTableOfButtons.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
- stencilLayer.Add( stencil );
- stencilLayer.Add( mScrollView );
+ mStencilLayer.Add( stencil );
+ mStencilLayer.Add( mScrollView );
mScrollView.Add( mTableOfButtons );
- self.Add( stencilLayer );
-
- stencilLayer.RaiseToTop();
+ self.Add( mStencilLayer );
}
void TextSelectionToolbar::OnScrollStarted( const Vector2& position )
void TextSelectionToolbar::AddDivider( Actor& divider )
{
AddOption( divider );
- mDividerIndexes.PushBack( mIndexInTable );
+ mDividerIndexes.PushBack( mIndexInTable - 1u );
}
void TextSelectionToolbar::ResizeDividers( Size& size )
RelayoutRequest();
}
+void TextSelectionToolbar::RaiseAbove( Layer target )
+{
+ mStencilLayer.RaiseAbove( target );
+}
+
TextSelectionToolbar::TextSelectionToolbar()
: Control( ControlBehaviour( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ) ),
mMaxSize ( DEFAULT_MAX_SIZE ),
mRulerX.Reset();
}
-
} // namespace Internal
} // namespace Toolkit
static Property::Value GetProperty( BaseObject* object, Property::Index index );
/**
- * @copydoc TextSelectionToolbar::AddOption
+ * @copydoc Toolkit::TextSelectionToolbar::AddOption()
*/
void AddOption( Actor& option );
/**
- * @copydoc TextSelectionToolbar::AddDivider
+ * @copydoc Toolkit::TextSelectionToolbar::AddDivider()
*/
void AddDivider( Actor& divider );
/**
- * @copydoc ResizeDividers
+ * @copydoc Toolkit::TextSelectionToolbar::ResizeDividers()
*/
void ResizeDividers( Size& size );
+ /**
+ * @copydoc Toolkit::TextSelectionToolbar::RaiseAbove()
+ */
+ void RaiseAbove( Layer target );
+
private: // From Control
/**
* @copydoc Control::OnRelayout()
*/
virtual void OnRelayout( const Vector2& size, RelayoutContainer& container );
+
+ /**
+ * @copydoc Control::OnStageConnection()
+ */
+ virtual void OnStageConnection( int depth );
+
/**
* @brief Set max size of Popup
* @param[in] maxSize Size (Vector2)
private: // Data
- Toolkit::TableView mTableOfButtons; // Actor which holds all the buttons, sensitivity can be set on buttons via this actor
- Toolkit::ScrollView mScrollView; // Provides scrolling of Toolbar when content does not fit.
- RulerPtr mRulerX; // Ruler to clamp horizontal scrolling. Updates on Relayout
- Size mMaxSize; // Max size of the Toolbar
- unsigned int mIndexInTable; // Index in table to add option
- Dali::Vector< unsigned int > mDividerIndexes; // Vector of indexes in the Toolbar that contain dividers.
+ Layer mStencilLayer; ///< The stencil layer
+ Toolkit::TableView mTableOfButtons; ///< Actor which holds all the buttons, sensitivity can be set on buttons via this actor
+ Toolkit::ScrollView mScrollView; ///< Provides scrolling of Toolbar when content does not fit.
+ RulerPtr mRulerX; ///< Ruler to clamp horizontal scrolling. Updates on Relayout
+ Size mMaxSize; ///< Max size of the Toolbar
+ unsigned int mIndexInTable; ///< Index in table to add option
+ Dali::Vector< unsigned int > mDividerIndexes; ///< Vector of indexes in the Toolbar that contain dividers.
};
// The memory is freed after the visual to logical to visual conversion tables are built in the logical model.
lineInfoRun.visualToLogicalMap = reinterpret_cast<CharacterIndex*>( malloc( line.characterRun.numberOfCharacters * sizeof( CharacterIndex ) ) );
- // Reorders the line.
- bidirectionalSupport.Reorder( paragraphInfo.bidirectionalInfoIndex,
- line.characterRun.characterIndex - paragraphInfo.characterRun.characterIndex,
- line.characterRun.numberOfCharacters,
- lineInfoRun.visualToLogicalMap );
+ if( NULL != lineInfoRun.visualToLogicalMap )
+ {
+ // Reorders the line.
+ bidirectionalSupport.Reorder( paragraphInfo.bidirectionalInfoIndex,
+ line.characterRun.characterIndex - paragraphInfo.characterRun.characterIndex,
+ line.characterRun.numberOfCharacters,
+ lineInfoRun.visualToLogicalMap );
+ }
// Push the run into the vector.
lineInfoRuns.PushBack( lineInfoRun );
const Dali::Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.25f, 1.5f, 1.0f );
const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.25f, 1.5f, 1.0f );
-const Dali::Vector4 LIGHT_BLUE( (0xb2 / 255.0f), (0xeb / 255.0f), (0xf2 / 255.0f), 0.5f ); // The text highlight color.
+const Dali::Vector4 LIGHT_BLUE( 0.75f, 0.96f, 1.f, 1.f ); // The text highlight color. TODO: due some problems, maybe with the blending function in the text clipping, the color is fully opaque.
const Dali::Vector4 HANDLE_COLOR( 0.0f, (183.0f / 255.0f), (229.0f / 255.0f), 1.0f );
const float TO_MILLISECONDS = 1000.f;
const float TO_SECONDS = 1.f / TO_MILLISECONDS;
-const float DISPLAYED_HIGHLIGHT_Z_OFFSET( -0.05f );
-
const unsigned int SCROLL_TICK_INTERVAL = 50u;
const float SCROLL_THRESHOLD = 10.f;
mNotifyEndOfScroll( false )
{
mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
- mQuadIndexFormat[ "indices" ] = Property::UNSIGNED_INTEGER;
+ mQuadIndexFormat[ "indices" ] = Property::INTEGER;
mHighlightMaterial = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
}
}
else if( grabHandle.actor )
{
- UnparentAndReset( grabHandle.actor );
+ grabHandle.actor.Unparent();
}
// Show or hide the selection handles/highlight
primary.actor.SetVisible( isPrimaryVisible );
secondary.actor.SetVisible( isSecondaryVisible );
- // Shouldn't be needed......
- UnparentAndReset( mHighlightActor );
-
CreateHighlight();
UpdateHighlight();
}
else
{
- UnparentAndReset( primary.actor );
- UnparentAndReset( secondary.actor );
- UnparentAndReset( mHighlightActor );
+ if( primary.actor )
+ {
+ primary.actor.Unparent();
+ }
+ if( secondary.actor )
+ {
+ secondary.actor.Unparent();
+ }
+ if( mHighlightActor )
+ {
+ mHighlightActor.Unparent();
+ }
}
- if ( mActiveCopyPastePopup )
+ if( mActiveCopyPastePopup )
{
- // todo Swap UnparentAndReset for DeterminePositionPopup() if mCopyPastePopup.actor valid Once the issue with the labels disappearing is fixed.
- UnparentAndReset( mCopyPastePopup.actor );
- if ( !mCopyPastePopup.actor )
+ if( !mCopyPastePopup.actor.GetParent() )
{
- mCopyPastePopup.actor = TextSelectionPopup::New( mEnabledPopupButtons, &mTextSelectionPopupCallbackInterface );
-#ifdef DECORATOR_DEBUG
- mCopyPastePopup.actor.SetName("mCopyPastePopup");
-#endif
- mCopyPastePopup.actor.SetAnchorPoint( AnchorPoint::CENTER );
- mCopyPastePopup.actor.OnRelayoutSignal().Connect( this, &Decorator::Impl::PopupRelayoutComplete ); // Position popup after size negotiation
- mActiveLayer.Add ( mCopyPastePopup.actor );
+ mActiveLayer.Add( mCopyPastePopup.actor );
}
+
+ mCopyPastePopup.actor.RaiseAbove( mActiveLayer );
}
else
{
- if ( mCopyPastePopup.actor )
- {
- UnparentAndReset( mCopyPastePopup.actor );
- }
+ if( mCopyPastePopup.actor )
+ {
+ mCopyPastePopup.actor.Unparent();
+ }
}
}
mHandle[ LEFT_SELECTION_HANDLE ].position += scrollOffset;
mHandle[ RIGHT_SELECTION_HANDLE ].position += scrollOffset;
mHighlightPosition += scrollOffset;
+ DeterminePositionPopup();
}
void DeterminePositionPopup()
{
if( mActiveCursor == ACTIVE_CURSOR_NONE )
{
- UnparentAndReset( mPrimaryCursor );
- UnparentAndReset( mSecondaryCursor );
+ if( mPrimaryCursor )
+ {
+ mPrimaryCursor.Unparent();
+ }
+ if( mSecondaryCursor )
+ {
+ mSecondaryCursor.Unparent();
+ }
}
else
{
#ifdef DECORATOR_DEBUG
mPrimaryCursor.SetName( "PrimaryCursorActor" );
#endif
+ }
+
+ if( !mPrimaryCursor.GetParent() )
+ {
mActiveLayer.Add( mPrimaryCursor );
}
}
#ifdef DECORATOR_DEBUG
mSecondaryCursor.SetName( "SecondaryCursorActor" );
#endif
+ }
+
+ if( !mSecondaryCursor.GetParent() )
+ {
mActiveLayer.Add( mSecondaryCursor );
}
}
else
{
- UnparentAndReset( mSecondaryCursor );
+ if( mSecondaryCursor )
+ {
+ mSecondaryCursor.Unparent();
+ }
}
}
}
mActiveLayer.Add( grabHandle.actor );
}
+
+ if( !grabHandle.actor.GetParent() )
+ {
+ mActiveLayer.Add( grabHandle.actor );
+ }
}
void CreateSelectionHandles()
primary.grabArea.TouchedSignal().Connect( this, &Decorator::Impl::OnHandleOneTouched );
primary.actor.Add( primary.grabArea );
+ }
+
+ if( !primary.actor.GetParent() )
+ {
mActiveLayer.Add( primary.actor );
}
secondary.grabArea.TouchedSignal().Connect( this, &Decorator::Impl::OnHandleTwoTouched );
secondary.actor.Add( secondary.grabArea );
+ }
+
+ if( !secondary.actor.GetParent() )
+ {
mActiveLayer.Add( secondary.actor );
}
}
void CreateHighlight()
{
- if ( !mHighlightActor )
+ if( !mHighlightActor )
{
mHighlightActor = Actor::New();
mHighlightActor.SetName( "HighlightActor" );
#endif
mHighlightActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
- mHighlightActor.SetPosition( 0.0f, 0.0f, DISPLAYED_HIGHLIGHT_Z_OFFSET );
mHighlightActor.SetSize( 1.0f, 1.0f );
mHighlightActor.SetColor( mHighlightColor );
mHighlightActor.SetColorMode( USE_OWN_COLOR );
-
- // Add the highlight box telling the controller it needs clipping.
- mController.AddDecoration( mHighlightActor, true );
}
+
+ // Add the highlight box telling the controller it needs clipping.
+ mController.AddDecoration( mHighlightActor, true );
}
void UpdateHighlight()
{
-
- if ( mHighlightActor && !mHighlightQuadList.empty() )
+ if ( mHighlightActor )
{
- Vector< Vector2 > vertices;
- Vector< unsigned int> indices;
- Vector2 vertex;
+ if( !mHighlightQuadList.empty() )
+ {
+ Vector< Vector2 > vertices;
+ Vector< unsigned int> indices;
+ Vector2 vertex;
- std::vector<QuadCoordinates>::iterator iter = mHighlightQuadList.begin();
- std::vector<QuadCoordinates>::iterator endIter = mHighlightQuadList.end();
+ std::vector<QuadCoordinates>::iterator iter = mHighlightQuadList.begin();
+ std::vector<QuadCoordinates>::iterator endIter = mHighlightQuadList.end();
- for(std::size_t v = 0; iter != endIter; ++iter,v+=4 )
- {
+ for( std::size_t v = 0; iter != endIter; ++iter,v+=4 )
+ {
+
+ QuadCoordinates& quad = *iter;
+
+ // top-left (v+0)
+ vertex.x = quad.min.x;
+ vertex.y = quad.min.y;
+ vertices.PushBack( vertex );
+
+ // top-right (v+1)
+ vertex.x = quad.max.x;
+ vertex.y = quad.min.y;
+ vertices.PushBack( vertex );
+
+ // bottom-left (v+2)
+ vertex.x = quad.min.x;
+ vertex.y = quad.max.y;
+ vertices.PushBack( vertex );
+
+ // bottom-right (v+3)
+ vertex.x = quad.max.x;
+ vertex.y = quad.max.y;
+ vertices.PushBack( vertex );
+
+ // triangle A (3, 1, 0)
+ indices.PushBack( v + 3 );
+ indices.PushBack( v + 1 );
+ indices.PushBack( v );
+
+ // triangle B (0, 2, 3)
+ indices.PushBack( v );
+ indices.PushBack( v + 2 );
+ indices.PushBack( v + 3 );
+ }
+
+ if( mQuadVertices )
+ {
+ mQuadVertices.SetSize( vertices.Size() );
+ }
+ else
+ {
+ mQuadVertices = PropertyBuffer::New( mQuadVertexFormat, vertices.Size() );
+ }
+
+ if( mQuadIndices )
+ {
+ mQuadIndices.SetSize( indices.Size() );
+ }
+ else
+ {
+ mQuadIndices = PropertyBuffer::New( mQuadIndexFormat, indices.Size() );
+ }
+
+ mQuadVertices.SetData( &vertices[ 0 ] );
+ mQuadIndices.SetData( &indices[ 0 ] );
+
+ mQuadGeometry = Geometry::New();
+ mQuadGeometry.AddVertexBuffer( mQuadVertices );
+ mQuadGeometry.SetIndexBuffer( mQuadIndices );
+
+ if( mHighlightRenderer )
+ {
+ mHighlightRenderer.SetGeometry( mQuadGeometry );
+ }
+ else
+ {
+ mHighlightRenderer = Dali::Renderer::New( mQuadGeometry, mHighlightMaterial );
+ mHighlightActor.AddRenderer( mHighlightRenderer );
+ }
- QuadCoordinates& quad = *iter;
-
- // top-left (v+0)
- vertex.x = quad.min.x;
- vertex.y = quad.min.y;
- vertices.PushBack( vertex );
-
- // top-right (v+1)
- vertex.x = quad.max.x;
- vertex.y = quad.min.y;
- vertices.PushBack( vertex );
-
- // bottom-left (v+2)
- vertex.x = quad.min.x;
- vertex.y = quad.max.y;
- vertices.PushBack( vertex );
-
- // bottom-right (v+3)
- vertex.x = quad.max.x;
- vertex.y = quad.max.y;
- vertices.PushBack( vertex );
-
- // triangle A (3, 1, 0)
- indices.PushBack( v + 3 );
- indices.PushBack( v + 1 );
- indices.PushBack( v );
-
- // triangle B (0, 2, 3)
- indices.PushBack( v );
- indices.PushBack( v + 2 );
- indices.PushBack( v + 3 );
+ mHighlightActor.SetPosition( mHighlightPosition.x,
+ mHighlightPosition.y );
}
- PropertyBuffer quadVertices = PropertyBuffer::New( mQuadVertexFormat, vertices.Size() );
- PropertyBuffer quadIndices = PropertyBuffer::New( mQuadIndexFormat, indices.Size() );
-
- quadVertices.SetData( &vertices[ 0 ] );
- quadIndices.SetData( &indices[ 0 ] );
-
- Geometry quadGeometry = Geometry::New();
- quadGeometry.AddVertexBuffer( quadVertices );
- quadGeometry.SetIndexBuffer( quadIndices );
-
- // if ( mHighlightRenderer )
- // {
- // mHighlightRenderer.SetGeometry( quadGeometry );
- // }
- // else
- // {
- mHighlightRenderer = Dali::Renderer::New( quadGeometry, mHighlightMaterial );
- mHighlightRenderer.SetDepthIndex( DECORATION_DEPTH_INDEX - 1 );
- // }
- mHighlightActor.AddRenderer( mHighlightRenderer );
+ mHighlightRenderer.SetDepthIndex( mTextDepth - 2u ); // text is rendered at mTextDepth and text's shadow at mTextDepth -1u.
}
}
CursorImpl mCursor[CURSOR_COUNT];
HandleImpl mHandle[HANDLE_TYPE_COUNT];
+
+ PropertyBuffer mQuadVertices;
+ PropertyBuffer mQuadIndices;
+ Geometry mQuadGeometry;
QuadContainer mHighlightQuadList; ///< Sub-selections that combine to create the complete selection highlight
Rect<int> mBoundingBox;
float mScrollThreshold; ///< Defines a square area inside the control, close to the edge. A cursor entering this area will trigger scroll events.
float mScrollSpeed; ///< The scroll speed in pixels per second.
float mScrollDistance; ///< Distance the text scrolls during a scroll interval.
+ int mTextDepth; ///< The depth used to render the text.
bool mActiveCopyPastePopup : 1;
bool mCursorBlinkStatus : 1; ///< Flag to switch between blink on and blink off.
return mImpl->mHighlightColor;
}
+void Decorator::SetTextDepth( int textDepth )
+{
+ mImpl->mTextDepth = textDepth;
+}
+
void Decorator::SetPopupActive( bool active )
{
mImpl->mActiveCopyPastePopup = active;
void Decorator::SetEnabledPopupButtons( TextSelectionPopup::Buttons& enabledButtonsBitMask )
{
mImpl->mEnabledPopupButtons = enabledButtonsBitMask;
+
+ UnparentAndReset( mImpl->mCopyPastePopup.actor );
+ mImpl->mCopyPastePopup.actor = TextSelectionPopup::New( mImpl->mEnabledPopupButtons,
+ &mImpl->mTextSelectionPopupCallbackInterface );
+#ifdef DECORATOR_DEBUG
+ mImpl->mCopyPastePopup.actor.SetName("mCopyPastePopup");
+#endif
+ mImpl->mCopyPastePopup.actor.SetAnchorPoint( AnchorPoint::CENTER );
+ mImpl->mCopyPastePopup.actor.OnRelayoutSignal().Connect( mImpl, &Decorator::Impl::PopupRelayoutComplete ); // Position popup after size negotiation
+
+ if( mImpl->mActiveLayer )
+ {
+ mImpl->mActiveLayer.Add( mImpl->mCopyPastePopup.actor );
+ }
}
TextSelectionPopup::Buttons& Decorator::GetEnabledPopupButtons()
const Vector4& GetHighlightColor() const;
/**
+ * @brief Sets into the decorator the depth used to render the text.
+ *
+ * @param[in] depth The text's depth.
+ */
+ void SetTextDepth( int textDepth );
+
+ /**
* @brief Set the Selection Popup to show or hide via the active flaf
* @param[in] active true to show, false to hide
*/
// Get the glyph info.
const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex );
+ // Check if the font of the current glyph is the same of the previous one.
+ // If it's different the ascender and descender need to be updated.
+ if( lastFontId != glyphInfo.fontId )
+ {
+ UpdateLineHeight( glyphInfo.fontId, tmpLineLayout );
+ lastFontId = glyphInfo.fontId;
+ }
+
// Get the character indices for the current glyph. The last character index is needed
// because there are glyphs formed by more than one character but their break info is
// given only for the last character.
tmpLineLayout.Clear();
}
- // Check if the font of the current glyph is the same of the previous one.
- // If it's different the ascender and descender need to be updated.
- if( lastFontId != glyphInfo.fontId )
- {
- UpdateLineHeight( glyphInfo.fontId, tmpLineLayout );
- lastFontId = glyphInfo.fontId;
- }
-
previousCharacterDirection = characterDirection;
}
return internal;
}
-void AtlasGlyphManager::Add( Text::FontId fontId,
- const Text::GlyphInfo& glyph,
+void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
Dali::Toolkit::AtlasManager::AtlasSlot& slot )
{
for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
fontGlyphRecordIt != mFontGlyphRecords.end(); ++fontGlyphRecordIt )
{
- if ( fontGlyphRecordIt->mFontId == fontId )
+ if ( fontGlyphRecordIt->mFontId == glyph.fontId )
{
fontGlyphRecordIt->mGlyphRecords.PushBack( record );
foundGlyph = true;
{
// We need to add a new font entry
FontGlyphRecord fontGlyphRecord;
- fontGlyphRecord.mFontId = fontId;
+ fontGlyphRecord.mFontId = glyph.fontId;
fontGlyphRecord.mGlyphRecords.PushBack( record );
mFontGlyphRecords.push_back( fontGlyphRecord );
}
const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
{
- mMetrics.mGlyphCount = mFontGlyphRecords.size();
+ mMetrics.mGlyphCount = 0u;
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end();
+ ++fontGlyphRecordIt )
+ {
+ mMetrics.mGlyphCount += fontGlyphRecordIt->mGlyphRecords.Size();
+ }
mAtlasManager.GetMetrics( mMetrics.mAtlasMetrics );
return mMetrics;
}
/**
* @copydoc Toolkit::AtlasGlyphManager::Add
*/
- void Add( Text::FontId fontId,
- const Text::GlyphInfo& glyph,
+ void Add( const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
Dali::Toolkit::AtlasManager::AtlasSlot& slot );
{
}
-void AtlasGlyphManager::Add( Text::FontId fontId,
- const Text::GlyphInfo& glyph,
+void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
AtlasManager::AtlasSlot& slot )
{
- GetImplementation(*this).Add( fontId, glyph, bitmap, slot );
+ GetImplementation(*this).Add( glyph, bitmap, slot );
}
void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
*/
struct Metrics
{
+ Metrics()
+ : mGlyphCount( 0u )
+ {}
+
+ ~Metrics()
+ {}
+
uint32_t mGlyphCount; // number of glyphs being managed
AtlasManager::Metrics mAtlasMetrics; // metrics from the Atlas Manager
};
/**
* @brief Ask Atlas Manager to add a glyph
*
- * @param[in] fontId fontId glyph comes from
* @param[in] glyph glyph to add to an atlas
* @param[in] bitmap bitmap to use for glyph addition
* @param[out] slot information returned by atlas manager for addition
*/
- void Add( Text::FontId fontId,
- const Text::GlyphInfo& glyph,
+ void Add( const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
AtlasManager::AtlasSlot& slot );
};
Impl()
+ : mDepth( 0 )
{
mGlyphManager = AtlasGlyphManager::Get();
mFontClient = TextAbstraction::FontClient::Get();
mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
mQuadVertexFormat[ "aTexCoord" ] = Property::VECTOR2;
- mQuadIndexFormat[ "indices" ] = Property::UNSIGNED_INTEGER;
+ mQuadIndexFormat[ "indices" ] = Property::INTEGER;
}
void AddGlyphs( const std::vector<Vector2>& positions,
bool underlineEnabled,
const Vector4& underlineColor,
float underlineHeight,
- unsigned int depth )
+ int depth )
{
AtlasManager::AtlasSlot slot;
std::vector< MeshRecord > meshContainer;
Vector< Extent > extents;
TextCacheEntry textCacheEntry;
- mDepth = static_cast< int >( depth );
+ mDepth = depth;
float currentUnderlinePosition = ZERO;
float currentUnderlineThickness = underlineHeight;
}
// Locate a new slot for our glyph
- mGlyphManager.Add( glyph.fontId, glyph, bitmap, slot );
+ mGlyphManager.Add( glyph, bitmap, slot );
}
}
currentUnderlinePosition,
currentUnderlineThickness,
slot );
- lastFontId = glyph.fontId;
+ lastFontId = glyph.fontId;
}
}
actor.Add( GenerateShadow( *mIt, shadowOffset, shadowColor ) );
}
- if ( mActor )
+ if( mActor )
{
+ actor.SetParentOrigin( ParentOrigin::CENTER ); // Keep all of the origins aligned
mActor.Add( actor );
}
else
Material material = mGlyphManager.GetMaterial( meshRecord.mAtlasId );
Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material );
- renderer.SetDepthIndex( mDepth );
+ renderer.SetDepthIndex( CONTENT_DEPTH_INDEX + mDepth );
Actor actor = Actor::New();
+#if defined(DEBUG_ENABLED)
+ actor.SetName( "Text renderable actor" );
+#endif
actor.AddRenderer( renderer );
actor.SetSize( 1.0f, 1.0f );
actor.SetColor( meshRecord.mColor );
Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material );
// Ensure shadow is behind the text...
- renderer.SetDepthIndex( mDepth + CONTENT_DEPTH_INDEX - 1 );
+ renderer.SetDepthIndex( CONTENT_DEPTH_INDEX + mDepth - 1 );
Actor actor = Actor::New();
actor.AddRenderer( renderer );
actor.SetSize( 1.0f, 1.0f );
return Text::RendererPtr( new AtlasRenderer() );
}
-Actor AtlasRenderer::Render( Text::ViewInterface& view, unsigned int depth )
+Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth )
{
UnparentAndReset( mImpl->mActor );
* @param[in] depth The depth in the tree of the parent.
* @return The Renderable actor used to position the text.
*/
- virtual Actor Render( ViewInterface& view, unsigned int depth );
+ virtual Actor Render( ViewInterface& view, int depth );
protected:
* @param[in] depth The depth in the tree of the parent.
* @return The Renderable actor used to position the text.
*/
- virtual Actor Render( ViewInterface& view, unsigned int depth ) = 0;
+ virtual Actor Render( ViewInterface& view, int depth ) = 0;
protected:
}
}
+float Controller::Impl::GetDefaultFontLineHeight()
+{
+ FontId defaultFontId = 0u;
+ if( NULL == mFontDefaults )
+ {
+ defaultFontId = mFontClient.GetFontId( EMPTY_STRING,
+ EMPTY_STRING );
+ }
+ else
+ {
+ defaultFontId = mFontDefaults->GetFontId( mFontClient );
+ }
+
+ Text::FontMetrics fontMetrics;
+ mFontClient.GetFontMetrics( defaultFontId, fontMetrics );
+
+ return( fontMetrics.ascender - fontMetrics.descender );
+}
+
void Controller::Impl::OnCursorKeyEvent( const Event& event )
{
if( NULL == mEventData )
HideClipboard();
mEventData->mDecoratorUpdated = true;
}
+ else if( EventData::EDITING_WITH_GRAB_HANDLE == mEventData->mState )
+ {
+ mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
+ if( mEventData->mCursorBlinkEnabled )
+ {
+ mEventData->mDecorator->StartCursorBlink();
+ }
+ // Grab handle is not shown until a tap is received whilst EDITING
+ mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+ mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
+ mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
+ if( mEventData->mGrabHandlePopupEnabled )
+ {
+ mEventData->mDecorator->SetPopupActive( false );
+ }
+ mEventData->mDecoratorUpdated = true;
+ HideClipboard();
+ }
else if ( EventData::SELECTION_HANDLE_PANNING == mEventData->mState )
{
mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
if( isFirstPosition && isLastPosition )
{
- // There is zero characters. Get the default font.
-
- FontId defaultFontId = 0u;
- if( NULL == mFontDefaults )
- {
- defaultFontId = mFontClient.GetFontId( EMPTY_STRING,
- EMPTY_STRING );
- }
- else
- {
- defaultFontId = mFontDefaults->GetFontId( mFontClient );
- }
-
- Text::FontMetrics fontMetrics;
- mFontClient.GetFontMetrics( defaultFontId, fontMetrics );
-
- cursorInfo.lineHeight = fontMetrics.ascender - fontMetrics.descender;
+ // There is zero characters. Get the default font's line height.
+ cursorInfo.lineHeight = GetDefaultFontLineHeight();
cursorInfo.primaryCursorHeight = cursorInfo.lineHeight;
cursorInfo.primaryPosition.x = 1.f;
SELECTION_CHANGED,
EDITING,
EDITING_WITH_POPUP,
+ EDITING_WITH_GRAB_HANDLE,
GRAB_HANDLE_PANNING,
SELECTION_HANDLE_PANNING
};
*/
void GetDefaultFonts( Dali::Vector<FontRun>& fonts, Length numberOfCharacters );
+ /**
+ * @brief Retrieve the line height of the default font.
+ */
+ float GetDefaultFontLineHeight();
+
void OnCursorKeyEvent( const Event& event );
void OnTapEvent( const Event& event );
// Get the direction of the first character.
const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u );
- const Size& actualSize = mImpl->mVisualModel->GetActualSize();
+ Size actualSize = mImpl->mVisualModel->GetActualSize();
+ if( fabsf( actualSize.height ) < Math::MACHINE_EPSILON_1000 )
+ {
+ // Get the line height of the default font.
+ actualSize.height = mImpl->GetDefaultFontLineHeight();
+ }
// If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END;
LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment();
if( !isShowingPlaceholderText &&
( EventData::EDITING == mImpl->mEventData->mState ) )
{
- mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
- mImpl->mEventData->mDecorator->SetPopupActive( false );
+ mImpl->ChangeState( EventData::EDITING_WITH_GRAB_HANDLE );
}
-
- // Handles & cursors must be repositioned after Relayout() i.e. after the Model has been updated
- if( mImpl->mEventData )
+ else if( EventData::EDITING_WITH_GRAB_HANDLE != mImpl->mEventData->mState )
{
+ // Handles & cursors must be repositioned after Relayout() i.e. after the Model has been updated
mImpl->ChangeState( EventData::EDITING );
+ }
- Event event( Event::TAP_EVENT );
- event.p1.mUint = tapCount;
- event.p2.mFloat = x;
- event.p3.mFloat = y;
- mImpl->mEventData->mEventQueue.push_back( event );
+ Event event( Event::TAP_EVENT );
+ event.p1.mUint = tapCount;
+ event.p2.mFloat = x;
+ event.p3.mFloat = y;
+ mImpl->mEventData->mEventQueue.push_back( event );
- mImpl->RequestRelayout();
- }
+ mImpl->RequestRelayout();
}
else if( !isShowingPlaceholderText &&
mImpl->mEventData->mSelectionEnabled &&
//Create the index buffer
Property::Map indexFormat;
- indexFormat["indices"] = Property::UNSIGNED_INTEGER;
+ indexFormat["indices"] = Property::INTEGER;
PropertyBuffer indexBuffer = PropertyBuffer::New( indexFormat, 6u );
indexBuffer.SetData(gQuadIndex);
{
mImpl->mStyleName = styleName;
- // Apply new style
+ // Apply new style, if stylemanager is available
Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
- GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
+ if( styleManager )
+ {
+ GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
+ }
}
}
if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
{
Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+ // if stylemanager is available
+ if( styleManager )
+ {
+ // Register for style changes
+ styleManager.StyleChangeSignal().Connect( this, &Control::OnStyleChange );
- // Register for style changes
- styleManager.StyleChangeSignal().Connect( this, &Control::OnStyleChange );
-
- // Apply the current style
- GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
+ // Apply the current style
+ GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
+ }
}
if( mImpl->mFlags & REQUIRES_KEYBOARD_NAVIGATION_SUPPORT )
void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change )
{
// By default the control is only interested in theme (not font) changes
- if( change == StyleChange::THEME_CHANGE )
+ if( styleManager && change == StyleChange::THEME_CHANGE )
{
GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
}
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 47;
+const unsigned int TOOLKIT_MICRO_VERSION = 48;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
"font-style":"Regular",
"point-size":18
},
+ "textselectionpopuplabel":
+ {
+ "point-size":18
+ },
"textselectionpopup":
{
"popup-max-size":[400,100],
- "popup-min-size":[100,65],
- "background-color":[0.0,0.0,0.0,1.0]
+ "popup-min-size":[100,65]
},
"textfield":
{
"textfield":
{
"font-family":"SamsungSans",
- "font-style":"Regular"
+ "font-style":"Regular",
"primary-cursor-color":[1.0,0.71,0.9,1.0],
"secondary-cursor-color":[1.0,0.71,0.9,1.0],
"selection-highlight-color":[0.75,0.96,1.0,1.0],
{
"point-size":10
},
+ "textselectionpopuplabel":
+ {
+ "point-size":8
+ },
"textselectionpopup":
{
"popup-max-size":[400,100],
- "popup-min-size":[100,65],
- "background-color":[0.0,0.0,0.0,1.0]
+ "popup-min-size":[100,65]
},
"scrollview":
{
--- /dev/null
+{
+ "variables": {
+ 'DALI_JS_DIR%':'../plugins/dali-script-v8/src/'
+ },
+ "targets": [
+ {
+ 'target_name': 'dali',
+ 'include_dirs': ['<(DALI_JS_DIR)/',
+ '<(DALI_JS_DIR)/utils'],
+ 'sources': [ 'dali-addon.cpp',
+ 'javascript-application-options.cpp',
+ '<(DALI_JS_DIR)/utils/v8-utils.cpp',
+ '<(DALI_JS_DIR)/dali-wrapper.cpp',
+ '<(DALI_JS_DIR)/shared/base-wrapped-object.cpp',
+ '<(DALI_JS_DIR)/shared/object-template-helper.cpp',
+ '<(DALI_JS_DIR)/actors/actor-wrapper.cpp',
+ '<(DALI_JS_DIR)/actors/actor-api.cpp',
+ '<(DALI_JS_DIR)/actors/layer-api.cpp',
+ '<(DALI_JS_DIR)/actors/image-actor-api.cpp',
+ '<(DALI_JS_DIR)/actors/camera-actor-api.cpp',
+ '<(DALI_JS_DIR)/constants/constants-wrapper.cpp',
+ '<(DALI_JS_DIR)/animation/animation-api.cpp',
+ '<(DALI_JS_DIR)/animation/animation-wrapper.cpp',
+ '<(DALI_JS_DIR)/animation/constrainer-api.cpp',
+ '<(DALI_JS_DIR)/animation/linear-constrainer-wrapper.cpp',
+ '<(DALI_JS_DIR)/animation/path-api.cpp',
+ '<(DALI_JS_DIR)/animation/path-constrainer-wrapper.cpp',
+ '<(DALI_JS_DIR)/animation/path-wrapper.cpp',
+ '<(DALI_JS_DIR)/stage/stage-wrapper.cpp',
+ '<(DALI_JS_DIR)/events/event-object-generator.cpp',
+ '<(DALI_JS_DIR)/events/pan-gesture-detector-api.cpp',
+ '<(DALI_JS_DIR)/events/pan-gesture-detector-wrapper.cpp',
+ '<(DALI_JS_DIR)/stage/stage-api.cpp',
+ '<(DALI_JS_DIR)/shader-effects/shader-effect-api.cpp',
+ '<(DALI_JS_DIR)/shader-effects/shader-effect-wrapper.cpp',
+ '<(DALI_JS_DIR)/image/image-wrapper.cpp',
+ '<(DALI_JS_DIR)/image/image-api.cpp',
+ '<(DALI_JS_DIR)/image/buffer-image-api.cpp',
+ '<(DALI_JS_DIR)/image/native-image-api.cpp',
+ '<(DALI_JS_DIR)/image/frame-buffer-image-api.cpp',
+ '<(DALI_JS_DIR)/image/resource-image-api.cpp',
+ '<(DALI_JS_DIR)/image/nine-patch-image-api.cpp',
+ '<(DALI_JS_DIR)/object/handle-wrapper.cpp',
+ '<(DALI_JS_DIR)/object/property-value-wrapper.cpp',
+ '<(DALI_JS_DIR)/signals/signal-manager.cpp',
+ '<(DALI_JS_DIR)/render-tasks/render-task-list-api.cpp',
+ '<(DALI_JS_DIR)/render-tasks/render-task-list-wrapper.cpp',
+ '<(DALI_JS_DIR)/render-tasks/render-task-api.cpp',
+ '<(DALI_JS_DIR)/render-tasks/render-task-wrapper.cpp',
+ '<(DALI_JS_DIR)/toolkit/builder/builder-api.cpp',
+ '<(DALI_JS_DIR)/toolkit/builder/builder-wrapper.cpp',
+ '<(DALI_JS_DIR)/toolkit/focus-manager/keyboard-focus-manager-api.cpp',
+ '<(DALI_JS_DIR)/toolkit/focus-manager/keyboard-focus-manager-wrapper.cpp',
+ '<(DALI_JS_DIR)/signals/dali-any-javascript-converter.cpp',
+ '<(DALI_JS_DIR)/garbage-collector/garbage-collector.cpp',
+ '<(DALI_JS_DIR)/module-loader/module.cpp',
+ '<(DALI_JS_DIR)/module-loader/module-loader.cpp'
+ ],
+ 'cflags': [
+ '-fPIC',
+ '-frtti',
+ '<!@(pkg-config --cflags dali dali-toolkit)'
+ ],
+
+ 'cflags_cc': [
+ '-fexceptions', # Enable exception handler
+ '-frtti' # needed for typeinfo with dali-any
+ ],
+ 'ldflags': [
+ '<!@(pkg-config --libs-only-L --libs-only-other dali dali-toolkit)'
+ ],
+ 'libraries': [
+ '<!@(pkg-config --libs-only-l dali dali-toolkit)'
+ ]
+ }]
+}
--- /dev/null
+# This file is generated by gyp; do not edit.
+
+export builddir_name ?= ./build/.
+.PHONY: all
+all:
+ $(MAKE) dali
--- /dev/null
+# Do not edit. File was generated by node-gyp's "configure" step
+{
+ "target_defaults": {
+ "cflags": [],
+ "default_configuration": "Release",
+ "defines": [],
+ "include_dirs": [],
+ "libraries": []
+ },
+ "variables": {
+ "clang": 0,
+ "gcc_version": 46,
+ "host_arch": "x64",
+ "icu_small": "false",
+ "node_install_npm": "true",
+ "node_prefix": "",
+ "node_shared_cares": "false",
+ "node_shared_http_parser": "false",
+ "node_shared_libuv": "false",
+ "node_shared_openssl": "false",
+ "node_shared_v8": "false",
+ "node_shared_zlib": "false",
+ "node_tag": "",
+ "node_use_dtrace": "false",
+ "node_use_etw": "false",
+ "node_use_mdb": "false",
+ "node_use_openssl": "true",
+ "node_use_perfctr": "false",
+ "openssl_no_asm": 0,
+ "python": "/usr/bin/python",
+ "target_arch": "x64",
+ "uv_library": "static_library",
+ "uv_parent_path": "/deps/uv/",
+ "uv_use_dtrace": "false",
+ "v8_enable_gdbjit": 0,
+ "v8_enable_i18n_support": 0,
+ "v8_no_strict_aliasing": 1,
+ "v8_optimized_debug": 0,
+ "v8_random_seed": 0,
+ "v8_use_snapshot": "true",
+ "want_separate_host_toolset": 0,
+ "nodedir": "/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4",
+ "copy_dev_lib": "true",
+ "standalone_static_library": 1
+ }
+}
--- /dev/null
+# This file is generated by gyp; do not edit.
+
+TOOLSET := target
+TARGET := dali
+DEFS_Debug := \
+ '-DNODE_GYP_MODULE_NAME=dali' \
+ '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-DBUILDING_NODE_EXTENSION' \
+ '-DDEBUG' \
+ '-D_DEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Debug := \
+ -fPIC \
+ -pthread \
+ -Wall \
+ -Wextra \
+ -Wno-unused-parameter \
+ -m64 \
+ -fPIC \
+ -frtti \
+ -I/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/include/dali \
+ -I/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/include \
+ -g \
+ -O0
+
+# Flags passed to only C files.
+CFLAGS_C_Debug :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := \
+ -fno-rtti \
+ -fno-exceptions \
+ -fexceptions \
+ -frtti
+
+INCS_Debug := \
+ -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/src \
+ -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/deps/uv/include \
+ -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/deps/v8/include \
+ -I$(srcdir)/../plugins/dali-script-v8/src \
+ -I$(srcdir)/../plugins/dali-script-v8/src/utils
+
+DEFS_Release := \
+ '-DNODE_GYP_MODULE_NAME=dali' \
+ '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-DBUILDING_NODE_EXTENSION'
+
+# Flags passed to all source files.
+CFLAGS_Release := \
+ -fPIC \
+ -pthread \
+ -Wall \
+ -Wextra \
+ -Wno-unused-parameter \
+ -m64 \
+ -fPIC \
+ -frtti \
+ -I/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/include/dali \
+ -I/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/include \
+ -O3 \
+ -ffunction-sections \
+ -fdata-sections \
+ -fno-tree-vrp \
+ -fno-omit-frame-pointer
+
+# Flags passed to only C files.
+CFLAGS_C_Release :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := \
+ -fno-rtti \
+ -fno-exceptions \
+ -fexceptions \
+ -frtti
+
+INCS_Release := \
+ -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/src \
+ -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/deps/uv/include \
+ -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/deps/v8/include \
+ -I$(srcdir)/../plugins/dali-script-v8/src \
+ -I$(srcdir)/../plugins/dali-script-v8/src/utils
+
+OBJS := \
+ $(obj).target/$(TARGET)/dali-addon.o \
+ $(obj).target/$(TARGET)/javascript-application-options.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/utils/v8-utils.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/dali-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/shared/base-wrapped-object.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/shared/object-template-helper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/actor-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/actor-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/layer-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/image-actor-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/camera-actor-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/constants/constants-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/animation-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/animation-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/constrainer-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/linear-constrainer-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/path-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/path-constrainer-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/path-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/stage/stage-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/events/event-object-generator.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/events/pan-gesture-detector-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/events/pan-gesture-detector-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/stage/stage-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/shader-effects/shader-effect-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/shader-effects/shader-effect-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/image-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/image-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/buffer-image-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/native-image-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/frame-buffer-image-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/resource-image-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/nine-patch-image-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/object/handle-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/object/property-value-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/signals/signal-manager.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/render-tasks/render-task-list-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/render-tasks/render-task-list-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/render-tasks/render-task-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/render-tasks/render-task-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/toolkit/builder/builder-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/toolkit/builder/builder-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/toolkit/focus-manager/keyboard-focus-manager-api.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/toolkit/focus-manager/keyboard-focus-manager-wrapper.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/signals/dali-any-javascript-converter.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/garbage-collector/garbage-collector.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/module-loader/module.o \
+ $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/module-loader/module-loader.o
+
+# Add to the list of files we specially track dependencies for.
+all_deps += $(OBJS)
+
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.
+$(OBJS): TOOLSET := $(TOOLSET)
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+
+# Suffix rules, putting all outputs into $(obj).
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+
+# Try building from generated source, too.
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+
+# End of this set of suffix rules
+### Rules for final target.
+LDFLAGS_Debug := \
+ -pthread \
+ -rdynamic \
+ -m64 \
+ -L/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/lib
+
+LDFLAGS_Release := \
+ -pthread \
+ -rdynamic \
+ -m64 \
+ -L/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/lib
+
+LIBS := \
+ -ldali-adaptor \
+ -ldali-toolkit \
+ -ldali-core
+
+$(obj).target/dali.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
+$(obj).target/dali.node: LIBS := $(LIBS)
+$(obj).target/dali.node: TOOLSET := $(TOOLSET)
+$(obj).target/dali.node: $(OBJS) FORCE_DO_CMD
+ $(call do_cmd,solink_module)
+
+all_deps += $(obj).target/dali.node
+# Add target alias
+.PHONY: dali
+dali: $(builddir)/dali.node
+
+# Copy this to the executable output path.
+$(builddir)/dali.node: TOOLSET := $(TOOLSET)
+$(builddir)/dali.node: $(obj).target/dali.node FORCE_DO_CMD
+ $(call do_cmd,copy)
+
+all_deps += $(builddir)/dali.node
+# Short alias for building this executable.
+.PHONY: dali.node
+dali.node: $(obj).target/dali.node $(builddir)/dali.node
+
+# Add executable to "all" target.
+.PHONY: all
+all: $(builddir)/dali.node
+
--- /dev/null
+/* Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <node.h>
+#include <public-api/dali-core.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <integration-api/core.h>
+#include <integration-api/adaptors/adaptor.h>
+#include <public-api/adaptor-framework/window.h>
+#include <devel-api/adaptor-framework/singleton-service.h>
+
+// INTERNAL INCLUDES
+#include <dali-wrapper.h>
+#include "javascript-application-options.h"
+
+using namespace Dali;
+
+namespace DaliNodeAddon
+{
+
+class DaliApplication
+{
+public:
+
+ DaliApplication()
+ : mInitialized( false),
+ mSingletonService(SingletonService::New()),
+ mAdaptor( NULL )
+ {
+ }
+
+ ~DaliApplication()
+ {
+ mSingletonService.UnregisterAll();
+ delete mAdaptor;
+ mWindow.Reset();
+ }
+
+ bool Initialized() const
+ {
+ return mInitialized;
+ }
+
+ void Initialize( ApplicationOptions options )
+ {
+ if( mInitialized )
+ {
+ return;
+ }
+
+ // 1. Create the window ( adaptor requires a window)
+ const WindowOptions& window( options.window);
+
+ mWindow = Window::New( window.positionSize, window.name, window.transparent );
+
+ // 2. create the adaptor
+ Adaptor* adaptor = &Adaptor::New( mWindow );
+
+ // 3. start the adaptor
+ adaptor->Start();
+
+ // Set the view modes
+
+ if( options.stereo.viewMode > Dali::MONO )
+ {
+ adaptor->SetStereoBase( options.stereo.stereoBase );
+ adaptor->SetViewMode( options.stereo.viewMode );
+ }
+
+ // fire the scene create signal
+ adaptor->SceneCreated();
+
+ mInitialized = true;
+ }
+private:
+
+ bool mInitialized;
+ SingletonService mSingletonService;
+ Adaptor* mAdaptor;
+ Window mWindow;
+
+};
+
+DaliApplication app;
+
+void CreateDali(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ ApplicationOptions options;
+
+ bool ok = GetApplicationOptions( args, options);
+ if (!ok )
+ {
+ isolate->ThrowException( v8::Exception::TypeError( v8::String::NewFromUtf8(isolate, "Please check arguments passed to DALi require") ) );
+ return;
+ }
+
+ app.Initialize( options );
+
+ // the return value from calling the function require('dali.js)( options )
+ // is the dali object
+ args.GetReturnValue().Set( V8Plugin::DaliWrapper::CreateWrapperForNodeJS( isolate ) );
+}
+
+
+/**
+ * We make module.exports a function so that the developer can pass to
+ * parameters to DALi when it's 'required'
+ * E.g
+ *
+ *
+ * var window= {
+ * x:10,
+ * y:10,
+ * width:800,
+ * height: 600,
+ * transparent: false,
+ * name:'my-first-dali-app'
+ * };
+ *
+ * var viewMode {
+ * 'stereoscopic-mode':'stereo-vertical', // mono, stereo-horizontal, stereo-vertical, stereo-interlaced,
+ * 'stereo-base': 65 // Distance in millimeters between left/right cameras typically between (50-70mm)
+ * };
+ *
+ * var options= {
+ * 'window': window,
+ * 'view-mode': viewMode,
+ * 'style-sheet': 'my-theme.json'
+ * }
+ *
+ * var dali = require('dali.js')( options )
+ *
+ *
+ */
+void ExportDaliModule(v8::Handle<v8::Object> exports, v8::Handle<v8::Object> module)
+{
+ NODE_SET_METHOD(module, "exports", CreateDali);
+}
+
+} // namespace DaliNodeAddon
+
+NODE_MODULE(dali, DaliNodeAddon::ExportDaliModule)
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// HEADER
+#include "javascript-application-options.h"
+
+// EXTERNAL INCLUDES
+#include <cstring>
+
+// INTERNAL INCLUDES
+#include <v8-utils.h>
+
+namespace DaliNodeAddon
+{
+
+namespace
+{
+
+struct StereoInfo
+{
+ const char* const name;
+ Dali::ViewMode mode;
+};
+StereoInfo StereoModeTable[] = {
+ { "mono", Dali::MONO},
+ { "stereo-horizontal", Dali::STEREO_HORIZONTAL },
+ { "stereo-vertical", Dali::STEREO_VERTICAL },
+ { "stereo-interlaced", Dali::STEREO_INTERLACED },
+};
+
+const unsigned int numberViewModes = sizeof( StereoModeTable ) / sizeof( StereoModeTable[0] );
+
+bool GetViewMode( const std::string& modeString, Dali::ViewMode& mode )
+{
+ for( unsigned int i = 0; i < numberViewModes; ++i )
+ {
+ const StereoInfo& info (StereoModeTable[i]);
+
+ if( strcmp ( modeString.c_str() , info.name ) == 0 )
+ {
+ mode = info.mode;
+ return true;
+ }
+ }
+ // mode not found
+ mode = Dali::MONO;
+ return false;
+}
+
+
+// Note we can't parse the enviroment options for window width / height because
+// adaptor which holds the environment option class has not been created
+// and we can't create it, until we have a window
+bool ParseWindowOptions( v8::Isolate* isolate, const v8::Local<v8::Object>& obj, WindowOptions& window )
+{
+ v8::HandleScope scope(isolate);
+
+ v8::Local<v8::Value> xValue = obj->Get( v8::String::NewFromUtf8( isolate, "x" ) );
+ v8::Local<v8::Value> yValue = obj->Get( v8::String::NewFromUtf8( isolate, "y" ) );
+ v8::Local<v8::Value> widthValue = obj->Get( v8::String::NewFromUtf8( isolate, "width" ) );
+ v8::Local<v8::Value> heightValue = obj->Get( v8::String::NewFromUtf8( isolate, "height" ) );
+ v8::Local<v8::Value> nameValue = obj->Get( v8::String::NewFromUtf8( isolate, "name" ) );
+ v8::Local<v8::Value> transparencyValue = obj->Get( v8::String::NewFromUtf8( isolate, "transparent" ) );
+
+ // if x,y are optional
+ if( xValue->IsUint32() )
+ {
+ window.positionSize.x = xValue->ToUint32()->Value();
+ }
+ if( yValue->IsUint32() )
+ {
+ window.positionSize.y = yValue->ToUint32()->Value();
+ }
+
+ // width and height are optional but will only accept them if they are both set
+ if( widthValue->IsUint32() && heightValue->IsUint32() )
+ {
+ window.positionSize.width = widthValue->ToUint32()->Value();
+ window.positionSize.height = heightValue->ToUint32()->Value();
+ }
+
+ // get the window name
+ if( nameValue->IsString() )
+ {
+ window.name = Dali::V8Plugin::V8Utils::v8StringToStdString( nameValue );
+ }
+ else
+ {
+ window.name ="DALi application";
+ }
+
+ if( transparencyValue->IsBoolean() )
+ {
+ window.transparent = transparencyValue->ToBoolean()->Value();
+ }
+ return true;
+}
+
+bool ParseStereoScopicOptions( v8::Isolate* isolate, const v8::Local<v8::Object>& stereoObject, StereoScopicOptions& options )
+{
+ v8::HandleScope scope(isolate);
+
+ v8::Local<v8::Value> modeValue = stereoObject->Get( v8::String::NewFromUtf8( isolate, "stereoscopic-mode" ) );
+ v8::Local<v8::Value> stereoBaseValue = stereoObject->Get( v8::String::NewFromUtf8( isolate, "stereo-base" ) );
+
+ if( !modeValue->IsString() )
+ {
+ return true;
+ }
+
+ std::string mode = Dali::V8Plugin::V8Utils::v8StringToStdString( modeValue );
+ bool ok = GetViewMode( mode, options.viewMode);
+ if( !ok )
+ {
+ return false;
+ }
+ if( stereoBaseValue->IsNumber() )
+ {
+ options.stereoBase = stereoBaseValue->ToNumber()->Value();
+ }
+
+ return true;
+}
+
+} // unnamed namespace
+
+bool GetApplicationOptions(const v8::FunctionCallbackInfo<v8::Value>& args, ApplicationOptions& options )
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::HandleScope scope(isolate);
+ bool ok( false );
+
+ if( !args[ 0 ]->IsObject() )
+ {
+ return false;
+ }
+
+ v8::Local<v8::Object> object = args[ 0 ]->ToObject();
+
+ // get the window settings
+ v8::Local<v8::Value> windowValue= object->Get( v8::String::NewFromUtf8( isolate, "window" ) );
+ if( windowValue->IsObject() )
+ {
+ ok = ParseWindowOptions( isolate, windowValue->ToObject(), options.window );
+ if( !ok )
+ {
+ return false; // missing window size
+ }
+ }
+
+ // get the stereoscopic settings
+ v8::Local<v8::Value> stereoValue= object->Get( v8::String::NewFromUtf8( isolate, "view-mode" ) );
+ if( stereoValue->IsObject() )
+ {
+ ok = ParseStereoScopicOptions( isolate, stereoValue->ToObject(), options.stereo );
+ if( !ok )
+ {
+ return false; // incorrect stereoscopic mode
+ }
+ }
+
+ // get the style sheet
+ v8::Local<v8::Value> stylesheetValue= object->Get( v8::String::NewFromUtf8( isolate, "style-sheet" ) );
+ if( stylesheetValue->IsString() )
+ {
+ options.stylesheet = Dali::V8Plugin::V8Utils::v8StringToStdString( stylesheetValue );
+ }
+
+ return true;
+}
+
+} // namespace DaliNodeAddon
--- /dev/null
+#ifndef __DALI_JAVASCRIPT_APPLICATION_OPTIONS_H__
+#define __DALI_JAVASCRIPT_APPLICATION_OPTIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <public-api/dali-core.h>
+#include <public-api/adaptor-framework/window.h>
+#include <v8.h>
+
+namespace DaliNodeAddon
+{
+
+struct WindowOptions
+{
+ WindowOptions()
+ : positionSize(0,0,0,0)
+ {
+ }
+
+ std::string name;
+ Dali::PositionSize positionSize;
+ bool transparent:1;
+};
+
+struct StereoScopicOptions
+{
+ StereoScopicOptions()
+ : viewMode(Dali::MONO),
+ stereoBase(65.f)
+ {
+ }
+
+ Dali::ViewMode viewMode;
+ float stereoBase;
+};
+
+struct ApplicationOptions
+{
+ WindowOptions window;
+ StereoScopicOptions stereo;
+ std::string stylesheet;
+};
+
+/**
+ * @brief parse the dali JavaScript application options
+ * The options are passed to dali when require is called.
+ * E.g. var dali.require('dali.js)( {options object} )
+ *
+ * @param[in] args JavaScript arguments
+ * @param[out] options assigned Dali options
+ * @return true on success, false on failure
+ *
+ */
+bool GetApplicationOptions( const v8::FunctionCallbackInfo<v8::Value>& args, ApplicationOptions& options );
+
+
+} // namespace DaliNodeAddon
+
+
+
+#endif // __DALI_JAVASCRIPT_APPLICATION_OPTIONS_H__
--- /dev/null
+{
+ "name": "dali",
+ "version": "0.0.0",
+ "description": "DALi 3D Engine addon",
+ "main": "index.js",
+ "gypfile": "true",
+ "scripts": {
+ "preinstall" : "./configure",
+ "install" : "make && make install",
+ "test" : "node test.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "review.tizen.org:29418/platform/core/uifw/dali-core"
+ },
+ "keywords": [
+ "dali",
+ "3D",
+ "engine",
+ "OpenGL",
+ "user interface"
+ ],
+ "author": "Samsung",
+ "license": "http://www.apache.org/licenses/LICENSE-2.0"
+}
--- /dev/null
+ var window= {
+ x:800,
+ y:500,
+ width:880,
+ height: 1020,
+ transparent: false,
+ name:'my-first-dali-app'
+ };
+var viewMode={
+ 'stereoscopic-mode':'mono', // stereo-horizontal, stereo-vertical, stereo-interlaced,
+ 'stereo-base': 65 // Distance in millimeters between left/right cameras typically between (50-70mm)
+ };
+ var options= {
+ 'window': window,
+ 'view-mode': viewMode,
+ }
+
+var dali = require('./build/Release/dali')( options );
+var netflixRoulette = require('netflix-roulette');
+
+
+var NUMBER_OF_IMAGES = 40; // for now use 16 ( demo files go up to 30)
+var DEMO_IMAGES = []; // array to store Dali Images
+var VIDEO_WALL_ACTORS = []; // array to store Image actors
+var VIDEO_WALL_ROWS = 5; // use 3 rows for the video wall
+var VIDEO_WALL_COLUMNS = 6; // use 12 columns for the video wall
+var VIDEO_WALL_TOTAL_ITEMS = VIDEO_WALL_COLUMNS * VIDEO_WALL_ROWS; // total items
+var VIDEO_WALL_ITEM_SIZE = 128; // width / height of a item in the video wall
+var BORDER_SIZE = 5;
+var VIDEO_WALL_ITEM_SIZE_NO_BORDER = VIDEO_WALL_ITEM_SIZE - BORDER_SIZE;
+var VIDEO_WALL_WIDTH = VIDEO_WALL_COLUMNS * VIDEO_WALL_ITEM_SIZE;
+var VIDEO_WALL_HEIGHT = VIDEO_WALL_ROWS * VIDEO_WALL_ITEM_SIZE;
+var daliApp = {};
+var posters = [];
+
+var wallRootActor; // the root actor of the video wall
+
+
+daliApp.loadNetflixImages = function() {
+
+ if( NUMBER_OF_IMAGES >= VIDEO_WALL_TOTAL_ITEMS)
+ {
+ NUMBER_OF_IMAGES = VIDEO_WALL_TOTAL_ITEMS-1;
+ }
+
+ for (index = 0; index < NUMBER_OF_IMAGES; ++index) {
+
+ fileName = posters[ index % (posters.length-1) ];
+ if ( fileName )
+ {
+ DEMO_IMAGES[index] = new dali.ResourceImage( { url:fileName } );
+ }
+ }
+}
+
+
+daliApp.createRootActor = function() {
+ wallRootActor = new dali.Actor();
+ wallRootActor.parentOrigin = dali.CENTER;
+ wallRootActor.anchorPoint = dali.CENTER;
+ dali.stage.add(wallRootActor);
+
+ var field = new dali.Control("TextField");
+ field.parentOrigin = dali.CENTER;
+ field.anchorPoint = dali.CENTER;
+
+ field.placeholderText = "DALi netflix netflix-roulette demo";
+ dali.stage.add( field );
+}
+
+
+
+daliApp.getWallActorIndex = function(x, y) {
+ return x + y * VIDEO_WALL_COLUMNS;
+}
+
+daliApp.createActors = function() {
+ daliApp.createRootActor();
+
+ var anim = new dali.Animation(1);
+ var animOptions = {
+ alpha: "linear",
+ delay: 0.0, // used to delay the start of the animation
+ duration: 1, // duration of the animation
+ };
+
+ for (y = 0; y < VIDEO_WALL_ROWS; ++y) {
+ for (x = 0; x < VIDEO_WALL_COLUMNS; ++x) {
+
+ var actorIndex = daliApp.getWallActorIndex(x, y);
+ var imageActor = new dali.ImageActor();
+
+ // wrap image index between 0 and NUMBER_OF_IMAGES
+ var imageIndex = actorIndex % NUMBER_OF_IMAGES;
+
+ imageActor.setImage(DEMO_IMAGES[imageIndex]);
+
+ imageActor.parentOrigin = dali.CENTER;
+ imageActor.anchorPoint = dali.CENTER;
+ imageActor.size = [VIDEO_WALL_ITEM_SIZE_NO_BORDER, VIDEO_WALL_ITEM_SIZE_NO_BORDER, 1.0]; // start with zero size so it zooms up
+
+ var xPosition = x * VIDEO_WALL_ITEM_SIZE;
+ // as the middle the wall is at zero (relative to wallRootActor), we need to subtract half the wall width.
+ // + add half item size because the item anchor point is the center of the wallRootActor.
+ xPosition = xPosition - (VIDEO_WALL_WIDTH / 2) + (VIDEO_WALL_ITEM_SIZE / 2);
+
+ var yPosition = y * VIDEO_WALL_ITEM_SIZE;
+ yPosition = yPosition - (VIDEO_WALL_HEIGHT / 2) + (VIDEO_WALL_ITEM_SIZE / 2);
+
+ imageActor.position = [0,0,0];
+
+ animOptions.delay+=0.25;
+ anim.animateTo( imageActor,"position",[xPosition, yPosition, 0.0],animOptions);
+ // store the actor
+ VIDEO_WALL_ACTORS[actorIndex] = imageActor;
+
+ // Add to the video wall root actor.
+ wallRootActor.add(imageActor);
+ }
+ }
+ anim.play();
+}
+
+function Initialise() {
+
+ daliApp.loadNetflixImages();
+
+ daliApp.createActors();
+}
+
+function actorLoaded( error, data )
+{
+ for( i = 0; i < data.length; ++i )
+ {
+ var entry = data[i];
+
+ if( entry.poster )
+ {
+ posters.push(entry.poster);
+ //console.log(" entry = " + entry.poster );
+ }
+ }
+ Initialise();
+
+}
+
+
+netflixRoulette.actor('nicolas', actorLoaded );
+
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.0.47
+Version: 1.0.48
Release: 1
Group: System/Libraries
License: Apache-2.0
BuildRequires: pkgconfig(dali)
BuildRequires: pkgconfig(dali-core)
+#############################
+# profile setup
+#############################
+
+%define dali_toolkit_profile MOBILE
+
+# Further resource locations profiles can be provided here otherwise MOBILE will be used
+%if "%{tizen_profile_name}" == "mobile"
+ %define dali_toolkit_profile MOBILE
+%endif
+
%description
The OpenGLES Canvas Core Library Toolkit - a set of controls that provide
user interface functionality.
autoreconf --install
DALI_DATA_RW_DIR="%{dali_data_rw_dir}" ; export DALI_DATA_RW_DIR
DALI_DATA_RO_DIR="%{dali_data_ro_dir}" ; export DALI_DATA_RO_DIR
-%configure
+%configure --enable-profile=%{dali_toolkit_profile}
make %{?jobs:-j%jobs}
##############################
v8::Persistent<v8::ObjectTemplate> ActorWrapper::mImageActorTemplate;
v8::Persistent<v8::ObjectTemplate> ActorWrapper::mCameraActorTemplate;
v8::Persistent<v8::ObjectTemplate> ActorWrapper::mLayerActorTemplate;
-v8::Persistent<v8::ObjectTemplate> ActorWrapper::mTextLabelTemplate;
namespace
{
{ &ActorWrapper::mActorTemplate }, // ACTOR
{ &ActorWrapper::mImageActorTemplate }, // IMAGE_ACTOR
{ &ActorWrapper::mLayerActorTemplate }, // LAYER_ACTOR
- { &ActorWrapper::mCameraActorTemplate}, // CAMERA_ACTOR
- { &ActorWrapper::mTextLabelTemplate }
+ { &ActorWrapper::mCameraActorTemplate} // CAMERA_ACTOR
};
/**
/**
* Lookup table to match a actor type with a constructor and supported API's.
+ * HandleWrapper::ActorType is used to index this table
*/
const ActorApiStruct ActorApiLookup[]=
{
{"ImageActor", ActorWrapper::IMAGE_ACTOR, ImageActorApi::New, ACTOR_API | IMAGE_ACTOR_API },
{"Layer", ActorWrapper::LAYER_ACTOR, LayerApi::New, ACTOR_API | LAYER_API },
{"CameraActor",ActorWrapper::CAMERA_ACTOR, CameraActorApi::New, ACTOR_API | CAMERA_ACTOR_API },
- {"TextLabel", ActorWrapper::TEXT_LABEL, TextLabelApi::New, ACTOR_API },
-
};
const unsigned int ActorApiLookupCount = sizeof(ActorApiLookup)/sizeof(ActorApiLookup[0]);
// if we don't currently support the actor type, then use type registry to create it
if( actorType == ActorWrapper::UNKNOWN_ACTOR )
{
- Dali::TypeInfo typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( typeName );
- if( typeInfo ) // handle, check if it has a value
- {
- Dali::BaseHandle handle = typeInfo.CreateInstance();
- if( handle )
- {
- actor = Actor::DownCast( handle );
- }
- }
- else
- {
- DALI_SCRIPT_EXCEPTION(args.GetIsolate(),"Unknown actor type");
+ DALI_SCRIPT_EXCEPTION( args.GetIsolate(), "Unknown actor type" );
return Actor();
- }
}
else
{
args.GetReturnValue().Set( localObject );
}
+void ActorWrapper::NewControl( const v8::FunctionCallbackInfo< v8::Value >& args)
+{
+ v8::Isolate* isolate = args.GetIsolate();
+ v8::HandleScope handleScope( isolate );
+
+ if( !args.IsConstructCall() )
+ {
+ DALI_SCRIPT_EXCEPTION( isolate, "constructor called without 'new" );
+ return;
+ }
+
+ bool found( false );
+ std::string controlName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
+
+ if( !found )
+ {
+ DALI_SCRIPT_EXCEPTION( isolate, "missing control name" );
+ return;
+ }
+ Actor control;
+ Dali::TypeInfo typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( controlName );
+ if( typeInfo ) // handle, check if it has a value
+ {
+ Dali::BaseHandle handle = typeInfo.CreateInstance();
+ if( handle )
+ {
+ control = Actor::DownCast( handle );
+ }
+ }
+
+ v8::Local<v8::Object> localObject = WrapActor( isolate, control, ACTOR );
+
+ args.GetReturnValue().Set( localObject );
+}
+
+
/**
* given an actor type name, e.g. ImageActor returns the type, e.g. ActorWrapper::IMAGE_ACTOR
*/
public:
/**
- * Actor type used an index
+ * Actor type used an index.
+ * These enums are used to index the ActorApiLookup table in actor-wrapper.cpp.
+ * Any changes made must be reflected in the ActorApiLookup otherwise it may segfault when creating an actor
*/
enum ActorType
{
UNKNOWN_ACTOR = -1,
- ACTOR = 0,
- IMAGE_ACTOR =1,
- MESH_ACTOR =2,
- LAYER_ACTOR =3,
- CAMERA_ACTOR =4,
- TEXT_LABEL =5
+ ACTOR = 0,
+ IMAGE_ACTOR = 1,
+ LAYER_ACTOR = 2,
+ CAMERA_ACTOR = 3
};
/**
static void NewActor( const v8::FunctionCallbackInfo< v8::Value >& args);
/**
+ * @brief Creates a new Control wrapped inside a Javascript Object.
+ * @note: the control type is passed as a parameter e.g. 'TextField'
+ * @param[in] args v8 function call arguments interpreted
+ */
+ static void NewControl( const v8::FunctionCallbackInfo< v8::Value >& args);
+
+ /**
* @brief Wraps an actor of a given type
*/
static v8::Handle<v8::Object> WrapActor(v8::Isolate* isolate, Dali::Actor actor,ActorType actorType);
// The Actor ObjectTemplates.
static v8::Persistent<v8::ObjectTemplate> mActorTemplate;
static v8::Persistent<v8::ObjectTemplate> mImageActorTemplate;
- static v8::Persistent<v8::ObjectTemplate> mMeshActorTemplate;
static v8::Persistent<v8::ObjectTemplate> mCameraActorTemplate;
static v8::Persistent<v8::ObjectTemplate> mLayerActorTemplate;
- static v8::Persistent<v8::ObjectTemplate> mTextLabelTemplate;
/**
* @return the wrapped actor
{ "MeshActor", ActorWrapper::NewActor },
{ "CameraActor", ActorWrapper::NewActor },
{ "Layer", ActorWrapper::NewActor },
- { "TextView", ActorWrapper::NewActor },
+ { "Control", ActorWrapper::NewControl },
{ "ResourceImage", ImageWrapper::NewImage },
{ "BufferImage", ImageWrapper::NewImage },
{ "NinePatchImage", ImageWrapper::NewImage },
bool DaliWrapper::mInstanceCreated = false;
DaliWrapper* DaliWrapper::mWrapper = NULL;
-DaliWrapper::DaliWrapper()
-:mIsolate( NULL )
+DaliWrapper::DaliWrapper( RunMode runMode, v8::Isolate* isolate )
+:mIsolate( isolate ),
+ mRunMode(runMode)
{
}
DaliWrapper& DaliWrapper::Get()
{
- if(!mInstanceCreated)
+ if( !mInstanceCreated )
{
- mWrapper = new DaliWrapper();
+ mWrapper = new DaliWrapper( RUNNING_STANDALONE, NULL );
+
mInstanceCreated = true;
- if(mWrapper)
- {
- mWrapper->Initialize();
- }
- }
+ mWrapper->InitializeStandAlone();
+ }
return *mWrapper;
}
+v8::Local<v8::Object> DaliWrapper::CreateWrapperForNodeJS( v8::Isolate* isolate )
+{
+ v8::EscapableHandleScope handleScope( isolate);
+
+ mInstanceCreated = true;
+
+ mWrapper = new DaliWrapper( RUNNING_IN_NODE_JS, isolate );
+
+ v8::Local<v8::Object> dali = mWrapper->CreateDaliObject();
+
+ // As we running inside node, we already have an isolate and context
+ return handleScope.Escape( dali );
+}
+
+v8::Local<v8::Object> DaliWrapper::CreateDaliObject()
+{
+ v8::EscapableHandleScope handleScope( mIsolate );
+
+ // Create dali object used for creating objects, and accessing constant values
+ // e.g. var x = new dali.Actor(), or var col = dali.COLOR_RED;
+
+ v8::Local<v8::ObjectTemplate> daliObjectTemplate = NewDaliObjectTemplate( mIsolate );
+
+ // add dali.staqe
+ v8::Local<v8::Object> stageObject = StageWrapper::WrapStage( mIsolate, Stage::GetCurrent() );
+ daliObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "stage") , stageObject );
+
+ v8::Local<v8::Object> keyboardObject = KeyboardFocusManagerWrapper::WrapKeyboardFocusManager( mIsolate,Toolkit::KeyboardFocusManager::Get() );
+ daliObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "keyboardFocusManager") , keyboardObject );
+
+
+ //create an instance of the template
+ v8::Local<v8::Object> daliObject = daliObjectTemplate->NewInstance();
+
+ ConstantsWrapper::AddDaliConstants( mIsolate, daliObject);
+
+ daliObject->Set( v8::String::NewFromUtf8( mIsolate, "V8_VERSION") ,v8::String::NewFromUtf8( mIsolate, v8::V8::GetVersion() ));
+
+ return handleScope.Escape( daliObject );
+}
+
+
void DaliWrapper::SetFlagsFromString(const std::string &flags)
{
v8::V8::SetFlagsFromString(flags.c_str(), flags.size());
void DaliWrapper::Shutdown()
{
+ // if we're running inside node then we don't have ownership of the context
+ if( mRunMode == RUNNING_IN_NODE_JS )
+ {
+ return;
+ }
+
DALI_LOG_WARNING("Destroying V8 DALi context\n");
if( !mContext.IsEmpty())
return mGarbageCollector;
}
-void DaliWrapper::CreateContext( )
+void DaliWrapper::ApplyGlobalObjectsToContext( v8::Local<v8::Context> context )
{
v8::HandleScope handleScope( mIsolate );
- // Create a global JavaScript object so we can set built-in global functions, like Log.
- v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New( mIsolate );
+ // Add global objects ( functions/ values ) e.g. log function
+ // create a console.log and console.error functions
+ v8::Local<v8::ObjectTemplate> consoleObjectTemplate = v8::ObjectTemplate::New( mIsolate );
+ consoleObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "log"), v8::FunctionTemplate::New( mIsolate, V8Utils::Log));
+ consoleObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "error"), v8::FunctionTemplate::New( mIsolate, V8Utils::LogError));
- // Add global objects ( functions/ values ) e.g. log function and V8_VERSION
- global->Set( v8::String::NewFromUtf8( mIsolate, "log"), v8::FunctionTemplate::New( mIsolate, V8Utils::Log) );
- global->Set( v8::String::NewFromUtf8( mIsolate, "logError"), v8::FunctionTemplate::New( mIsolate, V8Utils::LogError) );
- global->Set( v8::String::NewFromUtf8( mIsolate, "require"), v8::FunctionTemplate::New( mIsolate, DaliWrapper::Require));
- global->Set( v8::String::NewFromUtf8( mIsolate, "V8_VERSION") ,v8::String::NewFromUtf8( mIsolate, v8::V8::GetVersion() ));
+ context->Global()->Set( v8::String::NewFromUtf8( mIsolate, "console"), consoleObjectTemplate->NewInstance() );
- // add the dali object to it, assume it won't be garbage collected until global is deleted
- global->Set(v8::String::NewFromUtf8( mIsolate, DALI_API_NAME) , NewDaliObjectTemplate( mIsolate ));
+ // add require functionality
+ context->Global()->Set( v8::String::NewFromUtf8( mIsolate, "require"), v8::FunctionTemplate::New( mIsolate, DaliWrapper::Require)->GetFunction());
+ // Create the Dali object
+ // @todo consider forcing developers to perform require('dali') if we want to avoid polluting the global namespace
+ v8::Local<v8::Object> daliObject = CreateDaliObject();
- // create a new context.
- // Isolate = isolated copy of the V8 including a heap manager, a garbage collector
- // Only 1 thread can access a single Isolate at a given time. However, multiple Isolates can be run in parallel.
- // Context = multiple contexts can exist in a given Isolate, and share data between contexts
- v8::Handle<v8::Context> context = v8::Context::New( mIsolate, NULL, global);
+ // allow developers to require('dali'); // this is to maintain compatibility with node.js where dali is not part of the global namespace
+ mModuleLoader.StorePreBuiltModule( mIsolate, daliObject, DALI_API_NAME );
- mGlobalObjectTemplate.Reset( mIsolate, global);
+ context->Global()->Set( v8::String::NewFromUtf8( mIsolate, DALI_API_NAME),daliObject );
- mContext.Reset( mIsolate, context);
}
-void DaliWrapper::Initialize()
+void DaliWrapper::InitializeStandAlone()
{
if( !mIsolate )
{
// default isolate removed from V8 version 3.27.1 and beyond.
mIsolate = v8::Isolate::New();
+
mIsolate->Enter();
v8::V8::SetFatalErrorHandler( FatalErrorCallback );
-
}
+
// if context is null, create it and add dali object to the global object.
if( mContext.IsEmpty())
{
v8::HandleScope handleScope( mIsolate );
- CreateContext();
- v8::Local<v8::Context> context = v8::Local<v8::Context>::New(mIsolate, mContext);
-
- context->Enter();
- // Add the dali global object. Used for creating objects, and accessing constant values
- // e.g. var x = new dali.ImageActor(), or var col = dali.COLOR_RED;
+ // create a new context.
+ // Isolate = isolated copy of the V8 including a heap manager, a garbage collector
+ // Only 1 thread can access a single Isolate at a given time. However, multiple Isolates can be run in parallel.
+ // Context = multiple contexts can exist in a given Isolate, and share data between contexts
+ v8::Local<v8::Context> context = v8::Context::New( mIsolate );
- v8::Local<v8::Object> daliObject = v8::Local<v8::Object>::Cast( context->Global()->Get( v8::String::NewFromUtf8( mIsolate, DALI_API_NAME)));
-
- v8::Local<v8::Object> stageObject = StageWrapper::WrapStage( mIsolate, Stage::GetCurrent() );
- daliObject->Set( v8::String::NewFromUtf8( mIsolate, "stage") , stageObject );
-
- // keyboard focus manager is a singleton
- v8::Local<v8::Object> keyboardObject = KeyboardFocusManagerWrapper::WrapKeyboardFocusManager( mIsolate,Toolkit::KeyboardFocusManager::Get() );
- daliObject->Set( v8::String::NewFromUtf8( mIsolate, "keyboardFocusManager") , keyboardObject );
+ context->Enter();
- ConstantsWrapper::AddDaliConstants( mIsolate, daliObject);
+ // Apply global objects like dali and console to the context
+ ApplyGlobalObjectsToContext(context);
+ mContext.Reset( mIsolate, context);
}
+
DALI_LOG_INFO( gLogExecuteFilter, Debug::Verbose, "V8 Library %s loaded \n", v8::V8::GetVersion() );
}
+
v8::Handle<v8::ObjectTemplate> DaliWrapper::NewDaliObjectTemplate( v8::Isolate* isolate )
{
v8::EscapableHandleScope handleScope( isolate );
objTemplate->Set( v8::String::NewFromUtf8( isolate, "BUILD"),
v8::String::NewFromUtf8( isolate, "Dali binary built on:" __DATE__ ", at " __TIME__));
-
+#ifdef DALI_DATA_READ_ONLY_DIR
// add the data data directory,
objTemplate->Set( v8::String::NewFromUtf8( isolate, "DALI_DATA_DIRECTORY"),
- v8::String::NewFromUtf8( isolate, DALI_DATA_READ_ONLY_DIR));
-
+ v8::String::NewFromUtf8( isolate, DALI_DATA_READ_ONLY_DIR));
+#endif
// add our constructor functions
ObjectTemplateHelper::InstallFunctions( isolate,
objTemplate,
void DaliWrapper::Require(const v8::FunctionCallbackInfo< v8::Value >& args)
{
DaliWrapper& wrapper( DaliWrapper::Get() );
- wrapper.mModuleLoader.Require( args, wrapper.mGlobalObjectTemplate );
+ wrapper.mModuleLoader.Require( args );
}
-
-
} // namespace V8Plugin
} // namespace Dali
// INTERNAL INCLUDES
#include <garbage-collector/garbage-collector.h>
+
#include <module-loader/module-loader.h>
namespace Dali
*/
class DALI_INTERNAL DaliWrapper
{
+
public:
/**
- * Constructor
+ * @brief whether the wrapper is running in standalone using V8,
+ * or inside Node.JS using V8
*/
- DaliWrapper();
+ enum RunMode
+ {
+ RUNNING_STANDALONE,
+ RUNNING_IN_NODE_JS
+ };
+
+ /**
+ * @brief Constructor
+ * @param[in] runMode whether the wrapper is running standalone or inside Node.JS
+ * @param[in] isolate v8 isolate ( can be null if running standalone )
+ */
+ DaliWrapper( RunMode runMode, v8::Isolate* isolate );
/**
* non virtual destructor, not intended as a base class
static DaliWrapper& Get();
/**
+ * Intialize DaliWrapper for running inside NodeJS
+ */
+ static v8::Local<v8::Object> CreateWrapperForNodeJS( v8::Isolate* isolate);
+
+
+ /**
* Set V8 engine configuration flags
*
* @param[in] flags Configruation flags (See v8 documentation)
private:
/**
- * Create V8 context
+ * @brief Apply global objects like console.log and require() to the context
*/
- void CreateContext();
+ void ApplyGlobalObjectsToContext( v8::Local<v8::Context> context );
/**
- * Initialize DaliWrapper
+ * @brief Initialize DaliWrapper for running standalone
+ * Creates a new isolate
+ *
*/
- void Initialize();
+ void InitializeStandAlone();
+
+ /**
+ * @brief create dali namespace/object
+ */
+ v8::Local<v8::Object> CreateDaliObject();
/**
* Create Dali ObjectTemplate
GarbageCollector mGarbageCollector; ///< DALi garbage collector
ModuleLoader mModuleLoader; ///< Module loader
v8::Persistent<v8::Context> mContext; ///< A sandboxed execution context with its own set of built-in objects and functions.
- v8::Persistent<v8::ObjectTemplate> mGlobalObjectTemplate; ///< Global object template for storing things like dali global object
v8::Isolate* mIsolate; ///< represents an isolated instance of the V8 engine.
-
+ RunMode mRunMode;
};
ModuleLoader::ModuleLoader()
{
-
}
ModuleLoader::~ModuleLoader()
* @for ModuleLoader
*
*/
-void ModuleLoader::Require(const v8::FunctionCallbackInfo< v8::Value >& args,
-
- v8::Persistent<v8::ObjectTemplate>& globalObjectTemplate )
+void ModuleLoader::Require(const v8::FunctionCallbackInfo< v8::Value >& args )
{
v8::Isolate* isolate = args.GetIsolate();
v8::HandleScope handleScope( isolate );
args.GetReturnValue().Set( moduleExports );
}
+
+void ModuleLoader::StorePreBuiltModule( v8::Isolate* isolate, v8::Local<v8::Object>& exportObject, const std::string& name )
+{
+ StoreModule( "", name, name, isolate, exportObject );
+}
+
void ModuleLoader::StoreScriptInfo( const std::string& sourceFileName )
{
V8Utils::GetFileDirectory( sourceFileName, mCurrentScriptPath);
public:
/**
- * Constructor
+ * @brief Constructor
+ * @param[in] isolate v8 isolate
+ * @param[in] daliObject dali exports object, used when developer does require('dali');
*/
ModuleLoader();
/**
- * non virtual destructor, not intended as a base class
+ * @brief non virtual destructor, not intended as a base class
*/
~ModuleLoader();
/**
- * Execute a script from a file
+ * @brief Execute a script from a file
+ * @param[in] isolate v8 isolate
* @param[in] fileName file name
* @return true on success, false on failure
*
/**
- * Execute a script
+ * @brief Execute a script
+ * @param[in] isolate v8 isolate
* @param[in] sourceCode source code to run
* @param[in] sourceFileName source file name
* @return true on success, false on failure
/**
- * Implements JavaScript Require functionality
+ * @brief Implements JavaScript Require functionality
+ * @param[in] args arguments passed to require. The return value is set using args.GetReturnValue().Set(
*/
- void Require(const v8::FunctionCallbackInfo< v8::Value >& args, v8::Persistent<v8::ObjectTemplate>& globalObjectTemplate );
+ void Require( const v8::FunctionCallbackInfo< v8::Value >& args );
+
+ /**
+ * @brief
+ * Stores a pre compiled object as a module.
+ * Currently used for storing the Dali object, so the developer can
+ * perform var dali = require('dali');
+ * @param[in] isolate v8 isolate
+ * @param[in] exportObject export object
+ * @param[in] name module name, used for the require('name') lookup
+ */
+ void StorePreBuiltModule( v8::Isolate* isolate, v8::Local<v8::Object>& exportObject, const std::string& name );
private:
const std::string& sourceFileName );
/**
- * Store information about the current script
+ * @brief Store information about the current script
* @param[in] sourceFileName source file name
*/
void StoreScriptInfo( const std::string& sourceFileName );
/**
- * Store module information
+ * @brief Store module information
* @param[in] sourceFileName source file name
* @return module object
*/
v8::Local<v8::Object>& moduleExportsObject );
/**
- * Find a module
+ * @brief Find a module
* @param[in] moduleName module name
* @return module
*/
{
case Dali::Property::BOOLEAN:
case Dali::Property::INTEGER:
- case Dali::Property::UNSIGNED_INTEGER:
case Dali::Property::STRING:
case Dali::Property::FLOAT:
{
v8Value = v8::Integer::New( isolate, value.Get<int>());
break;
}
- case Dali::Property::UNSIGNED_INTEGER:
- {
- v8Value = v8::Integer::New( isolate, value.Get<unsigned int>());
- break;
- }
case Dali::Property::STRING:
{
std::string string = value.Get< std::string >();
}
break;
}
- case Dali::Property::UNSIGNED_INTEGER:
- {
- if( v8Value->IsUint32() )
- {
- daliPropertyValue = Dali::Property::Value( v8Value->Uint32Value() );//static_cast<unsigned int>( V8Utils::GetNumberValue( isolate, v8Value) ));
- }
- break;
- }
case Dali::Property::STRING:
{
if( V8Utils::IsStringPrimitiveOrObject( v8Value) )
std::cout << " ";
}
v8::String::Utf8Value utf8_value( args[i] );
- std::cout << *utf8_value;
+ std::cout << *utf8_value << "\n";
}
}
}
v8::String::Utf8Value utf8_value( args[i] );
output += *utf8_value;
+ output +="\n";
}
DALI_LOG_ERROR_NOFN( "JavaScript: %s",output.c_str() );
}
v8::Local<v8::Number> v = value->ToNumber();
return Dali::Property::Value(static_cast<float>(v->Value()));
}
- else if( value->IsInt32() )
+ else if( value->IsInt32() || value->IsUint32() )
{
found = true;
v8::Local<v8::Int32> v = value->ToInt32();
return Dali::Property::Value(static_cast<int>(v->Value()));
}
- else if ( value->IsUint32() )
- {
- found = true;
- v8::Local<v8::Uint32> v = value->ToUint32();
- return Dali::Property::Value(static_cast<unsigned int>(v->Value()));
- }
return daliPropertyValue;
}
v8Value = v8::Integer::New( isolate, value.Get<int>());
break;
}
- case Dali::Property::UNSIGNED_INTEGER:
- {
- v8Value = v8::Integer::New( isolate, value.Get<unsigned int>());
- break;
- }
case Dali::Property::STRING:
{
std::string string = value.Get< std::string >();