const unsigned 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;
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 )
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,
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;
};
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;
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.
};
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;
}
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
*/
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,
/**
* @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 );
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: