const char* const PROPERTY_NAME_HORIZONTAL_ALIGNMENT = "horizontal-alignment";
const char* const PROPERTY_NAME_VERTICAL_ALIGNMENT = "vertical-alignment";
+static bool gTextChangedCallBackCalled;
static bool gMaxCharactersCallBackCalled;
+static void TestTextChangedCallback( TextField control )
+{
+ tet_infoline(" TestTextChangedCallback");
+
+ gTextChangedCallBackCalled = true;
+}
+
static void TestMaxLengthReachedCallback( TextField control )
{
- tet_infoline(" TestMaxLengthReachedCallbackCallback");
+ tet_infoline(" TestMaxLengthReachedCallback");
gMaxCharactersCallBackCalled = true;
}
END_TEST;
}
+// Positive test for the text-changed signal.
+int utcDaliTextFieldTextChangedP(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldTextChangedP");
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ Stage::GetCurrent().Add(field);
+
+ field.TextChangedSignal().Connect(&TestTextChangedCallback);
+
+ gTextChangedCallBackCalled = false;
+ field.SetProperty( TextField::Property::TEXT, "ABC" );
+ DALI_TEST_CHECK( gTextChangedCallBackCalled );
+
+ application.SendNotification();
+
+ field.SetKeyInputFocus();
+
+ Dali::Integration::KeyEvent keyevent;
+ keyevent.keyName = "D";
+ keyevent.keyString = "D";
+ keyevent.keyCode = 0;
+ keyevent.keyModifier = 0;
+ keyevent.time = 0;
+ keyevent.state = Integration::KeyEvent::Down;
+
+ gTextChangedCallBackCalled = false;
+ application.ProcessEvent( keyevent );
+ DALI_TEST_CHECK( gTextChangedCallBackCalled );
+
+ END_TEST;
+}
+
+// Negative test for the text-changed signal.
+int utcDaliTextFieldTextChangedN(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldTextChangedN");
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ Stage::GetCurrent().Add(field);
+
+ field.TextChangedSignal().Connect(&TestTextChangedCallback);
+
+ gTextChangedCallBackCalled = false;
+ field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "ABC" ); // Setting placeholder, not TEXT
+ DALI_TEST_CHECK( ! gTextChangedCallBackCalled );
+
+ END_TEST;
+}
+
// Positive test for Max Characters reached signal.
int utcDaliTextFieldMaxCharactersReachedP(void)
{
.image
{
text-align: left;
- margin-left: 50px;
+ margin-left: 20px;
+ margin-right: 20px;
}
div.image img {
void AtlasManager::GenerateMeshData( ImageId id,
const Vector2& position,
- MeshData& meshData )
+ MeshData& meshData,
+ bool addReference )
{
// Read the atlas Id to use for this image
SizeType imageId = id - 1u;
CreateMesh( atlas, width, height, position, widthInBlocks, heightInBlocks, meshData, mImageList[ imageId ] );
- // Mesh created so increase the reference count
- mImageList[ imageId ].mCount++;
+ // Mesh created so increase the reference count, if we're asked to
+ if ( addReference )
+ {
+ mImageList[ imageId ].mCount++;
+ }
}
Dali::Atlas AtlasManager::GetAtlasContainer( AtlasId atlas ) const
metrics.mTextureMemoryUsed = textureMemoryUsed;
}
-
} // namespace Internal
} // namespace Toolkit
*/
void GenerateMeshData( ImageId id,
const Vector2& position,
- MeshData& mesh );
+ MeshData& mesh,
+ bool addReference );
/**
* @copydoc Toolkit::AtlasManager::StitchMesh
void AtlasManager::GenerateMeshData( ImageId id,
const Vector2& position,
- MeshData& meshData)
+ MeshData& meshData,
+ bool addReference )
{
GetImplementation(*this).GenerateMeshData( id,
position,
- meshData );
+ meshData,
+ addReference );
}
void AtlasManager::StitchMesh( MeshData& first,
* @param[in] id Image Id returned in the AtlasSlot from the add operation
* @param[in] position position of the resulting mesh in model space
* @param[out] mesh Mesh Data Object to populate with mesh data
+ * @param[in] addReference Whether to increase the internal reference count for image or not
*/
void GenerateMeshData( ImageId id,
const Vector2& position,
- MeshData& mesh );
+ MeshData& mesh,
+ bool addReference = true );
/**
* @brief Append second mesh to the first mesh
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "decoration-bounding-box", RECTANGLE, DECORATION_BOUNDING_BOX )
DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "input-method-settings", MAP, INPUT_METHOD_SETTINGS )
+DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "text-changed", SIGNAL_TEXT_CHANGED )
DALI_SIGNAL_REGISTRATION( Toolkit, TextField, "max-length-reached", SIGNAL_MAX_LENGTH_REACHED )
DALI_TYPE_REGISTRATION_END()
bool connected( true );
Toolkit::TextField field = Toolkit::TextField::DownCast( handle );
- if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
+ if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_CHANGED ) )
+ {
+ field.TextChangedSignal().Connect( tracker, functor );
+ }
+ else if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_LENGTH_REACHED ) )
{
field.MaxLengthReachedSignal().Connect( tracker, functor );
}
return connected;
}
+Toolkit::TextField::TextChangedSignalType& TextField::TextChangedSignal()
+{
+ return mTextChangedSignal;
+}
+
Toolkit::TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
{
return mMaxLengthReachedSignal;
mController = Text::Controller::New( *this );
- mDecorator = Text::Decorator::New( *this, *mController );
+ mDecorator = Text::Decorator::New( *mController );
mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
return mController->KeyEvent( event );
}
-ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
+void TextField::AddDecoration( Actor& actor )
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
- return mController->OnImfEvent( imfManager, imfEvent );
+ if( actor )
+ {
+ Self().Add( actor );
+ }
}
void TextField::RequestTextRelayout()
RelayoutRequest();
}
+void TextField::TextChanged()
+{
+ Dali::Toolkit::TextField handle( GetOwner() );
+ mTextChangedSignal.Emit( handle );
+}
+
void TextField::MaxLengthReached()
{
Dali::Toolkit::TextField handle( GetOwner() );
mMaxLengthReachedSignal.Emit( handle );
}
+ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
+ return mController->OnImfEvent( imfManager, imfEvent );
+}
+
void TextField::EnableClipping( bool clipping, const Vector2& size )
{
if( clipping )
static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
/**
+ * @copydoc TextField::TextChangedSignal()
+ */
+ Toolkit::TextField::TextChangedSignalType& TextChangedSignal();
+
+ /**
* @copydoc TextField::MaxLengthReachedSignal()
*/
Toolkit::TextField::MaxLengthReachedSignalType& MaxLengthReachedSignal();
virtual bool OnKeyEvent(const KeyEvent& event);
/**
- * @copydoc Dali::Toolkit::Text::Controller::(ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent)
+ * @copydoc Text::ControlInterface::AddDecoration()
*/
- ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent );
+ virtual void AddDecoration( Actor& actor );
/**
* @copydoc Text::ControlInterface::RequestTextRelayout()
virtual void RequestTextRelayout();
/**
+ * @copydoc Text::ControlInterface::TextChanged()
+ */
+ virtual void TextChanged();
+
+ /**
* @copydoc Text::ControlInterface::MaxLengthReached()
*/
virtual void MaxLengthReached();
+ /**
+ * @copydoc Dali::Toolkit::Text::Controller::(ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent)
+ */
+ ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent );
+
private: // Implementation
/**
private: // Data
// Signals
+ Toolkit::TextField::TextChangedSignalType mTextChangedSignal;
Toolkit::TextField::MaxLengthReachedSignalType mMaxLengthReachedSignal;
Text::ControllerPtr mController;
}
}
+void TextLabel::AddDecoration( Actor& actor )
+{
+ // TextLabel does not show decorations
+}
+
void TextLabel::RequestTextRelayout()
{
RelayoutRequest();
}
+void TextLabel::TextChanged()
+{
+ // TextLabel does not provide a signal for this
+}
+
void TextLabel::MaxLengthReached()
{
// Pure Virtual from TextController Interface, only needed when inputting text
virtual float GetHeightForWidth( float width );
/**
+ * @copydoc Text::ControlInterface::AddDecoration()
+ */
+ virtual void AddDecoration( Actor& actor );
+
+ /**
* @copydoc Text::ControlInterface::RequestTextRelayout()
*/
virtual void RequestTextRelayout();
/**
+ * @copydoc Text::ControlInterface::TextChanged()
+ */
+ virtual void TextChanged();
+
+ /**
* @copydoc Text::ControlInterface::MaxLengthReached()
*/
virtual void MaxLengthReached();
Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
if(propertyActorFocusable == Property::INVALID_INDEX)
{
- propertyActorFocusable = actor.RegisterProperty(ACTOR_FOCUSABLE, true);
+ propertyActorFocusable = actor.RegisterProperty( ACTOR_FOCUSABLE, true, Property::READ_WRITE );
}
if(order == 0)
Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
if(propertyIsFocusGroup == Property::INVALID_INDEX)
{
- actor.RegisterProperty(IS_FOCUS_GROUP, isFocusGroup);
+ actor.RegisterProperty( IS_FOCUS_GROUP, isFocusGroup, Property::READ_WRITE );
}
else
{
Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
if(propertyActorFocusable == Property::INVALID_INDEX)
{
- actor.RegisterProperty(ACTOR_FOCUSABLE, focusable);
+ actor.RegisterProperty( ACTOR_FOCUSABLE, focusable, Property::READ_WRITE );
}
else
{
Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
if(propertyIsFocusGroup == Property::INVALID_INDEX)
{
- actor.RegisterProperty(IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup);
+ actor.RegisterProperty(IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE );
}
else
{
bool flipped : 1;
};
- Impl( Dali::Toolkit::Internal::Control& parent, Observer& observer )
- : mTextControlParent( parent ),
- mObserver( observer ),
+ Impl( ControllerInterface& controller )
+ : mController( controller ),
mBoundingBox( Rect<int>() ),
mHighlightColor( LIGHT_BLUE ),
mActiveCursor( ACTIVE_CURSOR_NONE ),
{
if( !mActiveLayer )
{
- Actor parent = mTextControlParent.Self();
-
mActiveLayer = Layer::New();
#ifdef DECORATOR_DEBUG
mActiveLayer.SetName ( "ActiveLayerActor" );
mActiveLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
mActiveLayer.SetPositionInheritanceMode( USE_PARENT_POSITION );
- parent.Add( mActiveLayer );
+ mController.AddDecoration( mActiveLayer );
}
mActiveLayer.RaiseToTop();
mHighlightMeshActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
mHighlightMeshActor.SetPosition( 0.0f, 0.0f, DISPLAYED_HIGHLIGHT_Z_OFFSET );
- Actor parent = mTextControlParent.Self();
- parent.Add( mHighlightMeshActor );
+ mController.AddDecoration( mHighlightMeshActor );
}
}
if( Gesture::Started == gesture.state ||
Gesture::Continuing == gesture.state )
{
+ Vector2 targetSize;
+ mController.GetTargetSize( targetSize );
+
if( x < mScrollThreshold )
{
mScrollDirection = SCROLL_RIGHT;
mHandleScrolling = type;
StartScrollTimer();
}
- else if( x > mTextControlParent.Self().GetTargetSize().width - mScrollThreshold )
+ else if( x > targetSize.width - mScrollThreshold )
{
mScrollDirection = SCROLL_LEFT;
mHandleScrolling = type;
{
mHandleScrolling = HANDLE_TYPE_COUNT;
StopScrollTimer();
- mObserver.HandleEvent( type, HANDLE_PRESSED, x, y );
+ mController.DecorationEvent( type, HANDLE_PRESSED, x, y );
}
}
else if( Gesture::Finished == gesture.state ||
{
mHandleScrolling = HANDLE_TYPE_COUNT;
StopScrollTimer();
- mObserver.HandleEvent( type, HANDLE_STOP_SCROLLING, x, y );
+ mController.DecorationEvent( type, HANDLE_STOP_SCROLLING, x, y );
}
else
{
- mObserver.HandleEvent( type, HANDLE_RELEASED, x, y );
+ mController.DecorationEvent( type, HANDLE_RELEASED, x, y );
}
handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_RELEASED] );
}
{
if( HANDLE_TYPE_COUNT != mHandleScrolling )
{
- mObserver.HandleEvent( mHandleScrolling,
- HANDLE_SCROLLING,
- mScrollDirection == SCROLL_RIGHT ? mScrollDistance : -mScrollDistance,
- 0.f );
+ mController.DecorationEvent( mHandleScrolling,
+ HANDLE_SCROLLING,
+ mScrollDirection == SCROLL_RIGHT ? mScrollDistance : -mScrollDistance,
+ 0.f );
}
return true;
}
- Internal::Control& mTextControlParent;
- Observer& mObserver;
+ ControllerInterface& mController;
TapGestureDetector mTapDetector;
PanGestureDetector mPanGestureDetector;
bool mSecondaryCursorVisible : 1; ///< Whether the secondary cursor is visible.
};
-DecoratorPtr Decorator::New( Internal::Control& parent, Observer& observer )
+DecoratorPtr Decorator::New( ControllerInterface& controller )
{
- return DecoratorPtr( new Decorator(parent, observer) );
+ return DecoratorPtr( new Decorator(controller) );
}
void Decorator::SetBoundingBox( const Rect<int>& boundingBox )
delete mImpl;
}
-Decorator::Decorator( Dali::Toolkit::Internal::Control& parent, Observer& observer )
+Decorator::Decorator( ControllerInterface& controller )
: mImpl( NULL )
{
- mImpl = new Decorator::Impl( parent, observer );
+ mImpl = new Decorator::Impl( controller );
}
} // namespace Text
namespace Dali
{
+class Actor;
class Image;
class Vector2;
class Vector4;
*
* Selection handles will be flipped around to ensure they do not exceed the Decoration Bounding Box. ( Stay visible ).
*
- * Decorator components forward input events to a controller class through an observer interface.
+ * Decorator components forward input events to a controller class through an interface.
* The controller is responsible for selecting which components are active.
*/
class Decorator : public RefObject
{
public:
- class Observer
+ class ControllerInterface
{
public:
/**
* @brief Constructor.
*/
- Observer() {};
+ ControllerInterface() {};
/**
* @brief Virtual destructor.
*/
- virtual ~Observer() {};
+ virtual ~ControllerInterface() {};
+
+ /**
+ * @brief An input event from one of the handles.
+ *
+ * @param[out] targetSize The Size of the UI control the decorator is adding it's decorations to.
+ */
+ virtual void GetTargetSize( Vector2& targetSize ) = 0;
+
+ /**
+ * @brief Add a decoration to the parent UI control.
+ *
+ * @param[in] decoration The actor displaying a decoration.
+ */
+ virtual void AddDecoration( Actor& actor ) = 0;
/**
* @brief An input event from one of the handles.
* @param[in] x The x position relative to the top-left of the parent control.
* @param[in] y The y position relative to the top-left of the parent control.
*/
- virtual void HandleEvent( HandleType handleType, HandleState state, float x, float y ) = 0;
+ virtual void DecorationEvent( HandleType handleType, HandleState state, float x, float y ) = 0;
};
/**
* @brief Create a new instance of a Decorator.
*
- * @param[in] parent Decorations will be added to this parent control.
- * @param[in] observer A class which receives input events from Decorator components.
+ * @param[in] controller The controller which receives input events from Decorator components.
* @return A pointer to a new Decorator.
*/
- static DecoratorPtr New( Dali::Toolkit::Internal::Control& parent, Observer& observer );
+ static DecoratorPtr New( ControllerInterface& controller );
/**
* @brief Set the bounding box which handles, popup and similar decorations will not exceed.
/**
* @brief Private constructor.
- * @param[in] parent Decorations will be added to this parent control.
- * @param[in] observer A class which receives input events from Decorator components.
+ * @param[in] controller The controller which receives input events from Decorator components.
*/
- Decorator(Dali::Toolkit::Internal::Control& parent, Observer& observer );
+ Decorator( ControllerInterface& controller );
// Undefined
Decorator( const Decorator& handle );
AtlasGlyphManager::~AtlasGlyphManager()
{
+ // Clear up any remaining references
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end();
+ ++fontGlyphRecordIt )
+ {
+ for ( Vector< GlyphRecordEntry >::Iterator glyphRecordEntryIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+ glyphRecordEntryIt != fontGlyphRecordIt->mGlyphRecords.End();
+ ++glyphRecordEntryIt )
+ {
+ mAtlasManager.Remove( glyphRecordEntryIt->mImageId );
+ }
+ }
}
AtlasGlyphManagerPtr AtlasGlyphManager::New()
return internal;
}
-void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
+void AtlasGlyphManager::Add( Text::FontId fontId,
+ const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
Dali::Toolkit::AtlasManager::AtlasSlot& slot )
{
- GlyphRecord record;
- record.mFontId = glyph.fontId;
- record.mIndex = glyph.index;
-
mAtlasManager.Add( bitmap, slot );
+
+ GlyphRecordEntry record;
+ record.mIndex = glyph.index;
record.mImageId = slot.mImageId;
- mGlyphRecords.PushBack( record );
+ record.mCount = 1;
+
+ // Have glyph records been created for this fontId ?
+ bool foundGlyph = false;
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end(); ++fontGlyphRecordIt )
+ {
+ if ( fontGlyphRecordIt->mFontId == fontId )
+ {
+ fontGlyphRecordIt->mGlyphRecords.PushBack( record );
+ foundGlyph = true;
+ break;
+ }
+ }
+
+ if ( !foundGlyph )
+ {
+ // We need to add a new font entry
+ FontGlyphRecord fontGlyphRecord;
+ fontGlyphRecord.mFontId = fontId;
+ fontGlyphRecord.mGlyphRecords.PushBack( record );
+ mFontGlyphRecords.push_back( fontGlyphRecord );
+ }
#ifdef DISPLAY_ATLAS
{
const Vector2& position,
MeshData& meshData )
{
- mAtlasManager.GenerateMeshData( imageId, position, meshData );
+ // Generate mesh data and tell Atlas Manager not to handle reference counting ( we'll do it )
+ mAtlasManager.GenerateMeshData( imageId, position, meshData, false );
}
void AtlasGlyphManager::StitchMesh( MeshData& first,
mAtlasManager.StitchMesh( first, second );
}
-void AtlasGlyphManager::Cached( Text::FontId fontId,
+bool AtlasGlyphManager::Cached( Text::FontId fontId,
uint32_t index,
Dali::Toolkit::AtlasManager::AtlasSlot& slot )
{
- for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i )
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end();
+ ++fontGlyphRecordIt )
{
- if ( fontId == mGlyphRecords[ i ].mFontId && index == mGlyphRecords[ i ].mIndex )
+ if ( fontGlyphRecordIt->mFontId == fontId )
{
- slot.mImageId = mGlyphRecords[ i ].mImageId;
- slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
- return;
+ for ( Vector< GlyphRecordEntry >::Iterator glyphRecordIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+ glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
+ ++glyphRecordIt )
+ {
+ if ( glyphRecordIt->mIndex == index )
+ {
+ slot.mImageId = glyphRecordIt->mImageId;
+ slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
+ return true;
+ }
+ }
}
}
slot.mImageId = 0;
+ return false;
}
Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId )
mAtlasManager.SetNewAtlasSize( size );
}
-void AtlasGlyphManager::Remove( uint32_t imageId )
-{
- if ( mAtlasManager.Remove( imageId ) )
- {
- for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i )
- {
- if ( mGlyphRecords[ i ].mImageId == imageId )
- {
- mGlyphRecords.Remove( mGlyphRecords.Begin() + i );
- return;
- }
- }
- }
-}
-
Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId )
{
return mAtlasManager.GetPixelFormat( atlasId );
const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
{
- mMetrics.mGlyphCount = mGlyphRecords.Size();
+ mMetrics.mGlyphCount = mFontGlyphRecords.size();
mAtlasManager.GetMetrics( mMetrics.mAtlasMetrics );
return mMetrics;
}
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, uint32_t imageId, int32_t delta )
+{
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end();
+ ++fontGlyphRecordIt )
+ {
+ if ( fontGlyphRecordIt->mFontId == fontId )
+ {
+ for ( Vector< GlyphRecordEntry >::Iterator glyphRecordIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+ glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
+ ++glyphRecordIt )
+ {
+ if ( glyphRecordIt->mImageId == imageId )
+ {
+ glyphRecordIt->mCount += delta;
+ if ( !glyphRecordIt->mCount )
+ {
+ mAtlasManager.Remove( glyphRecordIt->mImageId );
+ fontGlyphRecordIt->mGlyphRecords.Remove( glyphRecordIt );
+ }
+ return;
+ }
+ }
+ }
+ }
+}
+
} // namespace Internal
} // namespace Toolkit
{
public:
- struct GlyphRecord
+ struct GlyphRecordEntry
{
- Text::FontId mFontId;
Text::GlyphIndex mIndex;
uint32_t mImageId;
+ int32_t mCount;
+ };
+
+ struct FontGlyphRecord
+ {
+ Text::FontId mFontId;
+ Vector< GlyphRecordEntry > mGlyphRecords;
};
AtlasGlyphManager();
/**
* @copydoc Toolkit::AtlasGlyphManager::Add
*/
- void Add( const Text::GlyphInfo& glyph,
+ void Add( Text::FontId fontId,
+ const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
Dali::Toolkit::AtlasManager::AtlasSlot& slot );
/**
* @copydoc Toolkit::AtlasGlyphManager::Cached
*/
- void Cached( Text::FontId fontId,
+ bool Cached( Text::FontId fontId,
Text::GlyphIndex index,
Dali::Toolkit::AtlasManager::AtlasSlot& slot );
void SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight );
/**
- * @copydoc Toolkit::AtlasGlyphManager::Remove
- */
- void Remove( uint32_t imageId );
-
- /**
* @copydoc toolkit::AtlasGlyphManager::GetPixelFormat
*/
Pixel::Format GetPixelFormat( uint32_t atlasId );
*/
const Toolkit::AtlasGlyphManager::Metrics& GetMetrics();
+ /**
+ * @copydoc toolkit::AtlasGlyphManager::AdjustReferenceCount
+ */
+ void AdjustReferenceCount( Text::FontId fontId, uint32_t imageId, int32_t delta );
+
private:
Dali::Toolkit::AtlasManager mAtlasManager;
- Vector< GlyphRecord > mGlyphRecords;
+ std::vector< FontGlyphRecord > mFontGlyphRecords;
uint32_t mCount;
Toolkit::AtlasGlyphManager::Metrics mMetrics;
};
{
}
-void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
+void AtlasGlyphManager::Add( Text::FontId fontId,
+ const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
AtlasManager::AtlasSlot& slot )
{
- GetImplementation(*this).Add( glyph, bitmap, slot );
+ GetImplementation(*this).Add( fontId, glyph, bitmap, slot );
}
void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
GetImplementation(*this).StitchMesh( first, second );
}
-void AtlasGlyphManager::Cached( Text::FontId fontId,
+bool AtlasGlyphManager::Cached( Text::FontId fontId,
Text::GlyphIndex index,
AtlasManager::AtlasSlot& slot )
{
- GetImplementation(*this).Cached( fontId, index, slot );
+ return GetImplementation(*this).Cached( fontId, index, slot );
}
void AtlasGlyphManager::SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight )
return GetImplementation(*this).GetAtlasSize( atlasId );
}
-void AtlasGlyphManager::Remove( uint32_t imageId )
-{
- GetImplementation(*this).Remove( imageId );
-}
-
Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId )
{
return GetImplementation(*this).GetPixelFormat( atlasId );
return GetImplementation(*this).GetMetrics();
}
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, uint32_t imageId, int32_t delta )
+{
+ GetImplementation(*this).AdjustReferenceCount( fontId, imageId, delta );
+}
+
} // namespace Toolkit
} // namespace Dali
/**
* @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( const Text::GlyphInfo& glyph,
+ void Add( Text::FontId fontId,
+ const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
AtlasManager::AtlasSlot& slot );
* @param[in] fontId The font that this glyph comes from
* @param[in] index The GlyphIndex of this glyph
* @param[out] slot container holding information about the glyph( mImage = 0 indicates not being cached )
+ *
+ * @return Whether glyph is cached or not ?
*/
- void Cached( Text::FontId fontId,
+ bool Cached( Text::FontId fontId,
Text::GlyphIndex index,
AtlasManager::AtlasSlot& slot );
void SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight );
/**
- * @brief Unreference an image from the atlas and remove from cache if no longer needed
- *
- * @param[in] imageId ID of the image
- */
- void Remove( uint32_t imageId );
-
- /**
* @brief Get the Pixel Format used by an atlas
*
* @param[in] atlasId Id of atlas to check
*/
const Metrics& GetMetrics();
+ /**
+ * @brief Adjust the reference count for an imageId and remove cache entry if it becomes free
+ *
+ * @param[in] fontId the font this image came from
+ * @param[in] imageId The imageId
+ * @param[in] delta adjustment to make to reference count
+ */
+ void AdjustReferenceCount( Text::FontId fontId, uint32_t imageId, int32_t delta );
+
private:
explicit DALI_INTERNAL AtlasGlyphManager(Internal::AtlasGlyphManager *impl);
uint32_t mMeshRecordIndex;
};
- struct AtlasRecord
+ struct MaxBlockSize
{
- uint32_t mImageId;
+ FontId mFontId;
+ uint32_t mNeededBlockWidth;
+ uint32_t mNeededBlockHeight;
+ };
+
+ struct CheckEntry
+ {
+ FontId mFontId;
Text::GlyphIndex mIndex;
};
- struct MaxBlockSize
+ struct TextCacheEntry
{
FontId mFontId;
- uint32_t mNeededBlockWidth;
- uint32_t mNeededBlockHeight;
+ Text::GlyphIndex mIndex;
+ uint32_t mImageId;
};
Impl()
AtlasManager::AtlasSlot slot;
std::vector< MeshRecord > meshContainer;
Vector< Extent > extents;
+ TextCacheEntry textCacheEntry;
float currentUnderlinePosition = ZERO;
float currentUnderlineThickness = underlineHeight;
style = STYLE_DROP_SHADOW;
}
- if ( mImageIds.Size() )
+ if ( mTextCache.Size() )
{
- // Unreference any currently used glyphs
- RemoveText();
+ // Update the glyph cache with any changes to current text
+ RemoveText( glyphs );
}
CalculateBlocksSize( glyphs );
const Vector2& position = positions[ i ];
MeshData newMeshData;
- mGlyphManager.Cached( glyph.fontId, glyph.index, slot );
- if ( slot.mImageId )
- {
- // This glyph already exists so generate mesh data plugging in our supplied position
- mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData );
- mImageIds.PushBack( slot.mImageId );
- }
- else
+ if ( !mGlyphManager.Cached( glyph.fontId, glyph.index, slot ) )
{
-
// Select correct size for new atlas if needed....?
if ( lastFontId != glyph.fontId )
{
}
// Locate a new slot for our glyph
- mGlyphManager.Add( glyph, bitmap, slot );
-
- // Generate mesh data for this quad, plugging in our supplied position
- if ( slot.mImageId )
- {
- mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData );
- mImageIds.PushBack( slot.mImageId );
- }
+ mGlyphManager.Add( glyph.fontId, glyph, bitmap, slot );
}
}
+
+ // Generate mesh data for this quad, plugging in our supplied position
+ mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData );
+ textCacheEntry.mFontId = glyph.fontId;
+ textCacheEntry.mImageId = slot.mImageId;
+ textCacheEntry.mIndex = glyph.index;
+ mTextCache.PushBack( textCacheEntry );
+
// Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas)
StitchTextMesh( meshContainer,
newMeshData,
mActor = actor;
}
}
- mActor.OffStageSignal().Connect( this, &AtlasRenderer::Impl::OffStageDisconnect );
}
#if defined(DEBUG_ENABLED)
Toolkit::AtlasGlyphManager::Metrics metrics = mGlyphManager.GetMetrics();
}
}
- // Unreference any glyphs that were used with this actor
- void OffStageDisconnect( Dali::Actor actor )
+ void RemoveText( const Vector<GlyphInfo>& glyphs )
{
- RemoveText();
- }
+ Vector< CheckEntry > checked;
+ CheckEntry checkEntry;
- void RemoveText()
- {
- for ( uint32_t i = 0; i < mImageIds.Size(); ++i )
+ for ( Vector< TextCacheEntry >::Iterator tCit = mTextCache.Begin(); tCit != mTextCache.End(); ++tCit )
{
- mGlyphManager.Remove( mImageIds[ i ] );
+ uint32_t index = tCit->mIndex;
+ uint32_t fontId = tCit->mFontId;
+
+ // Check that this character has not already been checked...
+ bool wasChecked = false;
+ for ( Vector< CheckEntry >::Iterator cEit = checked.Begin(); cEit != checked.End(); ++cEit )
+ {
+ if ( fontId == cEit->mFontId && index == cEit->mIndex )
+ {
+ wasChecked = true;
+ }
+ }
+
+ if ( !wasChecked )
+ {
+
+ int32_t newCount = 0;
+ int32_t oldCount = 0;
+
+ // How many times does this character occur in the old text ?
+ for ( Vector< TextCacheEntry >::Iterator oTcit = mTextCache.Begin(); oTcit != mTextCache.End(); ++oTcit )
+ {
+ if ( fontId == oTcit->mFontId && index == oTcit->mIndex )
+ {
+ oldCount++;
+ }
+ }
+
+ // And how many times in the new ?
+ for ( Vector< GlyphInfo >::Iterator cGit = glyphs.Begin(); cGit != glyphs.End(); ++cGit )
+ {
+ if ( fontId == cGit->fontId && index == cGit->index )
+ {
+ newCount++;
+ }
+ }
+ mGlyphManager.AdjustReferenceCount( fontId, tCit->mImageId, newCount - oldCount );
+ checkEntry.mIndex = index;
+ checkEntry.mFontId = fontId;
+ checked.PushBack( checkEntry );
+ }
}
- mImageIds.Resize( 0 );
+ mTextCache.Resize( 0 );
}
void CalculateBlocksSize( const Vector<GlyphInfo>& glyphs )
RenderableActor mActor; ///< The actor parent which renders the text
AtlasGlyphManager mGlyphManager; ///< Glyph Manager to handle upload and caching
- Vector< uint32_t > mImageIds; ///< A list of imageIDs used by the renderer
TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
ShaderEffect mBasicShader; ///> Shader used to render L8 glyphs
ShaderEffect mBgraShader; ///> Shader used to render BGRA glyphs
ShaderEffect mBasicShadowShader; ///> Shader used to render drop shadow into buffer
std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas
std::vector< MeshData::FaceIndex > mFace; ///> Face indices for a quad
+ Vector< TextCacheEntry > mTextCache;
};
Text::RendererPtr AtlasRenderer::New()
AtlasRenderer::~AtlasRenderer()
{
+ Vector< GlyphInfo > emptyGlyphs;
+ mImpl->RemoveText( emptyGlyphs );
delete mImpl;
}
namespace Dali
{
+class Actor;
+
namespace Toolkit
{
virtual ~ControlInterface();
/**
+ * @brief Add a decoration.
+ *
+ * @param[in] decoration The actor displaying a decoration.
+ */
+ virtual void AddDecoration( Actor& actor ) = 0;
+
+ /**
* @brief Called to request a text relayout.
*/
virtual void RequestTextRelayout() = 0;
/**
+ * @brief Called to signal that text has been inserted or deleted.
+ */
+ virtual void TextChanged() = 0;
+
+ /**
* @brief Called when the number of characters to be inserted exceeds the maximum limit
*/
virtual void MaxLengthReached() = 0;
*/
void QueueModifyEvent( ModifyEvent::Type type )
{
+ if( ModifyEvent::TEXT_REPLACED == type)
+ {
+ // Cancel previously queued inserts etc.
+ mModifyEvents.clear();
+ }
+
ModifyEvent event;
event.type = type;
mModifyEvents.push_back( event );
void Controller::SetText( const std::string& text )
{
- // Cancel previously queued inserts etc.
- mImpl->mModifyEvents.clear();
-
// Remove the previously set text
ResetText();
+ CharacterIndex lastCursorIndex = 0u;
+
if( !text.empty() )
{
// Convert text into UTF-32
DALI_ASSERT_DEBUG( text.size() >= characterCount && "Invalid UTF32 conversion length" );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", this, text.size(), mImpl->mLogicalModel->mText.Count() );
- // Reset the cursor position
- if( mImpl->mEventData )
- {
- mImpl->mEventData->mPrimaryCursorPosition = characterCount;
- }
+ // To reset the cursor position
+ lastCursorIndex = characterCount;
// Update the rest of the model during size negotiation
mImpl->QueueModifyEvent( ModifyEvent::TEXT_REPLACED );
ShowPlaceholderText();
}
+ // Resets the cursor position.
+ ResetCursorPosition( lastCursorIndex );
+
+ // Scrolls the text to make the cursor visible.
+ ResetScrollPosition();
+
mImpl->RequestRelayout();
if( mImpl->mEventData )
// Reset keyboard as text changed
mImpl->ResetImfManager();
+
+ // Do this last since it provides callbacks into application code
+ mImpl->mControlInterface.TextChanged();
}
void Controller::GetText( std::string& text ) const
mImpl->mLogicalModel->mText.Clear();
ClearModelData();
- // Reset the cursor position
- if( mImpl->mEventData )
- {
- mImpl->mEventData->mPrimaryCursorPosition = 0;
- }
-
// We have cleared everything including the placeholder-text
mImpl->PlaceholderCleared();
mImpl->mOperationsPending = ALL_OPERATIONS;
}
+void Controller::ResetCursorPosition( CharacterIndex cursorIndex )
+{
+ // Reset the cursor position
+ if( NULL != mImpl->mEventData )
+ {
+ mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
+
+ // Update the cursor if it's in editing mode.
+ if( ( EventData::EDITING == mImpl->mEventData->mState ) ||
+ ( EventData::EDITING_WITH_POPUP == mImpl->mEventData->mState ) )
+ {
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ }
+ }
+}
+
+void Controller::ResetScrollPosition()
+{
+ if( NULL != mImpl->mEventData )
+ {
+ // Reset the scroll position.
+ mImpl->mEventData->mScrollPosition = Vector2::ZERO;
+ mImpl->mEventData->mScrollAfterUpdateCursorPosition = true;
+ }
+}
+
void Controller::TextReplacedEvent()
{
// Reset buffers.
{
DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected KeyEvent" );
+ bool textChanged( false );
+
if( mImpl->mEventData &&
keyEvent.state == KeyEvent::Down )
{
{
mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
}
+
+ textChanged = true;
}
}
else
mImpl->ClearPreEditFlag();
InsertText( keyString, COMMIT );
+
+ textChanged = true;
}
mImpl->ChangeState( EventData::EDITING ); // todo Confirm this is the best place to change the state of
mImpl->RequestRelayout();
}
+ if( textChanged )
+ {
+ // Do this last since it provides callbacks into application code
+ mImpl->mControlInterface.TextChanged();
+ }
+
return false;
}
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "MaxLengthReached (%d)\n", mImpl->mLogicalModel->mText.Count() );
- mImpl->mControlInterface.MaxLengthReached();
-
mImpl->ResetImfManager();
+
+ // Do this last since it provides callbacks into application code
+ mImpl->mControlInterface.MaxLengthReached();
}
}
}
}
-void Controller::HandleEvent( HandleType handleType, HandleState state, float x, float y )
+void Controller::GetTargetSize( Vector2& targetSize )
+{
+ targetSize = mImpl->mControlSize;
+}
+
+void Controller::AddDecoration( Actor& actor )
+{
+ mImpl->mControlInterface.AddDecoration( actor );
+}
+
+void Controller::DecorationEvent( HandleType handleType, HandleState state, float x, float y )
{
- DALI_ASSERT_DEBUG( mImpl->mEventData && "Controller::HandleEvent. Unexpected HandleEvent" );
+ DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected DecorationEvent" );
if( mImpl->mEventData )
{
{
mImpl->mOperationsPending = ALL_OPERATIONS;
mImpl->RequestRelayout();
+
+ // Do this last since it provides callbacks into application code
+ mImpl->mControlInterface.TextChanged();
}
ImfManager::ImfCallbackData callbackData( update, cursorPosition, text, false );
mImpl->mEventData->mIsShowingPlaceholderText = true;
- // Cancel previously queued inserts etc.
- mImpl->mModifyEvents.clear();
-
// Disable handles when showing place-holder text
mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
mImpl->mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
* It provides a view of the text that can be used by rendering back-ends.
*
* For selectable/editable UI controls, the controller handles input events from the UI control
- * and decorations (grab handles etc) via an observer interface.
+ * and decorations (grab handles etc) via an interface.
*/
-class Controller : public RefObject, public Decorator::Observer
+class Controller : public RefObject, public Decorator::ControllerInterface
{
public:
void ResetText();
/**
+ * @brief Used to reset the cursor position after setting a new text.
+ *
+ * @param[in] cursorIndex Where to place the cursor.
+ */
+ void ResetCursorPosition( CharacterIndex cursorIndex );
+
+ /**
+ * @brief Used to reset the scroll position after setting a new text.
+ */
+ void ResetScrollPosition();
+
+ /**
* @brief Used to process an event queued from SetText()
*/
void TextReplacedEvent();
void PanEvent( Gesture::State state, const Vector2& displacement );
/**
- * @copydoc Dali::Toolkit::Text::Decorator::Observer::HandleEvent()
- */
- virtual void HandleEvent( HandleType handle, HandleState state, float x, float y );
-
- /**
* @brief Event received from IMF manager
*
* @param[in] imfManager The IMF manager.
*/
ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent );
+ /**
+ * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::GetTargetSize()
+ */
+ virtual void GetTargetSize( Vector2& targetSize );
+
+ /**
+ * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::AddDecoration()
+ */
+ virtual void AddDecoration( Actor& actor );
+
+ /**
+ * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::DecorationEvent()
+ */
+ virtual void DecorationEvent( HandleType handle, HandleState state, float x, float y );
+
protected:
/**
{
const GlyphInfo& glyphToRemove = *( glyphs + index );
- // Need to reshape the glyph as the font may be different in size.
- const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph( mImpl->mFontClient.GetPointSize( glyphToRemove.fontId ) );
-
- if( !firstPenSet )
+ if( 0u != glyphToRemove.fontId )
{
- const Vector2& position = *( glyphPositions + index );
+ // i.e. The font id of the glyph shaped from the '\n' character is zero.
- // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
- penY = position.y + glyphToRemove.yBearing;
+ // Need to reshape the glyph as the font may be different in size.
+ const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph( mImpl->mFontClient.GetPointSize( glyphToRemove.fontId ) );
- // Calculates the first penX which will be used if rtl text is elided.
- firstPenX = position.x - glyphToRemove.xBearing;
- if( firstPenX < -ellipsisGlyph.xBearing )
+ if( !firstPenSet )
{
- // Avoids to exceed the bounding box when rtl text is elided.
- firstPenX = -ellipsisGlyph.xBearing;
- }
+ const Vector2& position = *( glyphPositions + index );
- removedGlypsWidth = -ellipsisGlyph.xBearing;
+ // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
+ penY = position.y + glyphToRemove.yBearing;
- firstPenSet = true;
- }
+ // Calculates the first penX which will be used if rtl text is elided.
+ firstPenX = position.x - glyphToRemove.xBearing;
+ if( firstPenX < -ellipsisGlyph.xBearing )
+ {
+ // Avoids to exceed the bounding box when rtl text is elided.
+ firstPenX = -ellipsisGlyph.xBearing;
+ }
- removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) );
+ removedGlypsWidth = -ellipsisGlyph.xBearing;
- // Calculate the width of the ellipsis glyph and check if it fits.
- const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
- if( ellipsisGlyphWidth < removedGlypsWidth )
- {
- GlyphInfo& glyphInfo = *( glyphs + index );
- Vector2& position = *( glyphPositions + index );
- position.x -= glyphInfo.xBearing;
-
- // Replace the glyph by the ellipsis glyph.
- glyphInfo = ellipsisGlyph;
+ firstPenSet = true;
+ }
- // Change the 'x' and 'y' position of the ellipsis glyph.
+ removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) );
- if( position.x > firstPenX )
+ // Calculate the width of the ellipsis glyph and check if it fits.
+ const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
+ if( ellipsisGlyphWidth < removedGlypsWidth )
{
- position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
- }
+ GlyphInfo& glyphInfo = *( glyphs + index );
+ Vector2& position = *( glyphPositions + index );
+ position.x -= glyphInfo.xBearing;
- position.x += ellipsisGlyph.xBearing;
- position.y = penY - ellipsisGlyph.yBearing;
+ // Replace the glyph by the ellipsis glyph.
+ glyphInfo = ellipsisGlyph;
- inserted = true;
+ // Change the 'x' and 'y' position of the ellipsis glyph.
+
+ if( position.x > firstPenX )
+ {
+ position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+ }
+
+ position.x += ellipsisGlyph.xBearing;
+ position.y = penY - ellipsisGlyph.yBearing;
+
+ inserted = true;
+ }
}
- else
+
+ if( !inserted )
{
if( index > 0u )
{
void Control::Initialize()
{
+ // Call deriving classes so initialised before styling is applied to them.
+ OnInitialize();
+
if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
{
Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
// Register for style changes
styleManager.StyleChangeSignal().Connect( this, &Control::OnStyleChange );
- // SetTheme
+ // Apply the current style
GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
}
{
SetKeyboardNavigationSupport( true );
}
-
- // Calling deriving classes
- OnInitialize();
}
void Control::OnInitialize()
return Control::DownCast<TextField, Internal::TextField>(handle);
}
+TextField::TextChangedSignalType& TextField::TextChangedSignal()
+{
+ return Dali::Toolkit::GetImpl( *this ).TextChangedSignal();
+}
+
TextField::MaxLengthReachedSignalType& TextField::MaxLengthReachedSignal()
{
return Dali::Toolkit::GetImpl( *this ).MaxLengthReachedSignal();
* * Signals
* | %Signal Name | Method |
* |------------------------|-----------------------------------------------------|
+ * | text-changed | @ref TextChangedSignal() |
* | max-length-reached | @ref MaxLengthReachedSignal() |
*
*/
// Type Defs
/// @brief Max Characters Exceed signal type;
+ typedef Signal<void ( TextField ) > TextChangedSignalType;
typedef Signal<void ( TextField ) > MaxLengthReachedSignalType;
/**
// Signals
/**
+ * @brief This signal is emitted when the text changes.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void YourCallbackName( TextField textField );
+ * @endcode
+ * @return The signal to connect to.
+ */
+ TextChangedSignalType& TextChangedSignal();
+
+ /**
* @brief This signal is emitted when inserted text exceeds the maximum character limit.
*
* A callback of the following type may be connected:
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 43;
+const unsigned int TOOLKIT_MICRO_VERSION = 44;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
+ Buttons
+ TableView
+ [Scroll View](@ref scroll-view)
- + ItemView
+ + [ItemView](@ref item-view)
### RenderTasks
+++ /dev/null
-/*! \page item-view Item View
- * Your text here
- *
- * References to Dali::Toolkit::ItemView will work...
- *
- */
-
--- /dev/null
+<!--
+/**-->
+
+# Item View {#item-view}
+
+An Item view is a scrollable container that contains several items.
+It can have several layouts.
+There are a few built-in layouts that the application writer can use:
+
+|GRID |SPIRAL |DEPTH |
+|:----------------------:|:------------------------:|:-----------------------:|
+|![ ](item-view/grid.png)|![ ](item-view/spiral.png)|![ ](item-view/depth.png)|
+
+The application writer can also create their own custom layout by inheriting from Dali::Toolkit::ItemLayout.
+
+## Item Factory
+
+To create an item-view, the application writer has to provide an item-factory.
+An ItemFactory provides methods to create items and how many items there are among other things.
+
+~~~{.cpp}
+class MyFactory : public Dali::Toolkit::ItemFactory
+{
+public:
+ virtual unsigned int GetNumberOfItems()
+ {
+ // Should return the number of items
+ return MY_ITEM_COUNT;
+ }
+
+ virtual Actor NewItem( unsigned int itemId )
+ {
+ // We should create the actor here that represents our item based on the itemId given.
+
+ // Here we'll create an ImageActor which uses the the itemId to parse the image in a particular directory.
+ std::ostringstream imageName;
+ imageName << "my-image-folder/" << itemId << ".png"; // If item was 10, then this would result in my-image-folder/10.png
+ Dali::ResourceImage image = Dali::ResourceImage::New( imageName.str() );
+
+ // Create an Image Actor from the image and return
+ return Dali::ImageActor::New( image );
+ }
+};
+~~~
+These overridden methods in our factory will be called by the Item View.
+
+## Creating an ItemView
+
+~~~{.cpp}
+MyFactory factory; // Should store this as a member variable
+Dali::Toolkit::ItemView itemView = Dali::Toolkit::ItemView::New( factory ); // Pass in our factory
+itemView.SetParentOrigin( ParentOrigin::CENTER );
+itemView.SetAnchorPoint( AnchorPoint::CENTER );
+
+// Now create a layout
+Dali::Toolkit::ItemLayoutPtr spiralLayout = Dali::Toolkit::DefaultItemLayout::New( Dali::Toolkit::DefaultItemLayout::SPIRAL );
+
+// ... and add the layout to the item view
+itemView.AddLayout( spiralLayout );
+
+// More layouts can be created and added to the item-view
+
+// Activate the layout
+itemView.ActivateLayout(
+ 0, // The layout ID matches the order in which layouts are added
+ Dali::Stage::GetCurrent().GetSize(), // Use the stage's size as our item-view size
+ 0 ); // We want the item-view to appear straight away
+
+// And add to the stage
+Dali::Stage::GetCurrent().Add( itemView );
+~~~
+
+*/
\ No newline at end of file
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.0.43
+Version: 1.0.44
Release: 1
Group: System/Libraries
License: Apache-2.0