currentPos = PerformGestureDiagonalSwipe(application, OVERSHOOT_START_SCROLL_POSITION, Vector2(1.0f, 1.0f), 105, false);
overshootXValue = scrollView.GetProperty<float>(ScrollView::Property::OVERSHOOT_X);
overshootYValue = scrollView.GetProperty<float>(ScrollView::Property::OVERSHOOT_Y);
- DALI_TEST_CHECK(overshootXValue > 0.49f && overshootXValue < 0.51f);
- DALI_TEST_CHECK(overshootYValue > 0.49f && overshootYValue < 0.51f);
+ // The overshoot value is a 0.0f - 1.0f ranged value of the amount overshot related to the maximum overshoot.
+ // EG. If we move 105, max overshoot is 50, then we overshot 50 / 105.
+ float correctOvershootValue = 50.0f / 105.f;
+ DALI_TEST_EQUALS( overshootXValue, correctOvershootValue, 0.001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( overshootYValue, correctOvershootValue, 0.001f, TEST_LOCATION );
// Scroll page further in NW (-30,-30 pixels), then check that overshoot should be now 1.0. (don't release touch)
currentPos = PerformGestureDiagonalSwipe(application, OVERSHOOT_START_SCROLL_POSITION, Vector2(1.0f, 1.0f), 30, false);
Wait(application);
// Try a vertical swipe.
PerformGestureDiagonalSwipe(application, START_POSITION, Vector2(0.0f, 1.0f), 60, true);
- DALI_TEST_EQUALS( scrollView.GetCurrentScrollPosition(), Vector2(10.0f, -50.0f), TEST_LOCATION );
+ // Take into account resampling done when prediction is off.
+ DALI_TEST_EQUALS( scrollView.GetCurrentScrollPosition() - Vector2(0.0f, 0.5f), Vector2(10.0f, -50.0f), 0.25f, TEST_LOCATION );
scrollView.SetScrollingDirection(Dali::PanGestureDetector::DIRECTION_VERTICAL);
Wait(application);
// Try a vertical swipe.
PerformGestureDiagonalSwipe(application, START_POSITION, Vector2(0.0f, 1.0f), 60, true);
- DALI_TEST_EQUALS( scrollView.GetCurrentScrollPosition(), Vector2(10.0f, -50.0f), TEST_LOCATION );
+ DALI_TEST_EQUALS( scrollView.GetCurrentScrollPosition() - Vector2(0.0f, 0.5f), Vector2(10.0f, -50.0f), 0.25f, TEST_LOCATION );
END_TEST;
}
Wait(application);
// Try a vertical swipe.
PerformGestureDiagonalSwipe(application, START_POSITION, Vector2(0.0f, 1.0f), 60, true);
- DALI_TEST_EQUALS( scrollView.GetCurrentScrollPosition(), Vector2(10.0f, -50.0f), TEST_LOCATION );
+ // Take into account resampling done when prediction is off.
+ DALI_TEST_EQUALS( scrollView.GetCurrentScrollPosition() - Vector2(0.0f, 0.5f), Vector2(10.0f, -50.0f), 0.25f, TEST_LOCATION );
END_TEST;
}
Profile: $dali_profile
Data Dir (Read/Write): $dataReadWriteDir
Data Dir (Read Only): $dataReadOnlyDir
- Style Dir $STYLE_DIR
- Style $dali_style
+ Style Dir: $STYLE_DIR
+ Style: $dali_style
+ i18n: $enable_i18n
"
dalisounddir = ${dataReadOnlyDir}/toolkit/sounds/
dalisound_DATA = ${dali_toolkit_sound_files}
+package_doxy_dir = ../../../doc
+include ../../../doc/file.list
+
# The library
lib_LTLIBRARIES = libdali-toolkit.la
publicapifocusmanager_HEADERS = $(public_api_focus_manager_header_files)
publicapirenderingbackend_HEADERS = $(public_api_rendering_backend_header_files)
+# package doxygen file (contains doxygen grouping information)
+packagedoxydir = $(topleveldir)/doc
+packagedoxy_HEADERS = $(package_doxy_files)
# Note: If this tag is empty the current directory is searched.
INPUT = @DOXYGEN_DOCS_DIR@/content \
+ @prefix@/include/dali/doc/dali-core-doc.h \
+ @prefix@/include/dali/doc/dali-adaptor-doc.h \
+ ../../../../dali-toolkit/doc/dali-toolkit-doc.h \
+ @prefix@/include/dali \
../../../../dali-toolkit/dali-toolkit/public-api \
- ../../../automated-tests/README.md \
- @prefix@/include/dali
+ ../../../automated-tests/README.md
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
GetImpl(*this).SetOrientation( orientation );
}
+std::string StyleManager::GetDefaultFontFamily() const
+{
+ return GetImpl(*this).GetDefaultFontFamily();
+}
+
Orientation StyleManager::GetOrientation()
{
return GetImpl(*this).GetOrientation();
Orientation GetOrientation();
/**
+ * @brief Retrieves the default font family.
+ * @return The default font family.
+ */
+ std::string GetDefaultFontFamily() const;
+
+ /**
* @brief Make a request to set the theme JSON file to one that exists in the Toolkit package.
*
* Multiple requests per event processing cycle can be made, but only the final one will be acted
atlasDescriptor.mHorizontalStrip = BufferImage::New( blockWidth, SINGLE_PIXEL_PADDING, pixelformat );
atlasDescriptor.mVerticalStrip = BufferImage::New( SINGLE_PIXEL_PADDING, blockHeight - DOUBLE_PIXEL_PADDING, pixelformat );
- memset( atlasDescriptor.mHorizontalStrip.GetBuffer(), 0, atlasDescriptor.mHorizontalStrip.GetBufferSize() );
- memset( atlasDescriptor.mVerticalStrip.GetBuffer(), 0, atlasDescriptor.mVerticalStrip.GetBufferSize() );
+ PixelBuffer* buffer = atlasDescriptor.mHorizontalStrip.GetBuffer();
+ if( buffer == NULL )
+ {
+ DALI_LOG_ERROR("atlasDescriptor.mHorizontalStrip.GetBuffer() returns NULL\n");
+ return 0;
+ }
+ memset( buffer, 0, atlasDescriptor.mHorizontalStrip.GetBufferSize() );
+
+ buffer = atlasDescriptor.mVerticalStrip.GetBuffer();
+ if( buffer == NULL )
+ {
+ DALI_LOG_ERROR("atlasDescriptor.mVerticalStrip.GetBuffer() returns NULL\n");
+ return 0;
+ }
+ memset( buffer, 0, atlasDescriptor.mVerticalStrip.GetBufferSize() );
BufferImage filledPixelImage = BufferImage::New( 1u, 1u, pixelformat );
- memset( filledPixelImage.GetBuffer(), 0xFF, filledPixelImage.GetBufferSize() );
+ buffer = filledPixelImage.GetBuffer();
+ if( buffer == NULL)
+ {
+ DALI_LOG_ERROR("filledPixelImage.GetBuffer() returns NULL\n");
+ return 0;
+ }
+
+ memset( buffer, 0xFF, filledPixelImage.GetBufferSize() );
atlas.Upload( filledPixelImage, 0, 0 );
Sampler sampler = Sampler::New( atlas, "sTexture" );
if( SetPropertyFromNode( *image, Property::MAP, property, constant ) )
{
Property::Map* map = property.GetMap();
- (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") );
- ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) );
- mFrameBufferImageLut[ name ] = ret;
+
+ if( map )
+ {
+ (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") );
+ ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) );
+ mFrameBufferImageLut[ name ] = ret;
+ }
}
}
}
{
value = Property::Value(Property::ARRAY);
Property::Array* array = value.GetArray();
+
unsigned int i = 0;
TreeNode::ConstIterator iter(node.CBegin());
- for( ; i < node.Size(); ++i, ++iter)
+
+ if( array )
{
- Property::Value childValue;
- if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ for( ; i < node.Size(); ++i, ++iter)
{
- array->PushBack( childValue );
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ {
+ array->PushBack( childValue );
+ }
}
- }
- if( array->Count() == node.Size() )
- {
- done = true;
- }
- else
- {
- done = false;
+ if( array->Count() == node.Size() )
+ {
+ done = true;
+ }
+ else
+ {
+ done = false;
+ }
}
}
break;
{
value = Property::Value(Property::MAP);
Property::Map* map = value.GetMap();
+
unsigned int i = 0;
TreeNode::ConstIterator iter(node.CBegin());
- for( ; i < node.Size(); ++i, ++iter)
+
+ if( map )
{
- Property::Value childValue;
- if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ for( ; i < node.Size(); ++i, ++iter)
{
- map->Insert( (*iter).first, childValue );
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ {
+ map->Insert( (*iter).first, childValue );
+ }
}
- }
- if( map->Count() == node.Size() )
- {
- done = true;
- }
- else
- {
- done = false;
+ if( map->Count() == node.Size() )
+ {
+ done = true;
+ }
+ else
+ {
+ done = false;
+ }
}
}
break;
value = Property::Value(Property::ARRAY);
Property::Array* array = value.GetArray();
- for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
+ if( array )
{
- Property::Value childValue;
- if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
{
- array->PushBack( childValue );
- done = true;
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ {
+ array->PushBack( childValue );
+ done = true;
+ }
}
}
}
{
value = Property::Value(Property::ARRAY);
Property::Array* array = value.GetArray();
- for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
+
+ if( array )
{
- Property::Value childValue;
- if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
{
- array->PushBack( childValue );
- done = true;
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ {
+ array->PushBack( childValue );
+ done = true;
+ }
}
}
}
{
value = Property::Value(Property::MAP);
Property::Map* map = value.GetMap();
- for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
+
+ if( map )
{
- Property::Value childValue;
- if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
{
- map->Insert( (*iter).first, childValue );
- done = true;
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
+ {
+ map->Insert( (*iter).first, childValue );
+ done = true;
+ }
}
}
}
BubbleActor::BubbleActor( unsigned int numberOfBubble,
const Vector2& movementArea)
: mMovementArea( movementArea ),
- mNumBubble( numberOfBubble )
+ mNumBubble( numberOfBubble ),
+ mRandomSeed( 0 )
{
mActor = Actor::New();
}
mIndexInvertedMovementArea = mActor.RegisterProperty( "uInvertedMovementArea", Vector2(1.f,1.f) / mMovementArea );
- srand(time(NULL));
mIndicesOffset.resize(9);
int offset = mMovementArea.Length() / 10.f;
- mIndicesOffset[0] = mActor.RegisterProperty( "uOffset[0]", Vector2(0.f,0.f));
- mIndicesOffset[1] = mActor.RegisterProperty( "uOffset[1]", Vector2(rand()%offset,rand()%offset) );
- mIndicesOffset[2] = mActor.RegisterProperty( "uOffset[2]", Vector2(rand()%offset,-rand()%offset) );
- mIndicesOffset[3] = mActor.RegisterProperty( "uOffset[3]", Vector2(-rand()%offset,rand()%offset) );
- mIndicesOffset[4] = mActor.RegisterProperty( "uOffset[4]", Vector2(-rand()%offset,-rand()%offset) );
- mIndicesOffset[5] = mActor.RegisterProperty( "uOffset[5]", Vector2(rand()%offset,0.f));
- mIndicesOffset[6] = mActor.RegisterProperty( "uOffset[6]", Vector2(-rand()%offset,0.f));
- mIndicesOffset[7] = mActor.RegisterProperty( "uOffset[7]", Vector2(0.f,rand()%offset));
- mIndicesOffset[8] = mActor.RegisterProperty( "uOffset[8]", Vector2(0.f,-rand()%offset));
+
+ mRandomSeed = time( NULL );
+
+ mIndicesOffset[0] = mActor.RegisterProperty( "uOffset[0]", Vector2( 0.f,0.f ) );
+ mIndicesOffset[1] = mActor.RegisterProperty( "uOffset[1]", Vector2( rand_r( &mRandomSeed ) % offset, rand_r( &mRandomSeed ) % offset ) );
+ mIndicesOffset[2] = mActor.RegisterProperty( "uOffset[2]", Vector2( rand_r( &mRandomSeed ) % offset, -rand_r( &mRandomSeed ) % offset ) );
+ mIndicesOffset[3] = mActor.RegisterProperty( "uOffset[3]", Vector2(-rand_r( &mRandomSeed ) % offset, rand_r( &mRandomSeed ) % offset ) );
+ mIndicesOffset[4] = mActor.RegisterProperty( "uOffset[4]", Vector2(-rand_r( &mRandomSeed ) % offset, -rand_r( &mRandomSeed ) % offset ) );
+ mIndicesOffset[5] = mActor.RegisterProperty( "uOffset[5]", Vector2( rand_r( &mRandomSeed ) % offset, 0.f ) );
+ mIndicesOffset[6] = mActor.RegisterProperty( "uOffset[6]", Vector2(-rand_r( &mRandomSeed ) % offset, 0.f ) );
+ mIndicesOffset[7] = mActor.RegisterProperty( "uOffset[7]", Vector2( 0.f, rand_r( &mRandomSeed ) % offset ) );
+ mIndicesOffset[8] = mActor.RegisterProperty( "uOffset[8]", Vector2( 0.f, -rand_r( &mRandomSeed ) % offset ) );
Vector4 zeroVector;
mIndiceStartEndPos.resize( mNumBubble );
mActor.SetProperty( mIndexInvertedMovementArea, Vector2(1.f,1.f) / mMovementArea );
int offset = mMovementArea.Length() / 10.f;
- mActor.SetProperty( mIndicesOffset[1], Vector2(rand()%offset,rand()%offset) );
- mActor.SetProperty( mIndicesOffset[2], Vector2(rand()%offset,-rand()%offset) );
- mActor.SetProperty( mIndicesOffset[3], Vector2(-rand()%offset,rand()%offset) );
- mActor.SetProperty( mIndicesOffset[4], Vector2(-rand()%offset,-rand()%offset) );
- mActor.SetProperty( mIndicesOffset[5], Vector2(rand()%offset,0.f));
- mActor.SetProperty( mIndicesOffset[6], Vector2(-rand()%offset,0.f));
- mActor.SetProperty( mIndicesOffset[7], Vector2(0.f,rand()%offset));
- mActor.SetProperty( mIndicesOffset[8], Vector2(0.f,-rand()%offset));
+
+ mActor.SetProperty( mIndicesOffset[1], Vector2( rand_r( &mRandomSeed ) % offset, rand_r( &mRandomSeed ) % offset ) );
+ mActor.SetProperty( mIndicesOffset[2], Vector2( rand_r( &mRandomSeed ) % offset, -rand_r( &mRandomSeed ) % offset ) );
+ mActor.SetProperty( mIndicesOffset[3], Vector2(-rand_r( &mRandomSeed ) % offset, rand_r( &mRandomSeed ) % offset ) );
+ mActor.SetProperty( mIndicesOffset[4], Vector2(-rand_r( &mRandomSeed ) % offset, -rand_r( &mRandomSeed ) % offset ) );
+ mActor.SetProperty( mIndicesOffset[5], Vector2( rand_r( &mRandomSeed ) % offset, 0.f ) );
+ mActor.SetProperty( mIndicesOffset[6], Vector2(-rand_r( &mRandomSeed ) % offset, 0.f ) );
+ mActor.SetProperty( mIndicesOffset[7], Vector2( 0.f, rand_r( &mRandomSeed ) % offset ) );
+ mActor.SetProperty( mIndicesOffset[8], Vector2( 0.f, -rand_r( &mRandomSeed ) % offset ) );
}
void BubbleActor::SetStartAndEndPosition( unsigned int index, const Vector4& startAndEndPosition )
Property::Index mIndexInvertedMovementArea; ///< Index of the property mapping to uniform 'uInvertedMovementArea'
unsigned int mNumBubble; ///< How many groups of uniforms are used to control the bubble movement.
+ unsigned int mRandomSeed; ///< Seed to generate random number.
};
} // namespace Internal
* Return a random value between the given interval.
* @param[in] f0 The low bound
* @param[in] f1 The up bound
+ * @param[in] seed The seed to genergate random number
* @return A random value between the given interval
*/
-float RandomRange(float f0, float f1)
+float RandomRange(float f0, float f1, unsigned int& seed)
{
- return f0 + (rand() & 0xfff) * (f1-f0) * (1.0f/4095.0f);
+ return f0 + (rand_r( &seed ) & 0xfff) * (f1-f0) * (1.0f/4095.0f);
}
}
mDensity( 5 ),
mTotalNumOfBubble( maximumNumberOfBubble ),
mCurrentBubble( 0 ),
+ mRandomSeed( 0 ),
mRenderTaskRunning(false)
{
// Calculate how many shaders are required
mNumBubblePerActor = mTotalNumOfBubble;
mNumActor = 1;
}
+
+ mRandomSeed = time( NULL );
}
BubbleEmitter::~BubbleEmitter()
for(unsigned int i = 0; i < numOfPatch; i++)
{
- float curSize = RandomRange(mBubbleSizeRange.x, mBubbleSizeRange.y);
+ float curSize = RandomRange(mBubbleSizeRange.x, mBubbleSizeRange.y, mRandomSeed);
float index = static_cast<float>( i );
vertexData.push_back( Vertex( index, Vector2(0.f,0.f), Vector2(0.f,0.f) ) );
int halfRange = displacement.x / 2;
// for the y coordinate, always negative, so bubbles always go upwards
- Vector2 randomVec(rand()%static_cast<int>(displacement.x) - halfRange, -rand()%static_cast<int>(displacement.y));
+ Vector2 randomVec( rand_r( &mRandomSeed ) % static_cast<int>(displacement.x) - halfRange, -rand_r( &mRandomSeed ) % static_cast<int>(displacement.y) );
dir.Normalize();
randomVec.x -= dir.x*halfRange;
randomVec.y *= 1.0f - fabsf(dir.x)*0.33f;
unsigned int mDensity; ///< How many bubbles will emit at each time, they are controlled by same uniforms in the shader.
unsigned int mTotalNumOfBubble; ///< mNumBubblePerShader*mNumShader.
unsigned int mCurrentBubble; ///< Keep track of the index for the newly emitted bubble
+ unsigned int mRandomSeed; ///< Seed to generate random number.
bool mRenderTaskRunning; ///< If the background render task is currently running
{
Property::Value value( Property::ARRAY );
Property::Array* array = value.GetArray();
- Dali::Vector<float> positions = scrollBarImpl.GetScrollPositionIntervals();
- size_t positionCount( array->Count() );
- for( size_t i( 0 ); i != positionCount; ++i )
+
+ if( array )
{
- array->PushBack( positions[i] );
+ Dali::Vector<float> positions = scrollBarImpl.GetScrollPositionIntervals();
+ size_t positionCount( array->Count() );
+ for( size_t i( 0 ); i != positionCount; ++i )
+ {
+ array->PushBack( positions[i] );
+ }
}
break;
}
private:
+ // Undefined
+ DepthLayout( const DepthLayout& depthLayout );
+
+ // Undefined
+ DepthLayout& operator=( const DepthLayout& depthLayout );
+
+private:
+
struct Impl;
Impl* mImpl;
};
private:
+ // Undefined
+ GridLayout( const GridLayout& itemLayout );
+
+ // Undefined
+ GridLayout& operator=( const GridLayout& rhs );
+
+private:
+
struct Impl;
Impl* mImpl;
};
private:
+ // Undefined
+ SpiralLayout( const SpiralLayout& spiralLayout );
+
+ // Undefined
+ SpiralLayout& operator=( const SpiralLayout& spiralLayout );
+
+private:
+
struct Impl;
Impl* mImpl;
};
}
}
-void ScrollOvershootIndicator::ClearOvershoot()
-{
- if(mEffectX)
- {
- mEffectX->SetOvershoot(0.0f);
- }
- if(mEffectY)
- {
- mEffectY->SetOvershoot(0.0f);
- }
-}
-
ScrollOvershootEffect::ScrollOvershootEffect( bool vertical ) :
mVertical(vertical)
{
void Reset();
/**
- * Clears the overshoot
- */
- void ClearOvershoot();
-
- /**
* Create an initialized ScrollOvershootIndicator
*
* @return A pointer to the created ScrollOvershootIndicator.
{
mScrollMainInternalPrePositionConstraint.Remove();
}
-
- if( mOvershootIndicator )
- {
- mOvershootIndicator->ClearOvershoot();
- }
}
else
{
//Create linear constrainer
pointsProperty = Property::Value(Property::ARRAY);
Property::Array* array = pointsProperty.GetArray();
- array->PushBack(0.0f);
- array->PushBack(1.0f);
- array->PushBack(0.0f);
+
+ if( array )
+ {
+ array->PushBack(0.0f);
+ array->PushBack(1.0f);
+ array->PushBack(0.0f);
+ }
mLinearConstrainer = Dali::LinearConstrainer::New();
mLinearConstrainer.SetProperty( LinearConstrainer::Property::VALUE, pointsProperty );
}
#include <dali-toolkit/internal/controls/text-controls/text-field-impl.h>
// EXTERNAL INCLUDES
-#include <string>
-#include <iostream>
#include <cstring>
#include <dali/public-api/adaptor-framework/key.h>
#include <dali/public-api/common/stage.h>
#include <dali/public-api/images/resource-image.h>
-#include <dali/public-api/object/type-registry.h>
-#include <dali/devel-api/object/type-registry-helper.h>
-#include <dali/devel-api/scripting/scripting.h>
#include <dali/devel-api/adaptor-framework/virtual-keyboard.h>
+#include <dali/devel-api/object/type-registry-helper.h>
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/text/rendering-backend.h>
-#include <dali-toolkit/internal/text/layouts/layout-engine.h>
+#include <dali-toolkit/internal/controls/text-controls/text-font-style.h>
#include <dali-toolkit/internal/text/rendering/text-backend.h>
#include <dali-toolkit/internal/text/text-view.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
#endif
const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
-
} // unnamed namespace
namespace
{
Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField SetProperty\n");
+
+
if( textField )
{
TextField& impl( GetImpl( textField ) );
if( impl.mController->GetDefaultFontFamily() != fontFamily )
{
- impl.mController->SetDefaultFontFamily( fontFamily );
+ impl.mController->SetDefaultFontFamily( fontFamily, true ); // "true" as SetProperty means user defined font so don't change when system font changes.
}
}
break;
}
case Toolkit::TextField::Property::FONT_STYLE:
{
- if( impl.mController )
- {
- const std::string fontStyle = value.Get< std::string >();
- DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_STYLE %s\n", impl.mController.Get(), fontStyle.c_str() );
-
- if( impl.mController->GetDefaultFontStyle() != fontStyle )
- {
- impl.mController->SetDefaultFontStyle( fontStyle );
- }
- }
+ SetFontStyleProperty( impl.mController, value );
break;
}
case Toolkit::TextField::Property::POINT_SIZE:
if( impl.mController )
{
const float pointSize = value.Get< float >();
- DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p FONT_STYLE %f\n", impl.mController.Get(), pointSize );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p POINT_SIZE %f\n", impl.mController.Get(), pointSize );
if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) )
{
{
const Image image = Scripting::NewImage( value );
- if( impl.mDecorator )
+ if( impl.mDecorator && image )
{
impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
impl.RequestTextRelayout();
{
const Image image = Scripting::NewImage( value );
- if( impl.mDecorator )
+ if( impl.mDecorator && image )
{
impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_RELEASED, image );
impl.RequestTextRelayout();
{
const Image image = Scripting::NewImage( value );
- if( impl.mDecorator )
+ if( impl.mDecorator && image )
{
impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
impl.RequestTextRelayout();
{
const Image image = Scripting::NewImage( value );
- if( impl.mDecorator )
+ if( impl.mDecorator && image )
{
impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE, HANDLE_IMAGE_PRESSED, image );
impl.RequestTextRelayout();
case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_LEFT:
{
const Image image = Scripting::NewImage( value );
- if( impl.mDecorator )
+
+ if( impl.mDecorator && image )
{
impl.mDecorator->SetHandleImage( LEFT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, image );
impl.RequestTextRelayout();
case Toolkit::TextField::Property::SELECTION_HANDLE_MARKER_IMAGE_RIGHT:
{
const Image image = Scripting::NewImage( value );
- if( impl.mDecorator )
+
+ if( impl.mDecorator && image )
{
impl.mDecorator->SetHandleImage( RIGHT_SELECTION_HANDLE_MARKER, HANDLE_IMAGE_RELEASED, image );
impl.RequestTextRelayout();
}
case Toolkit::TextField::Property::FONT_STYLE:
{
- if( impl.mController )
- {
- value = impl.mController->GetDefaultFontStyle();
- }
+ GetFontStyleProperty( impl.mController, value );
break;
}
case Toolkit::TextField::Property::POINT_SIZE:
{
if( impl.mDecorator )
{
- value = impl.mDecorator->GetBoundingBox();
+ Rect<int> boundingBox;
+ impl.mDecorator->GetBoundingBox( boundingBox );
+ value = boundingBox;
}
break;
}
self.TouchedSignal().Connect( this, &TextField::OnTouched );
// Set BoundingBox to stage size if not already set.
- if ( mDecorator->GetBoundingBox().IsEmpty() )
+ Rect<int> boundingBox;
+ mDecorator->GetBoundingBox( boundingBox );
+
+ if( boundingBox.IsEmpty() )
{
Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
mDecorator->SetBoundingBox( Rect<int>( 0.0f, 0.0f, stageSize.width, stageSize.height ) );
{
case StyleChange::DEFAULT_FONT_CHANGE:
{
- DALI_LOG_INFO( gLogFilter, Debug::General, "TextField::OnStyleChange StyleChange::DEFAULT_FONT_CHANGE\n");
- if ( mController->GetDefaultFontFamily() == "" )
- {
- // Property system did not set the font so should update it.
- // todo instruct text-controller to update model
- }
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnStyleChange DEFAULT_FONT_CHANGE\n");
+ std::string newFont = styleManager.GetDefaultFontFamily();
+ // Property system did not set the font so should update it.
+ mController->UpdateAfterFontChange( newFont );
break;
}
void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField OnRelayout\n");
+
if( mController->Relayout( size ) ||
!mRenderer )
{
void TextField::OnLongPress( const LongPressGesture& gesture )
{
+ // Show the keyboard if it was hidden.
+ if (!VirtualKeyboard::IsVisible())
+ {
+ VirtualKeyboard::Show();
+ }
+
mController->LongPressEvent( gesture.state, gesture.localPoint.x, gesture.localPoint.y );
+
+ SetKeyInputFocus();
}
bool TextField::OnKeyEvent( const KeyEvent& event )
--- /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.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/controls/text-controls/text-font-style.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/builder/json-parser.h>
+#include <dali-toolkit/devel-api/builder/tree-node.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace
+{
+const std::string STYLE_KEY( "style" );
+const std::string WIDTH_KEY( "width" );
+const std::string WEIGHT_KEY( "weight" );
+const std::string SLANT_KEY( "slant" );
+const std::string EMPTY_STRING( "" );
+
+} // namespace
+
+/**
+ * @brief Creates a map with pairs 'key,value' with the font's style parameters.
+ *
+ * @param[in] node Data structure with the font's style parameters.
+ * @param[out] map A map with the font's style parameters.
+ *
+ */
+void CreateFontStyleMap( const TreeNode* const node, Property::Map& map )
+{
+ switch( node->GetType() )
+ {
+ case TreeNode::IS_NULL:
+ case TreeNode::OBJECT:
+ case TreeNode::ARRAY: // FALL THROUGH
+ {
+ break;
+ }
+ case TreeNode::STRING:
+ {
+ map.Insert( node->GetName(), Property::Value( node->GetString() ) );
+ break;
+ }
+ case TreeNode::INTEGER:
+ case TreeNode::FLOAT:
+ case TreeNode::BOOLEAN: // FALL THROUGH
+ {
+ break;
+ }
+ }
+
+ for( TreeNode::ConstIterator it = node->CBegin(), endIt = node->CEnd(); it != endIt; ++it )
+ {
+ const TreeNode::KeyNodePair& pair = *it;
+ CreateFontStyleMap( &pair.second, map );
+ }
+}
+
+/**
+ * @brief Parses the font's style string.
+ *
+ * @param[in] style The font's style string.
+ * @param[out] map A map with the font's style parameters.
+ *
+ */
+void ParseFontStyleString( const std::string& style, Property::Map& map )
+{
+ Toolkit::JsonParser parser = Toolkit::JsonParser::New();
+
+ if( parser.Parse( style ) )
+ {
+ const TreeNode* const node = parser.GetRoot();
+
+ CreateFontStyleMap( node, map );
+ }
+}
+
+void SetFontStyleProperty( ControllerPtr controller, const Property::Value& value )
+{
+ if( controller )
+ {
+ const std::string style = value.Get< std::string >();
+
+ // Stores the string to be recovered by the GetFontStyleProperty() function.
+ controller->SetDefaultFontStyle( style );
+
+ // Parses and applies the style.
+ Property::Map map;
+ ParseFontStyleString( style, map );
+
+ if( !map.Empty() )
+ {
+ /// Width key
+ Property::Value* widthValue = map.Find( WIDTH_KEY );
+
+ if( widthValue )
+ {
+ const std::string widthStr = widthValue->Get<std::string>();
+
+ FontWidth width = TextAbstraction::FontWidth::NORMAL;
+ if( Scripting::GetEnumeration< FontWidth >( widthStr.c_str(),
+ FONT_WIDTH_STRING_TABLE,
+ FONT_WIDTH_STRING_TABLE_COUNT,
+ width ) )
+ {
+ if( controller->GetDefaultFontWidth() != width )
+ {
+ controller->SetDefaultFontWidth( width );
+ }
+ }
+ }
+ else
+ {
+ controller->SetDefaultFontWidth( TextAbstraction::FontWidth::NORMAL );
+ }
+
+ /// Weight key
+ Property::Value* weightValue = map.Find( WEIGHT_KEY );
+
+ if( weightValue )
+ {
+ const std::string weightStr = weightValue->Get<std::string>();
+
+ FontWeight weight = TextAbstraction::FontWeight::NORMAL;
+ if( Scripting::GetEnumeration< FontWeight >( weightStr.c_str(),
+ FONT_WEIGHT_STRING_TABLE,
+ FONT_WEIGHT_STRING_TABLE_COUNT,
+ weight ) )
+ {
+ if( controller->GetDefaultFontWeight() != weight )
+ {
+ controller->SetDefaultFontWeight( weight );
+ }
+ }
+ }
+ else
+ {
+ controller->SetDefaultFontWeight( TextAbstraction::FontWeight::NORMAL );
+ }
+
+ /// Slant key
+ Property::Value* slantValue = map.Find( SLANT_KEY );
+
+ if( slantValue )
+ {
+ const std::string slantStr = slantValue->Get<std::string>();
+
+ FontSlant slant = TextAbstraction::FontSlant::NORMAL;
+ if( Scripting::GetEnumeration< FontSlant >( slantStr.c_str(),
+ FONT_SLANT_STRING_TABLE,
+ FONT_SLANT_STRING_TABLE_COUNT,
+ slant ) )
+ {
+ if( controller->GetDefaultFontSlant() != slant )
+ {
+ controller->SetDefaultFontSlant( slant );
+ }
+ }
+ }
+ else
+ {
+ controller->SetDefaultFontSlant( TextAbstraction::FontSlant::NORMAL );
+ }
+ }
+ }
+}
+
+void GetFontStyleProperty( ControllerPtr controller, Property::Value& value )
+{
+ if( controller )
+ {
+ value = controller->GetDefaultFontStyle();
+ }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_FONT_STYLE_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_FONT_STYLE_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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/scripting/scripting.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+const Scripting::StringEnum FONT_WIDTH_STRING_TABLE[] =
+{
+ { "ultra-condensed", TextAbstraction::FontWidth::ULTRA_CONDENSED },
+ { "extra-condensed", TextAbstraction::FontWidth::EXTRA_CONDENSED },
+ { "condensed", TextAbstraction::FontWidth::CONDENSED },
+ { "semi-condensed", TextAbstraction::FontWidth::SEMI_CONDENSED },
+ { "normal", TextAbstraction::FontWidth::NORMAL },
+ { "semi-expanded", TextAbstraction::FontWidth::SEMI_EXPANDED },
+ { "expanded", TextAbstraction::FontWidth::EXPANDED },
+ { "extra-expanded", TextAbstraction::FontWidth::EXTRA_EXPANDED },
+ { "ultra-expanded", TextAbstraction::FontWidth::ULTRA_EXPANDED },
+};
+const unsigned int FONT_WIDTH_STRING_TABLE_COUNT = sizeof( FONT_WIDTH_STRING_TABLE ) / sizeof( FONT_WIDTH_STRING_TABLE[0] );
+
+const Scripting::StringEnum FONT_WEIGHT_STRING_TABLE[] =
+{
+ { "thin", TextAbstraction::FontWeight::THIN },
+ { "ultra-light", TextAbstraction::FontWeight::ULTRA_LIGHT },
+ { "extra-light", TextAbstraction::FontWeight::EXTRA_LIGHT },
+ { "light", TextAbstraction::FontWeight::LIGHT },
+ { "demi-light", TextAbstraction::FontWeight::DEMI_LIGHT },
+ { "semi-light", TextAbstraction::FontWeight::SEMI_LIGHT },
+ { "book", TextAbstraction::FontWeight::BOOK },
+ { "normal", TextAbstraction::FontWeight::NORMAL },
+ { "regular", TextAbstraction::FontWeight::REGULAR },
+ { "medium", TextAbstraction::FontWeight::MEDIUM },
+ { "demi-bold", TextAbstraction::FontWeight::DEMI_BOLD },
+ { "semi-bold", TextAbstraction::FontWeight::SEMI_BOLD },
+ { "bold", TextAbstraction::FontWeight::BOLD },
+ { "ultra-bold", TextAbstraction::FontWeight::ULTRA_BOLD },
+ { "extra-bold", TextAbstraction::FontWeight::EXTRA_BOLD },
+ { "black", TextAbstraction::FontWeight::BLACK },
+ { "heavy", TextAbstraction::FontWeight::HEAVY },
+ { "extra-black", TextAbstraction::FontWeight::EXTRA_BLACK }
+};
+const unsigned int FONT_WEIGHT_STRING_TABLE_COUNT = sizeof( FONT_WEIGHT_STRING_TABLE ) / sizeof( FONT_WEIGHT_STRING_TABLE[0] );
+
+const Scripting::StringEnum FONT_SLANT_STRING_TABLE[] =
+{
+ { "normal", TextAbstraction::FontSlant::NORMAL },
+ { "roman", TextAbstraction::FontSlant::ROMAN },
+ { "italic", TextAbstraction::FontSlant::ITALIC },
+ { "oblique", TextAbstraction::FontSlant::OBLIQUE }
+};
+const unsigned int FONT_SLANT_STRING_TABLE_COUNT = sizeof( FONT_SLANT_STRING_TABLE ) / sizeof( FONT_SLANT_STRING_TABLE[0] );
+
+/**
+ * @brief Sets the font's style property.
+ *
+ * @param[in] controller The text's controller.
+ * @param[in] value The value of the font's style.
+ *
+ */
+void SetFontStyleProperty( ControllerPtr controller, const Property::Value& value );
+
+/**
+ * @brief Retrieves the font's style property.
+ *
+ * @param[in] controller The text's controller.
+ * @param[out] value The value of the font's style.
+ */
+void GetFontStyleProperty( ControllerPtr controller, Property::Value& value );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_FONT_STYLE_H__
#include <dali-toolkit/internal/controls/text-controls/text-label-impl.h>
// EXTERNAL INCLUDES
-#include <dali/public-api/object/type-registry.h>
#include <dali/devel-api/object/type-registry-helper.h>
-#include <dali/devel-api/scripting/scripting.h>
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/text/rendering-backend.h>
-#include <dali-toolkit/internal/text/layouts/layout-engine.h>
+#include <dali-toolkit/internal/controls/text-controls/text-font-style.h>
#include <dali-toolkit/internal/text/rendering/text-backend.h>
#include <dali-toolkit/internal/text/text-view.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
{
const std::string fontFamily = value.Get< std::string >();
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetProperty Property::FONT_FAMILY newFont(%s)\n", fontFamily.c_str() );
if( impl.mController->GetDefaultFontFamily() != fontFamily )
{
- impl.mController->SetDefaultFontFamily( fontFamily );
+ impl.mController->SetDefaultFontFamily( fontFamily, true );
}
}
break;
}
case Toolkit::TextLabel::Property::FONT_STYLE:
{
- if( impl.mController )
- {
- const std::string fontStyle = value.Get< std::string >();
-
- if( impl.mController->GetDefaultFontStyle() != fontStyle )
- {
- impl.mController->SetDefaultFontStyle( fontStyle );
- }
- }
+ SetFontStyleProperty( impl.mController, value );
break;
}
case Toolkit::TextLabel::Property::POINT_SIZE:
}
case Toolkit::TextLabel::Property::FONT_STYLE:
{
- if( impl.mController )
- {
- value = impl.mController->GetDefaultFontStyle();
- }
+ GetFontStyleProperty( impl.mController, value );
break;
}
case Toolkit::TextLabel::Property::POINT_SIZE:
{
case StyleChange::DEFAULT_FONT_CHANGE:
{
- DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnStyleChange StyleChange::DEFAULT_FONT_CHANGE\n");
- if ( mController->GetDefaultFontFamily() == "" )
- {
- // Property system did not set the font so should update it.
- // todo instruct text-controller to update model
- }
+ // Property system did not set the font so should update it.
+ std::string newFont = styleManager.GetDefaultFontFamily();
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnStyleChange StyleChange::DEFAULT_FONT_CHANGE newFont(%s)\n", newFont.c_str() );
+ mController->UpdateAfterFontChange( newFont );
break;
}
#include <dali/public-api/math/vector4.h>
#include <dali/public-api/object/property-map.h>
#include <dali/devel-api/object/type-registry-helper.h>
+#include <dali/integration-api/debug.h>
#include <libintl.h>
#include <cfloat>
namespace
{
// todo Move this to adaptor??
-#define GET_LOCALE_TEXT(string) dgettext("elementary", string)
+#define GET_LOCALE_TEXT(string) dgettext("sys_string", string)
const std::string TEXT_SELECTION_POPUP_BUTTON_STYLE_NAME( "textselectionpopupbutton" );
const Dali::Vector4 DEFAULT_OPTION_PRESSED_COLOR( Dali::Vector4( 0.24f, 0.72f, 0.8f, 1.0f ) );
+#if defined(DEBUG_ENABLED)
+ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
+#endif
+
#ifdef DGETTEXT_ENABLED
#define POPUP_CUT_STRING GET_LOCALE_TEXT("IDS_COM_BODY_CUT")
Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New( TextSelectionPopupCallbackInterface* callbackInterface )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextSelectionPopup::New\n" );
+
// Create the implementation, temporarily owned by this handle on stack
IntrusivePtr< TextSelectionPopup > impl = new TextSelectionPopup( callbackInterface );
void TextSelectionPopup::OnInitialize()
{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::OnInitialize\n" );
Actor self = Self();
self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
self.SetProperty( Actor::Property::COLOR_ALPHA, 0.0f );
void TextSelectionPopup::OnStageConnection( int depth )
{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::OnStageConnection\n" );
// Call the Control::OnStageConnection() to set the depth of the background.
Control::OnStageConnection( depth );
Actor self = Self();
if ( !mPopupShowing ) // During the Hide/Fade animation there could be a call to Show the Popup again, mPopupShowing will be true in this case.
{
- UnparentAndReset( self ); // Popup needs to be shown so do not unparent
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::HideAnimationFinished\n" );
+ UnparentAndReset( mToolbar );
}
}
void TextSelectionPopup::AddOption( const ButtonRequirement& button, bool showDivider, bool showIcons, bool showCaption )
{
// 1. Create a option.
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::AddOption\n" );
+
Toolkit::PushButton option = Toolkit::PushButton::New();
option.SetName( button.name );
option.SetAnimationTime( 0.0f );
void TextSelectionPopup::AddPopupOptionsToToolbar( bool showIcons, bool showCaptions )
{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "TextSelectionPopup::AddPopupOptionsToToolbar\n" );
+
CreateOrderedListOfPopupOptions();
mButtonsChanged = false;
$(toolkit_src_dir)/controls/super-blur-view/super-blur-view-impl.cpp \
$(toolkit_src_dir)/controls/table-view/table-view-impl.cpp \
$(toolkit_src_dir)/controls/text-controls/text-field-impl.cpp \
+ $(toolkit_src_dir)/controls/text-controls/text-font-style.cpp \
$(toolkit_src_dir)/controls/text-controls/text-label-impl.cpp \
$(toolkit_src_dir)/controls/text-controls/text-selection-popup-impl.cpp \
$(toolkit_src_dir)/controls/text-controls/text-selection-toolbar-impl.cpp \
StyleManager::StyleManager()
: mOrientationDegrees( 0 ), // Portrait
mDefaultFontSize( -1 ),
+ mDefaultFontFamily(""),
mThemeFile( DEFAULT_THEME ),
mFeedbackStyle( NULL )
{
}
}
+std::string StyleManager::GetDefaultFontFamily() const
+{
+ return mDefaultFontFamily;
+}
+
Orientation StyleManager::GetOrientation()
{
return mOrientation;
{
case StyleChange::DEFAULT_FONT_CHANGE:
{
+ mDefaultFontFamily = styleMonitor.GetDefaultFontFamily();
break;
}
Orientation GetOrientation();
/**
+ * @copydoc Toolkit::StyleManager::GetDefaultFontFamily
+ */
+ std::string GetDefaultFontFamily() const;
+
+ /**
* @copydoc Toolkit::StyleManager::SetStyleConstant
*/
void SetStyleConstant( const std::string& key, const Property::Value& value );
int mDefaultFontSize; ///< Logical size, not a point-size
+ std::string mDefaultFontFamily;
+
std::string mThemeFile; ///< The full path of the current theme file
Property::Map mThemeBuilderConstants; ///< Contants to give the theme builder
originY + boundingRectangle.height );
}
+void WorldToLocalCoordinatesBoundingBox( const Dali::Vector4& boundingBox, Dali::Rect<int>& boundingRectangle )
+{
+ // Convert to local coordinates and store as a Dali::Rect.
+ Dali::Vector2 stageSize = Dali::Stage::GetCurrent().GetSize();
+
+ boundingRectangle.x = boundingBox.x + 0.5f * stageSize.width;
+ boundingRectangle.y = boundingBox.y + 0.5f * stageSize.height;
+ boundingRectangle.width = boundingBox.z - boundingBox.x;
+ boundingRectangle.height = boundingBox.w - boundingBox.y;
+}
} // end of namespace
{
HandleImpl()
: position(),
+ size(),
lineHeight( 0.0f ),
grabDisplacementX( 0.f ),
grabDisplacementY( 0.f ),
active( false ),
visible( false ),
pressed( false ),
- flipped( false )
+ horizontallyFlipped( false ),
+ verticallyFlipped( false )
{
}
ImageActor markerActor;
Vector2 position;
- float lineHeight; ///< Not the handle height
- float grabDisplacementX;
- float grabDisplacementY;
- bool active : 1;
- bool visible : 1;
- bool pressed : 1;
- bool flipped : 1;
+ Size size;
+ float lineHeight; ///< Not the handle height
+ float grabDisplacementX;
+ float grabDisplacementY;
+ bool active : 1;
+ bool visible : 1;
+ bool pressed : 1;
+ bool horizontallyFlipped : 1; ///< Whether the handle has been horizontally flipped.
+ bool verticallyFlipped : 1; ///< Whether the handle has been vertically flipped.
};
struct PopupImpl
mEnabledPopupButtons( TextSelectionPopup::NONE ),
mTextSelectionPopupCallbackInterface( callbackInterface ),
mHandleColor( HANDLE_COLOR ),
- mBoundingBox( Rect<int>() ),
+ mBoundingBox(),
mHighlightColor( LIGHT_BLUE ),
mHighlightPosition( Vector2::ZERO ),
mActiveCursor( ACTIVE_CURSOR_NONE ),
mDelayCursorBlink( false ),
mPrimaryCursorVisible( false ),
mSecondaryCursorVisible( false ),
- mSwapSelectionHandles( false ),
+ mFlipSelectionHandlesOnCross( false ),
+ mFlipLeftSelectionHandleDirection( false ),
+ mFlipRightSelectionHandleDirection( false ),
+ mHandlePanning( false ),
+ mHandleCurrentCrossed( false ),
+ mHandlePreviousCrossed( false ),
mNotifyEndOfScroll( false )
{
mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
mQuadIndexFormat[ "indices" ] = Property::INTEGER;
mHighlightMaterial = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
+
+ SetupTouchEvents();
}
/**
mPrimaryCursorVisible = ( cursor.position.x <= size.width ) && ( cursor.position.x >= 0.f );
if( mPrimaryCursorVisible )
{
- Vector2 position = cursor.position;
+ const Vector2& position = cursor.position;
mPrimaryCursor.SetPosition( position.x,
position.y );
HandleImpl& grabHandle = mHandle[GRAB_HANDLE];
if( grabHandle.active )
{
- Vector2 position = grabHandle.position;
+ const Vector2& position = grabHandle.position;
const bool isVisible = ( position.x <= size.width ) && ( position.x >= 0.f );
if( isVisible )
{
- SetupTouchEvents();
-
CreateGrabHandle();
- grabHandle.actor.SetPosition( position.x - floor( 0.5f * mCursorWidth ),
- position.y + grabHandle.lineHeight ); // TODO : Fix for multiline.
+ // Sets the grab handle position and calculate if it needs to be vertically flipped if it exceeds the boundary box.
+ SetGrabHandlePosition();
+
+ // Sets the grab handle image according if it's pressed, flipped, etc.
+ SetHandleImage( GRAB_HANDLE );
}
grabHandle.actor.SetVisible( isVisible );
}
HandleImpl& secondary = mHandle[ RIGHT_SELECTION_HANDLE ];
if( primary.active || secondary.active )
{
- Vector2 primaryPosition = primary.position;
- Vector2 secondaryPosition = secondary.position;
+ const Vector2& primaryPosition = primary.position;
+ const Vector2& secondaryPosition = secondary.position;
const bool isPrimaryVisible = ( primaryPosition.x <= size.width ) && ( primaryPosition.x >= 0.f );
const bool isSecondaryVisible = ( secondaryPosition.x <= size.width ) && ( secondaryPosition.x >= 0.f );
if( isPrimaryVisible || isSecondaryVisible )
{
- SetupTouchEvents();
-
CreateSelectionHandles();
if( isPrimaryVisible )
{
- primary.actor.SetPosition( primaryPosition.x,
- primaryPosition.y + primary.lineHeight ); // TODO : Fix for multiline.
+ SetSelectionHandlePosition( LEFT_SELECTION_HANDLE );
+
+ // Sets the primary handle image according if it's pressed, flipped, etc.
+ SetHandleImage( LEFT_SELECTION_HANDLE );
SetSelectionHandleMarkerSize( primary );
}
if( isSecondaryVisible )
{
- secondary.actor.SetPosition( secondaryPosition.x,
- secondaryPosition.y + secondary.lineHeight ); // TODO : Fix for multiline.
+ SetSelectionHandlePosition( RIGHT_SELECTION_HANDLE );
+
+ // Sets the secondary handle image according if it's pressed, flipped, etc.
+ SetHandleImage( RIGHT_SELECTION_HANDLE );
SetSelectionHandleMarkerSize( secondary );
}
mHandle[ LEFT_SELECTION_HANDLE ].position += scrollOffset;
mHandle[ RIGHT_SELECTION_HANDLE ].position += scrollOffset;
mHighlightPosition += scrollOffset;
- DeterminePositionPopup();
}
void ShowPopup()
void SetupTouchEvents()
{
- if ( !mTapDetector )
- {
- mTapDetector = TapGestureDetector::New();
- mTapDetector.DetectedSignal().Connect( this, &Decorator::Impl::OnTap );
- }
+ mTapDetector = TapGestureDetector::New();
+ mTapDetector.DetectedSignal().Connect( this, &Decorator::Impl::OnTap );
- if ( !mPanGestureDetector )
- {
- mPanGestureDetector = PanGestureDetector::New();
- mPanGestureDetector.DetectedSignal().Connect( this, &Decorator::Impl::OnPan );
- }
+ mPanGestureDetector = PanGestureDetector::New();
+ mPanGestureDetector.DetectedSignal().Connect( this, &Decorator::Impl::OnPan );
}
void CreateActiveLayer()
{
if ( handle.markerActor )
{
- handle.markerActor.SetResizePolicy ( ResizePolicy::FIXED, Dimension::HEIGHT );
handle.markerActor.SetSize( 0, handle.lineHeight );
}
}
{
if( !mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] )
{
- mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_GRAB_HANDLE_IMAGE_RELEASED );
+ SetHandleImage( GRAB_HANDLE, HANDLE_IMAGE_RELEASED, ResourceImage::New( DEFAULT_GRAB_HANDLE_IMAGE_RELEASED ) );
}
grabHandle.actor = ImageActor::New( mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] );
void CreateHandleMarker( HandleImpl& handle, Image& image, HandleType handleType )
{
- if ( image)
+ if ( image )
{
handle.markerActor = ImageActor::New( image );
handle.markerActor.SetColor( mHandleColor );
handle.actor.Add( handle.markerActor );
+ handle.markerActor.SetResizePolicy ( ResizePolicy::FIXED, Dimension::HEIGHT );
+
if ( LEFT_SELECTION_HANDLE == handleType )
{
handle.markerActor.SetAnchorPoint( AnchorPoint::BOTTOM_RIGHT );
#endif
primary.actor.SetAnchorPoint( AnchorPoint::TOP_RIGHT ); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text.
primary.actor.SetSortModifier( DECORATION_DEPTH_INDEX );
- primary.flipped = false;
primary.actor.SetColor( mHandleColor );
primary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move
#endif
secondary.actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); // Change to BOTTOM_LEFT if Look'n'Feel requires handle above text.
secondary.actor.SetSortModifier( DECORATION_DEPTH_INDEX );
- secondary.flipped = false;
secondary.actor.SetColor( mHandleColor );
secondary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move
}
}
+ void CalculateHandleWorldCoordinates( HandleImpl& handle, Vector2& position )
+ {
+ // Get the world position of the active layer
+ const Vector3 parentWorldPosition = mActiveLayer.GetCurrentWorldPosition();
+
+ // Get the size of the UI control.
+ Vector2 targetSize;
+ mController.GetTargetSize( targetSize );
+
+ // The grab handle position in world coords.
+ position.x = parentWorldPosition.x - 0.5f * targetSize.width + handle.position.x;
+ position.y = parentWorldPosition.y - 0.5f * targetSize.height + handle.position.y + handle.lineHeight;
+ }
+
+ void SetGrabHandlePosition()
+ {
+ // Reference to the grab handle.
+ HandleImpl& grabHandle = mHandle[GRAB_HANDLE];
+
+ // The grab handle position in world coords.
+ Vector2 grabHandleWorldPosition;
+ CalculateHandleWorldCoordinates( grabHandle, grabHandleWorldPosition );
+
+ // Check if the grab handle exceeds the boundaries of the decoration box.
+ // At the moment only the height is checked for the grab handle.
+ grabHandle.verticallyFlipped = ( grabHandleWorldPosition.y + grabHandle.size.height > mBoundingBox.w );
+
+ // The grab handle 'y' position in local coords.
+ // If the grab handle exceeds the bottom of the decoration box,
+ // set the 'y' position to the top of the line.
+ // The SetGrabHandleImage() method will change the orientation.
+ const float yLocalPosition = grabHandle.verticallyFlipped ? grabHandle.position.y : grabHandle.position.y + grabHandle.lineHeight;
+
+ grabHandle.actor.SetPosition( grabHandle.position.x - floor( 0.5f * mCursorWidth ),
+ yLocalPosition ); // TODO : Fix for multiline.
+ }
+
+ void SetSelectionHandlePosition( HandleType type )
+ {
+ const bool isPrimaryHandle = LEFT_SELECTION_HANDLE == type;
+
+ // Reference to the selection handle.
+ HandleImpl& handle = mHandle[type];
+
+ // Get the world coordinates of the handle position.
+ Vector2 handleWorldPosition;
+ CalculateHandleWorldCoordinates( handle, handleWorldPosition );
+
+ // Whether to flip the handle.
+ bool flipHandle = isPrimaryHandle ? mFlipLeftSelectionHandleDirection : mFlipRightSelectionHandleDirection;
+
+ // Whether to flip the handles if they are crossed.
+ bool crossFlip = false;
+ if( mFlipSelectionHandlesOnCross || !mHandlePanning )
+ {
+ crossFlip = mHandleCurrentCrossed;
+ }
+
+ // Does not flip if both conditions are true (double flip)
+ flipHandle = flipHandle != ( crossFlip || mHandlePreviousCrossed );
+
+ // Check if the selection handle exceeds the boundaries of the decoration box.
+ const bool exceedsLeftEdge = ( isPrimaryHandle ? !flipHandle : flipHandle ) && ( handleWorldPosition.x - handle.size.width < mBoundingBox.x );
+
+ const bool exceedsRightEdge = ( isPrimaryHandle ? flipHandle : !flipHandle ) && ( handleWorldPosition.x + handle.size.width > mBoundingBox.z );
+
+ // Does not flip if both conditions are true (double flip)
+ flipHandle = flipHandle != ( exceedsLeftEdge || exceedsRightEdge );
+
+ if( flipHandle )
+ {
+ if( !handle.horizontallyFlipped )
+ {
+ // Change the anchor point to flip the image.
+ handle.actor.SetAnchorPoint( isPrimaryHandle ? AnchorPoint::TOP_LEFT : AnchorPoint::TOP_RIGHT );
+
+ handle.horizontallyFlipped = true;
+ }
+ }
+ else
+ {
+ if( handle.horizontallyFlipped )
+ {
+ // Reset the anchor point.
+ handle.actor.SetAnchorPoint( isPrimaryHandle ? AnchorPoint::TOP_RIGHT : AnchorPoint::TOP_LEFT );
+
+ handle.horizontallyFlipped = false;
+ }
+ }
+
+ // Whether to flip the handle vertically.
+ handle.verticallyFlipped = ( handleWorldPosition.y + handle.size.height > mBoundingBox.w );
+
+ // The primary selection handle 'y' position in local coords.
+ // If the handle exceeds the bottom of the decoration box,
+ // set the 'y' position to the top of the line.
+ // The SetHandleImage() method will change the orientation.
+ const float yLocalPosition = handle.verticallyFlipped ? handle.position.y : handle.position.y + handle.lineHeight;
+
+ handle.actor.SetPosition( handle.position.x,
+ yLocalPosition ); // TODO : Fix for multiline.
+ }
+
+ void SetHandleImage( HandleType type )
+ {
+ HandleImpl& handle = mHandle[type];
+
+ HandleType markerType = HANDLE_TYPE_COUNT;
+ // If the selection handle is flipped it chooses the image of the other selection handle. Does nothing for the grab handle.
+ if( LEFT_SELECTION_HANDLE == type )
+ {
+ type = handle.horizontallyFlipped ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE;
+ markerType = handle.horizontallyFlipped ? RIGHT_SELECTION_HANDLE_MARKER : LEFT_SELECTION_HANDLE_MARKER;
+ }
+ else if( RIGHT_SELECTION_HANDLE == type )
+ {
+ type = handle.horizontallyFlipped ? LEFT_SELECTION_HANDLE : RIGHT_SELECTION_HANDLE;
+ markerType = handle.horizontallyFlipped ? LEFT_SELECTION_HANDLE_MARKER : RIGHT_SELECTION_HANDLE_MARKER;
+ }
+
+ // Chooses between the released or pressed image. It checks whether the pressed image exists.
+ const HandleImageType imageType = ( handle.pressed ? ( mHandleImages[type][HANDLE_IMAGE_PRESSED] ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED ) : HANDLE_IMAGE_RELEASED );
+
+ handle.actor.SetImage( mHandleImages[type][imageType] );
+
+ if( HANDLE_TYPE_COUNT != markerType )
+ {
+ const HandleImageType markerImageType = ( handle.pressed ? ( mHandleImages[markerType][HANDLE_IMAGE_PRESSED] ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED ) : HANDLE_IMAGE_RELEASED );
+ handle.markerActor.SetImage( mHandleImages[markerType][markerImageType] );
+ }
+
+ // Whether to flip the handle vertically.
+ handle.actor.SetOrientation( handle.verticallyFlipped ? ANGLE_180 : ANGLE_0, Vector3::XAXIS );
+ }
+
void CreateHighlight()
{
if( !mHighlightActor )
StopScrollTimer();
mController.DecorationEvent( type, HANDLE_PRESSED, x, y );
}
+
+ mHandlePanning = true;
}
else if( Gesture::Finished == gesture.state ||
Gesture::Cancelled == gesture.state )
mController.DecorationEvent( type, HANDLE_RELEASED, x, y );
}
- if( GRAB_HANDLE == type )
- {
- handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_RELEASED] );
- }
- else
- {
- HandleType selectionHandleType = type;
-
- if( mSwapSelectionHandles != handle.flipped )
- {
- selectionHandleType = ( LEFT_SELECTION_HANDLE == type ) ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE;
- }
-
- handle.actor.SetImage( mHandleImages[selectionHandleType][HANDLE_IMAGE_RELEASED] );
- }
+ handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_RELEASED] );
handle.pressed = false;
+
+ mHandlePanning = false;
}
}
if( TouchPoint::Down == point.state )
{
mHandle[GRAB_HANDLE].pressed = true;
- Image imagePressed = mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED];
- if( imagePressed )
- {
- mHandle[GRAB_HANDLE].actor.SetImage( imagePressed );
- }
}
else if( ( TouchPoint::Up == point.state ) ||
( TouchPoint::Interrupted == point.state ) )
{
mHandle[GRAB_HANDLE].pressed = false;
- Image imageReleased = mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED];
- if( imageReleased )
- {
- mHandle[GRAB_HANDLE].actor.SetImage( imageReleased );
- }
}
+
+ SetHandleImage( GRAB_HANDLE );
}
// Consume to avoid pop-ups accidentally closing, when handle is outside of pop-up area
{
const TouchPoint& point = event.GetPoint(0);
- const bool flip = mSwapSelectionHandles != mHandle[LEFT_SELECTION_HANDLE].flipped;
if( TouchPoint::Down == point.state )
{
mHandle[LEFT_SELECTION_HANDLE].pressed = true;
- Image imagePressed = mHandleImages[flip ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED];
- if( imagePressed )
- {
- mHandle[LEFT_SELECTION_HANDLE].actor.SetImage( imagePressed );
- }
}
else if( ( TouchPoint::Up == point.state ) ||
( TouchPoint::Interrupted == point.state ) )
{
mHandle[LEFT_SELECTION_HANDLE].pressed = false;
- Image imageReleased = mHandleImages[flip ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED];
- if( imageReleased )
- {
- mHandle[LEFT_SELECTION_HANDLE].actor.SetImage( imageReleased );
- }
+ mHandlePreviousCrossed = mHandleCurrentCrossed;
+ mHandlePanning = false;
}
+
+ SetHandleImage( LEFT_SELECTION_HANDLE );
}
// Consume to avoid pop-ups accidentally closing, when handle is outside of pop-up area
{
const TouchPoint& point = event.GetPoint(0);
- const bool flip = mSwapSelectionHandles != mHandle[RIGHT_SELECTION_HANDLE].flipped;
if( TouchPoint::Down == point.state )
{
- Image imagePressed = mHandleImages[flip ? LEFT_SELECTION_HANDLE : RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED];
mHandle[RIGHT_SELECTION_HANDLE].pressed = true;
- if( imagePressed )
- {
- mHandle[RIGHT_SELECTION_HANDLE].actor.SetImage( imagePressed );
- }
}
else if( ( TouchPoint::Up == point.state ) ||
( TouchPoint::Interrupted == point.state ) )
{
- Image imageReleased = mHandleImages[flip ? LEFT_SELECTION_HANDLE : RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED];
mHandle[RIGHT_SELECTION_HANDLE].pressed = false;
- if( imageReleased )
- {
- mHandle[RIGHT_SELECTION_HANDLE].actor.SetImage( imageReleased );
- }
+ mHandlePreviousCrossed = mHandleCurrentCrossed;
+ mHandlePanning = false;
}
+
+ SetHandleImage( RIGHT_SELECTION_HANDLE );
}
// Consume to avoid pop-ups accidentally closing, when handle is outside of pop-up area
// Exceeding vertical boundary
- Vector4 worldCoordinatesBoundingBox;
- LocalToWorldCoordinatesBoundingBox( mBoundingBox, worldCoordinatesBoundingBox );
-
float popupHeight = mCopyPastePopup.actor.GetRelayoutSize( Dimension::HEIGHT);
PropertyNotification verticalExceedNotification = mCopyPastePopup.actor.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y,
- OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight * 0.5f,
- worldCoordinatesBoundingBox.w - popupHeight * 0.5f ) );
+ OutsideCondition( mBoundingBox.y + popupHeight * 0.5f,
+ mBoundingBox.w - popupHeight * 0.5f ) );
verticalExceedNotification.NotifySignal().Connect( this, &Decorator::Impl::PopUpLeavesVerticalBoundary );
}
- void GetConstrainedPopupPosition( Vector3& requiredPopupPosition, Vector3& popupSize, Vector3 anchorPoint, Actor& parent, Rect<int>& boundingBox )
+ void GetConstrainedPopupPosition( Vector3& requiredPopupPosition, Vector3& popupSize, Vector3 anchorPoint, Actor& parent, const Vector4& boundingRectangleWorld )
{
DALI_ASSERT_DEBUG ( "Popup parent not on stage" && parent.OnStage() )
Vector3 popupWorldPosition = parentWorldPositionLeftAnchor + requiredPopupPosition; // Parent World position plus popup local position gives World Position
Vector3 popupDistanceFromAnchorPoint = popupSize*anchorPoint;
- // Bounding rectangle is supplied as screen coordinates, bounding will be done in world coordinates.
- Vector4 boundingRectangleWorld;
- LocalToWorldCoordinatesBoundingBox( boundingBox, boundingRectangleWorld );
-
// Calculate distance to move popup (in local space) so fits within the boundary
float xOffSetToKeepWithinBounds = 0.0f;
if( popupWorldPosition.x - popupDistanceFromAnchorPoint.x < boundingRectangleWorld.x )
// Prevent pixel mis-alignment by rounding down.
requiredPopupPosition.x = static_cast<int>( requiredPopupPosition.x );
requiredPopupPosition.y = static_cast<int>( requiredPopupPosition.y );
-
}
- void FlipSelectionHandleImages()
+ void SetHandleImage( HandleType handleType, HandleImageType handleImageType, Dali::Image image )
{
- SetupTouchEvents();
-
- CreateSelectionHandles();
-
- HandleImpl& leftHandle = mHandle[LEFT_SELECTION_HANDLE];
- HandleImpl& rightHandle = mHandle[RIGHT_SELECTION_HANDLE];
-
- // If handle pressed and pressed image exists then use pressed image else stick with released image
- const HandleImageType leftImageType = ( leftHandle.pressed && mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] ) ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED;
- const HandleImageType rightImageType = ( rightHandle.pressed && mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] ) ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED;
+ HandleImpl& handle = mHandle[handleType];
+ handle.size = Size( image.GetWidth(), image.GetHeight() );
- const bool leftFlipped = mSwapSelectionHandles != leftHandle.flipped;
- const bool rightFlipped = mSwapSelectionHandles != rightHandle.flipped;
-
- leftHandle.actor.SetImage( leftFlipped ? mHandleImages[RIGHT_SELECTION_HANDLE][leftImageType] : mHandleImages[LEFT_SELECTION_HANDLE][leftImageType] );
-
- leftHandle.actor.SetAnchorPoint( leftFlipped ? AnchorPoint::TOP_LEFT : AnchorPoint::TOP_RIGHT );
-
- rightHandle.actor.SetImage( rightFlipped ? mHandleImages[LEFT_SELECTION_HANDLE][rightImageType] : mHandleImages[RIGHT_SELECTION_HANDLE][rightImageType] );
-
- rightHandle.actor.SetAnchorPoint( rightFlipped ? AnchorPoint::TOP_RIGHT : AnchorPoint::TOP_LEFT );
-
- if ( leftHandle.markerActor )
- {
- leftHandle.markerActor.SetImage( leftFlipped ? mHandleImages[RIGHT_SELECTION_HANDLE_MARKER][leftImageType] : mHandleImages[LEFT_SELECTION_HANDLE_MARKER][leftImageType] );
- }
- if ( rightHandle.markerActor )
- {
- rightHandle.markerActor.SetImage( rightFlipped ? mHandleImages[LEFT_SELECTION_HANDLE_MARKER][rightImageType] : mHandleImages[RIGHT_SELECTION_HANDLE_MARKER][rightImageType] );
- }
+ mHandleImages[handleType][handleImageType] = image;
}
void SetScrollThreshold( float threshold )
Geometry mQuadGeometry;
QuadContainer mHighlightQuadList; ///< Sub-selections that combine to create the complete selection highlight
- Rect<int> mBoundingBox;
+ Vector4 mBoundingBox; ///< The bounding box in world coords.
Vector4 mHighlightColor; ///< Color of the highlight
Vector2 mHighlightPosition; ///< The position of the highlight actor.
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.
- bool mDelayCursorBlink : 1; ///< Used to avoid cursor blinking when entering text.
- bool mPrimaryCursorVisible : 1; ///< Whether the primary cursor is visible.
- bool mSecondaryCursorVisible : 1; ///< Whether the secondary cursor is visible.
- bool mSwapSelectionHandles : 1; ///< Whether to swap the selection handle images.
- bool mNotifyEndOfScroll : 1; ///< Whether to notify the end of the scroll.
+ bool mActiveCopyPastePopup : 1;
+ bool mCursorBlinkStatus : 1; ///< Flag to switch between blink on and blink off.
+ bool mDelayCursorBlink : 1; ///< Used to avoid cursor blinking when entering text.
+ bool mPrimaryCursorVisible : 1; ///< Whether the primary cursor is visible.
+ bool mSecondaryCursorVisible : 1; ///< Whether the secondary cursor is visible.
+ bool mFlipSelectionHandlesOnCross : 1; ///< Whether to flip the selection handles as soon as they cross.
+ bool mFlipLeftSelectionHandleDirection : 1; ///< Whether to flip the left selection handle image because of the character's direction.
+ bool mFlipRightSelectionHandleDirection : 1; ///< Whether to flip the right selection handle image because of the character's direction.
+ bool mHandlePanning : 1; ///< Whether any of the handles is moving.
+ bool mHandleCurrentCrossed : 1; ///< Whether the handles are crossed.
+ bool mHandlePreviousCrossed : 1; ///< Whether the handles where crossed at the last handle touch up.
+ bool mNotifyEndOfScroll : 1; ///< Whether to notify the end of the scroll.
};
DecoratorPtr Decorator::New( ControllerInterface& controller,
void Decorator::SetBoundingBox( const Rect<int>& boundingBox )
{
- mImpl->mBoundingBox = boundingBox;
+ LocalToWorldCoordinatesBoundingBox( boundingBox, mImpl->mBoundingBox );
}
-const Rect<int>& Decorator::GetBoundingBox() const
+void Decorator::GetBoundingBox( Rect<int>& boundingBox ) const
{
- return mImpl->mBoundingBox;
+ WorldToLocalCoordinatesBoundingBox( mImpl->mBoundingBox, boundingBox );
}
void Decorator::Relayout( const Vector2& size )
if( !active )
{
+ if( ( LEFT_SELECTION_HANDLE == handleType ) || ( RIGHT_SELECTION_HANDLE == handleType ) )
+ {
+ mImpl->mHandlePreviousCrossed = false;
+ }
+
// TODO: this is a work-around.
// The problem is the handle actor does not receive the touch event with the Interrupt
// state when the power button is pressed and the application goes to background.
imageActor.SetImage( imageReleased );
}
}
+
}
bool Decorator::IsHandleActive( HandleType handleType ) const
void Decorator::SetHandleImage( HandleType handleType, HandleImageType handleImageType, Dali::Image image )
{
- mImpl->mHandleImages[handleType][handleImageType] = image;
+ mImpl->SetHandleImage( handleType, handleImageType, image );
}
Dali::Image Decorator::GetHandleImage( HandleType handleType, HandleImageType handleImageType ) const
return mImpl->mHandle[handleType].position;
}
-void Decorator::SwapSelectionHandlesEnabled( bool enable )
+void Decorator::FlipSelectionHandlesOnCrossEnabled( bool enable )
{
- mImpl->mSwapSelectionHandles = enable;
+ mImpl->mFlipSelectionHandlesOnCross = enable;
+}
- mImpl->FlipSelectionHandleImages();
+void Decorator::SetSelectionHandleFlipState( bool indicesSwapped, bool left, bool right )
+{
+ mImpl->mHandleCurrentCrossed = indicesSwapped;
+ mImpl->mFlipLeftSelectionHandleDirection = left;
+ mImpl->mFlipRightSelectionHandleDirection = right;
}
void Decorator::AddHighlight( float x1, float y1, float x2, float y2 )
* @brief Retrieve the bounding box origin and dimensions.
*
* default is set once control is added to stage, before this the return vector will be Vector4:ZERO
- * @return Rect<int> the bounding box origin, width and height
+ * @param[out] boundingBox The bounding box origin, width and height.
*/
- const Rect<int>& GetBoundingBox() const;
+ void GetBoundingBox( Rect<int>& boundingBox ) const;
/**
* @brief The decorator waits until a relayout before creating actors etc.
const Vector2& GetPosition( HandleType handleType ) const;
/**
- * @brief Swaps the selection handle's images.
+ * @brief Whether to flip the selection handles as soon as they are crossed.
*
- * This method is called by the text controller to swap the handles
- * when the start index is bigger than the end one.
+ * By default they flip when the handle is released.
+ *
+ * @param[in] enable If @e true the selection handles will flip as soon as they are crossed.
+ */
+ void FlipSelectionHandlesOnCrossEnabled( bool enable );
+
+ /**
+ * @brief Sets info to calculate the handle flip state.
+ *
+ * Sets the character's direction where the handles are pointing.
+ * It resets the decorator internal flip state when there is a new selection.
+ *
+ * @param[in] indicesSwapped Whether the selection handle indices are swapped (start > end).
+ * @param[in] left The direction of the character pointed by the primary selection handle.
+ * @param[in] right The direction of the character pointed by the secondary selection handle.
*/
- void SwapSelectionHandlesEnabled( bool enable );
+ void SetSelectionHandleFlipState( bool indicesSwapped, bool left, bool right );
/**
* @brief Adds a quad to the existing selection highlights.
mCursorWidth( CURSOR_WIDTH ),
mEllipsisEnabled( false )
{
- mFontClient = TextAbstraction::FontClient::Get();
}
/**
void UpdateLineHeight( FontId fontId, LineLayout& lineLayout )
{
Text::FontMetrics fontMetrics;
- mFontClient.GetFontMetrics( fontId, fontMetrics );
+ mMetrics->GetFontMetrics( fontId, fontMetrics );
// Sets the maximum ascender.
if( fontMetrics.ascender > lineLayout.ascender )
const GlyphInfo& glyphInfo = *( layoutParameters.glyphsBuffer + layoutParameters.totalNumberOfGlyphs - 1u );
Text::FontMetrics fontMetrics;
- mFontClient.GetFontMetrics( glyphInfo.fontId, fontMetrics );
+ mMetrics->GetFontMetrics( glyphInfo.fontId, fontMetrics );
LineRun lineRun;
lineRun.glyphRun.glyphIndex = 0u;
LayoutEngine::VerticalAlignment mVerticalAlignment;
float mCursorWidth;
- TextAbstraction::FontClient mFontClient;
+ IntrusivePtr<Metrics> mMetrics;
bool mEllipsisEnabled:1;
};
delete mImpl;
}
+void LayoutEngine::SetMetrics( MetricsPtr& metrics )
+{
+ mImpl->mMetrics = metrics;
+}
+
void LayoutEngine::SetLayout( Layout layout )
{
mImpl->mLayout = layout;
// INTERNAL INCLUDE
#include <dali-toolkit/internal/text/line-run.h>
+#include <dali-toolkit/internal/text/metrics.h>
namespace Dali
{
~LayoutEngine();
/**
+ * @brief Provide the wrapper around FontClient used to get metrics
+ *
+ * @param[in] metrics Used to get metrics
+ */
+ void SetMetrics( MetricsPtr& metrics );
+
+ /**
* @brief Choose the required layout.
*
* @param[in] layout The required layout.
--- /dev/null
+#ifndef __DALI_TOOLKIT_TEXT_METRICS_H__
+#define __DALI_TOOLKIT_TEXT_METRICS_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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+class Metrics;
+typedef IntrusivePtr<Metrics> MetricsPtr;
+
+/**
+ * @brief A wrapper around FontClient used to get metrics & potentially down-scaled Emoji metrics.
+ */
+class Metrics : public RefObject
+{
+public:
+
+ /**
+ * Create a new Metrics object
+ */
+ static Metrics* New( TextAbstraction::FontClient& fontClient )
+ {
+ return new Metrics( fontClient );
+ }
+
+ /**
+ * @brief Set the maximum Emoji size.
+ *
+ * @param[in] emojiSize Emoticons will be scaled to fit this size in pixels.
+ */
+ void SetMaxEmojiSize( int emojiSize )
+ {
+ mEmojiSize = emojiSize;
+ }
+
+ /**
+ * @brief Get the maximum Emoji size.
+ *
+ * @return The maximum Emoji size.
+ */
+ int GetMaxEmojiSize() const
+ {
+ return mEmojiSize;
+ }
+
+ /**
+ * @brief Query the metrics for a font.
+ *
+ * @param[in] fontId The ID of the font for the required glyph.
+ * @param[out] metrics The font metrics.
+ */
+ void GetFontMetrics( FontId fontId, FontMetrics& metrics )
+ {
+ mFontClient.GetFontMetrics( fontId, metrics, mEmojiSize ); // inline for performance
+ }
+
+ /**
+ * @brief Retrieve the metrics for a series of glyphs.
+ *
+ * @param[in,out] array An array of glyph-info structures with initialized FontId & GlyphIndex values.
+ * It may contain the advance and an offset set into the bearing from the shaping tool.
+ * On return, the glyph's size value will be initialized. The bearing value will be updated by adding the font's glyph bearing to the one set by the shaping tool.
+ * @param[in] size The size of the array.
+ * @return True if all of the requested metrics were found.
+ */
+ bool GetGlyphMetrics( GlyphInfo* array, uint32_t size )
+ {
+ return mFontClient.GetGlyphMetrics( array, size, true, mEmojiSize ); // inline for performance
+ }
+
+protected:
+
+ /**
+ * A reference counted object may only be deleted by calling Unreference()
+ */
+ virtual ~Metrics() {}
+
+private:
+
+ /**
+ * Constructor.
+ */
+ Metrics( TextAbstraction::FontClient& fontClient )
+ : mFontClient( fontClient ),
+ mEmojiSize( 0 )
+ {
+ }
+
+ // Undefined
+ Metrics(const Metrics&);
+
+ // Undefined
+ Metrics& operator=(const Metrics& rhs);
+
+private:
+
+ TextAbstraction::FontClient mFontClient;
+
+ int mEmojiSize;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_METRICS_H__
namespace
{
#if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_MULTI_LANGUAGE_SUPPORT");
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_MULTI_LANGUAGE_SUPPORT");
#endif
const Dali::Toolkit::Text::Character UTF32_A = 0x0041;
const Vector<ScriptRun>& scripts,
Vector<FontRun>& fonts )
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->MultilanguageSupport::ValidateFonts\n" );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "-->MultilanguageSupport::ValidateFonts\n" );
const Length numberOfCharacters = text.Count();
if( 0u == numberOfCharacters )
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--MultilanguageSupport::ValidateFonts\n" );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "<--MultilanguageSupport::ValidateFonts\n" );
// Nothing to do if there are no characters.
return;
}
// Copy the fonts set by application developers.
const Length numberOfFontRuns = fonts.Count();
- const Vector<FontRun> definedFonts = fonts;
+ const Vector<FontRun> userSetFonts = fonts;
fonts.Clear();
// Traverse the characters and validate/set the fonts.
TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
// Iterators of the font and script runs.
- Vector<FontRun>::ConstIterator fontRunIt = definedFonts.Begin();
- Vector<FontRun>::ConstIterator fontRunEndIt = definedFonts.End();
+ Vector<FontRun>::ConstIterator fontRunIt = userSetFonts.Begin();
+ Vector<FontRun>::ConstIterator fontRunEndIt = userSetFonts.End();
Vector<ScriptRun>::ConstIterator scriptRunIt = scripts.Begin();
Vector<ScriptRun>::ConstIterator scriptRunEndIt = scripts.End();
// Store the last run.
fonts.PushBack( currentFontRun );
}
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--MultilanguageSupport::ValidateFonts\n" );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "<--MultilanguageSupport::ValidateFonts\n" );
}
} // namespace Internal
textCacheEntry.mIndex = glyph.index;
newTextCache.PushBack( textCacheEntry );
+ // Adjust the vertices if the fixed-size font should be down-scaled
+ if( glyph.scaleFactor > 0 )
+ {
+ for( unsigned int i=0; i<newMesh.mVertices.Count(); ++i )
+ {
+ newMesh.mVertices[i].mPosition.x = position.x + ( ( newMesh.mVertices[i].mPosition.x - position.x ) * glyph.scaleFactor );
+ newMesh.mVertices[i].mPosition.y = position.y + ( ( newMesh.mVertices[i].mPosition.y - position.y ) * glyph.scaleFactor );
+ }
+ }
+
// 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,
newMesh,
Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material );
- // Ensure shadow is behind the text...
- renderer.SetDepthIndex( CONTENT_DEPTH_INDEX + mDepth );
+ // Set depth index to -1.0 to make sure shadow is rendered first in 3D layers
+ renderer.SetDepthIndex( -1.0f );
Actor actor = Actor::New();
actor.AddRenderer( renderer );
actor.SetParentOrigin( ParentOrigin::CENTER ); // Keep all of the origins aligned
{
#if defined(DEBUG_ENABLED)
- Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS");
+ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
#endif
/**
float xBearing; ///< The x bearing of the first glyph.
};
-const std::string EMPTY_STRING("");
-
} // namespace
namespace Dali
* @param[in] numberOfGlyphs The number of glyphs.
* @param[out] glyphMetrics Some glyph metrics (font height, advance, ascender and x bearing).
* @param[in] visualModel The visual model.
- * @param[in] fontClient The font client.
+ * @param[in] metrics Used to access metrics from FontClient.
*/
void GetGlyphsMetrics( GlyphIndex glyphIndex,
Length numberOfGlyphs,
GlyphMetrics& glyphMetrics,
- VisualModelPtr visualModel,
- TextAbstraction::FontClient& fontClient )
+ VisualModelPtr& visualModel,
+ MetricsPtr& metrics )
{
const GlyphInfo* glyphsBuffer = visualModel->mGlyphs.Begin();
const GlyphInfo& firstGlyph = *( glyphsBuffer + glyphIndex );
Text::FontMetrics fontMetrics;
- fontClient.GetFontMetrics( firstGlyph.fontId, fontMetrics );
+ metrics->GetFontMetrics( firstGlyph.fontId, fontMetrics );
glyphMetrics.fontHeight = fontMetrics.height;
glyphMetrics.advance = firstGlyph.advance;
void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::UpdateModel\n" );
+
// Calculate the operations to be done.
const OperationsMask operations = static_cast<OperationsMask>( mOperationsPending & operationsRequired );
if( GET_GLYPH_METRICS & operations )
{
GlyphInfo* glyphsBuffer = glyphs.Begin();
- mFontClient.GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
+ mMetrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
// Update the width and advance of all new paragraph characters.
for( Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it )
{
if( mFontDefaults )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::GetDefaultFonts font family(%s)\n", mFontDefaults->mFontDescription.family.c_str() );
FontRun fontRun;
fontRun.characterRun.characterIndex = 0;
fontRun.characterRun.numberOfCharacters = numberOfCharacters;
FontId defaultFontId = 0u;
if( NULL == mFontDefaults )
{
- defaultFontId = mFontClient.GetFontId( EMPTY_STRING,
- EMPTY_STRING );
+ TextAbstraction::FontDescription fontDescription;
+ defaultFontId = mFontClient.GetFontId( fontDescription );
}
else
{
}
Text::FontMetrics fontMetrics;
- mFontClient.GetFontMetrics( defaultFontId, fontMetrics );
+ mMetrics->GetFontMetrics( defaultFontId, fontMetrics );
return( fontMetrics.ascender - fontMetrics.descender );
}
return;
}
+ const bool handlesCrossed = mEventData->mLeftSelectionPosition > mEventData->mRightSelectionPosition;
+
//Get start and end position of selection
- uint32_t startOfSelectedText = mEventData->mLeftSelectionPosition;
- uint32_t lengthOfSelectedText = mEventData->mRightSelectionPosition - startOfSelectedText;
+ uint32_t startOfSelectedText = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
+ uint32_t lengthOfSelectedText = ( handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition ) - startOfSelectedText;
// Validate the start and end selection points
- if( ( startOfSelectedText >= 0 ) && ( ( startOfSelectedText + lengthOfSelectedText ) <= mLogicalModel->mText.Count() ) )
+ if( ( startOfSelectedText + lengthOfSelectedText ) <= mLogicalModel->mText.Count() )
{
//Get text as a UTF8 string
Vector<Character>& utf32Characters = mLogicalModel->mText;
Vector<Character>::Iterator last = first + lengthOfSelectedText;
currentText.Erase( first, last );
}
- mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition;
+ mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
mEventData->mScrollAfterDelete = true;
mEventData->mDecoratorUpdated = true;
}
const LineRun& firstLine = *lines.Begin();
const float height = firstLine.ascender + -firstLine.descender;
+ const bool isLastCharacter = selectionEnd >= mLogicalModel->mText.Count();
+ const bool startDirection = ( ( NULL == modelCharacterDirectionsBuffer ) ? false : *( modelCharacterDirectionsBuffer + selectionStart ) );
+ const bool endDirection = ( ( NULL == modelCharacterDirectionsBuffer ) ? false : *( modelCharacterDirectionsBuffer + ( selectionEnd - ( isLastCharacter ? 1u : 0u ) ) ) );
+
// Swap the indices if the start is greater than the end.
- const bool indicesSwapped = ( selectionStart > selectionEnd );
+ const bool indicesSwapped = selectionStart > selectionEnd;
+
+ // Tell the decorator to flip the selection handles if needed.
+ mEventData->mDecorator->SetSelectionHandleFlipState( indicesSwapped, startDirection, endDirection );
+
if( indicesSwapped )
{
std::swap( selectionStart, selectionEnd );
const Length numberOfCharactersEnd = *( charactersPerGlyphBuffer + glyphEnd );
bool splitEndGlyph = ( glyphStart != glyphEnd ) && ( numberOfCharactersEnd > 1u ) && HasLigatureMustBreak( mLogicalModel->GetScript( selectionEndMinusOne ) );
- // Tell the decorator to swap the selection handles if needed.
- mEventData->mDecorator->SwapSelectionHandlesEnabled( firstLine.direction != indicesSwapped );
-
const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset;
// Traverse the glyphs.
mEventData->mDecorator->SetPosition( RIGHT_SELECTION_HANDLE, secondaryPosition.x, secondaryPosition.y, secondaryCursorInfo.lineHeight );
// Cursor to be positioned at end of selection so if selection interrupted and edit mode restarted the cursor will be at end of selection
- mEventData->mPrimaryCursorPosition = (indicesSwapped)?mEventData->mLeftSelectionPosition:mEventData->mRightSelectionPosition;
+ mEventData->mPrimaryCursorPosition = ( indicesSwapped ) ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition;
// Set the flag to update the decorator.
mEventData->mDecoratorUpdated = true;
numberOfGlyphs,
glyphMetrics,
mVisualModel,
- mFontClient );
+ mMetrics );
const Vector2& position = *( positionsBuffer + glyphLogicalOrderIndex );
primaryNumberOfGlyphs,
glyphMetrics,
mVisualModel,
- mFontClient );
+ mMetrics );
// Whether to add the glyph's advance to the cursor position.
// i.e if the paragraph is left to right and the logical cursor is zero, the position is the position of the first glyph and the advance is not added,
secondaryNumberOfGlyphs,
glyphMetrics,
mVisualModel,
- mFontClient );
+ mMetrics );
// Set the secondary cursor's position.
cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + secondaryPosition.x + ( isCurrentRightToLeft ? 0.f : glyphMetrics.advance );
FontId defaultFontId = 0u;
if( NULL == mFontDefaults )
{
- defaultFontId = mFontClient.GetFontId( EMPTY_STRING,
- EMPTY_STRING );
+ TextAbstraction::FontDescription fontDescription;
+ defaultFontId = mFontClient.GetFontId( fontDescription );
}
else
{
}
Text::FontMetrics fontMetrics;
- mFontClient.GetFontMetrics( defaultFontId, fontMetrics );
+ mMetrics->GetFontMetrics( defaultFontId, fontMetrics );
lineHeight = fontMetrics.ascender - fontMetrics.descender;
struct FontDefaults
{
FontDefaults()
- : mDefaultPointSize(0.0f),
+ : mFontDescription(),
+ mFontStyle(),
+ mDefaultPointSize(0.0f),
mFontId(0u)
{
+ // Initially use the default platform font
+ TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
+ fontClient.GetDefaultPlatformFontDescription( mFontDescription );
}
FontId GetFontId( TextAbstraction::FontClient& fontClient )
if( !mFontId )
{
Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64;
- mFontId = fontClient.GetFontId( mDefaultFontFamily, mDefaultFontStyle, pointSize );
+ mFontId = fontClient.GetFontId( mFontDescription, pointSize );
}
return mFontId;
}
- std::string mDefaultFontFamily;
- std::string mDefaultFontStyle;
+ TextAbstraction::FontDescription mFontDescription;
+ std::string mFontStyle;
float mDefaultPointSize;
FontId mFontId;
};
mFontClient(),
mClipboard(),
mView(),
+ mMetrics(),
mLayoutEngine(),
mModifyEvents(),
mTextColor( Color::BLACK ),
mAlignmentOffset(),
mOperationsPending( NO_OPERATION ),
mMaximumNumberOfCharacters( 50 ),
- mRecalculateNaturalSize( true )
+ mRecalculateNaturalSize( true ),
+ mUserDefinedFontFamily( false )
{
mLogicalModel = LogicalModel::New();
mVisualModel = VisualModel::New();
mView.SetVisualModel( mVisualModel );
+ // Use this to access FontClient i.e. to get down-scaled Emoji metrics.
+ mMetrics = Metrics::New( mFontClient );
+ mLayoutEngine.SetMetrics( mMetrics );
+
// Set the text properties to default
mVisualModel->SetUnderlineEnabled( false );
mVisualModel->SetUnderlineHeight( 0.0f );
void ResetImfManager()
{
- // Reset incase we are in a pre-edit state.
- ImfManager imfManager = ImfManager::Get();
- if ( imfManager )
+ if( mEventData )
{
- imfManager.Reset(); // Will trigger a commit message
+ // Reset incase we are in a pre-edit state.
+ ImfManager imfManager = ImfManager::Get();
+ if ( imfManager )
+ {
+ imfManager.Reset(); // Will trigger a commit message
+ }
+
+ ClearPreEditFlag();
}
-
- ClearPreEditFlag();
}
bool IsClipboardEmpty()
FontDefaults* mFontDefaults; ///< Avoid allocating this when the user does not specify a font.
EventData* mEventData; ///< Avoid allocating everything for text input until EnableTextInput().
TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
- Clipboard mClipboard; ///< Handle to the system clipboard
+ Clipboard mClipboard; ///< Handle to the system clipboard
View mView; ///< The view interface to the rendering back-end.
+ MetricsPtr mMetrics; ///< A wrapper around FontClient used to get metrics & potentially down-scaled Emoji metrics.
LayoutEngine mLayoutEngine; ///< The layout engine.
std::vector<ModifyEvent> mModifyEvents; ///< Temporary stores the text set until the next relayout.
Vector4 mTextColor; ///< The regular text color
Vector2 mAlignmentOffset; ///< Vertical and horizontal offset of the whole text inside the control due to alignment.
OperationsMask mOperationsPending; ///< Operations pending to be done to layout the text.
Length mMaximumNumberOfCharacters; ///< Maximum number of characters that can be inserted.
+
bool mRecalculateNaturalSize:1; ///< Whether the natural size needs to be recalculated.
+ bool mUserDefinedFontFamily:1; ///< Whether the Font family was set by the user instead of being left as sytem default.
};
} // namespace Text
#endif
const float MAX_FLOAT = std::numeric_limits<float>::max();
+const unsigned int POINTS_PER_INCH = 72;
const std::string EMPTY_STRING("");
+const unsigned int ZERO = 0u;
float ConvertToEven( float value )
{
void Controller::SetText( const std::string& text )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText\n" );
+
+ // Reset keyboard as text changed
+ mImpl->ResetImfManager();
+
// Remove the previously set text
ResetText();
mImpl->mEventData->mEventQueue.clear();
}
- // Reset keyboard as text changed
- mImpl->ResetImfManager();
+ // Notify IMF as text changed
+ NotifyImfManager();
// Do this last since it provides callbacks into application code
mImpl->mControlInterface.TextChanged();
return mImpl->mMaximumNumberOfCharacters;
}
-void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily )
+void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily, bool userDefined )
{
if( !mImpl->mFontDefaults )
{
mImpl->mFontDefaults = new FontDefaults();
}
- mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily;
+ mImpl->mFontDefaults->mFontDescription.family = defaultFontFamily;
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetDefaultFontFamily %s userDefined: %s\n", defaultFontFamily.c_str(), userDefined ? "true":"false" );
+ mImpl->mUserDefinedFontFamily = userDefined;
// Clear the font-specific data
ClearFontData();
{
if( mImpl->mFontDefaults )
{
- return mImpl->mFontDefaults->mDefaultFontFamily;
+ return mImpl->mFontDefaults->mFontDescription.family;
}
return EMPTY_STRING;
}
-void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle )
+void Controller::SetDefaultFontStyle( const std::string& style )
{
if( !mImpl->mFontDefaults )
{
mImpl->mFontDefaults = new FontDefaults();
}
- mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle;
+ mImpl->mFontDefaults->mFontStyle = style;
+}
+
+const std::string& Controller::GetDefaultFontStyle() const
+{
+ if( mImpl->mFontDefaults )
+ {
+ return mImpl->mFontDefaults->mFontStyle;
+ }
+
+ return EMPTY_STRING;
+}
+
+void Controller::SetDefaultFontWidth( FontWidth width )
+{
+ if( !mImpl->mFontDefaults )
+ {
+ mImpl->mFontDefaults = new FontDefaults();
+ }
+
+ mImpl->mFontDefaults->mFontDescription.width = width;
// Clear the font-specific data
ClearFontData();
mImpl->RequestRelayout();
}
-const std::string& Controller::GetDefaultFontStyle() const
+FontWidth Controller::GetDefaultFontWidth() const
{
if( mImpl->mFontDefaults )
{
- return mImpl->mFontDefaults->mDefaultFontStyle;
+ return mImpl->mFontDefaults->mFontDescription.width;
}
- return EMPTY_STRING;
+ return TextAbstraction::FontWidth::NORMAL;
+}
+
+void Controller::SetDefaultFontWeight( FontWeight weight )
+{
+ if( !mImpl->mFontDefaults )
+ {
+ mImpl->mFontDefaults = new FontDefaults();
+ }
+
+ mImpl->mFontDefaults->mFontDescription.weight = weight;
+
+ // Clear the font-specific data
+ ClearFontData();
+
+ mImpl->mOperationsPending = ALL_OPERATIONS;
+ mImpl->mRecalculateNaturalSize = true;
+
+ mImpl->RequestRelayout();
+}
+
+FontWeight Controller::GetDefaultFontWeight() const
+{
+ if( mImpl->mFontDefaults )
+ {
+ return mImpl->mFontDefaults->mFontDescription.weight;
+ }
+
+ return TextAbstraction::FontWeight::NORMAL;
+}
+
+void Controller::SetDefaultFontSlant( FontSlant slant )
+{
+ if( !mImpl->mFontDefaults )
+ {
+ mImpl->mFontDefaults = new FontDefaults();
+ }
+
+ mImpl->mFontDefaults->mFontDescription.slant = slant;
+
+ // Clear the font-specific data
+ ClearFontData();
+
+ mImpl->mOperationsPending = ALL_OPERATIONS;
+ mImpl->mRecalculateNaturalSize = true;
+
+ mImpl->RequestRelayout();
+}
+
+FontSlant Controller::GetDefaultFontSlant() const
+{
+ if( mImpl->mFontDefaults )
+ {
+ return mImpl->mFontDefaults->mFontDescription.slant;
+ }
+
+ return TextAbstraction::FontSlant::NORMAL;
}
void Controller::SetDefaultPointSize( float pointSize )
mImpl->mFontDefaults->mDefaultPointSize = pointSize;
+ unsigned int horizontalDpi( 0u );
+ unsigned int verticalDpi( 0u );
+ mImpl->mFontClient.GetDpi( horizontalDpi, verticalDpi );
+
+ // Adjust the metrics if the fixed-size font should be down-scaled
+ int maxEmojiSize( pointSize/POINTS_PER_INCH * verticalDpi );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetDefaultPointSize %p setting MaxEmojiSize %d\n", this, maxEmojiSize );
+ mImpl->mMetrics->SetMaxEmojiSize( maxEmojiSize );
+
// Clear the font-specific data
ClearFontData();
return 0.0f;
}
+void Controller::UpdateAfterFontChange( std::string& newDefaultFont )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange");
+
+ ClearFontData();
+
+ if ( !mImpl->mUserDefinedFontFamily ) // If user defined font then should not update when system font changes
+ {
+ DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange newDefaultFont(%s)\n", newDefaultFont.c_str() );
+ mImpl->mFontDefaults->mFontDescription.family = newDefaultFont;
+ mImpl->UpdateModel( ALL_OPERATIONS );
+ mImpl->QueueModifyEvent( ModifyEvent::TEXT_REPLACED );
+ mImpl->mRecalculateNaturalSize = true;
+ mImpl->RequestRelayout();
+ }
+}
+
void Controller::SetTextColor( const Vector4& textColor )
{
mImpl->mTextColor = textColor;
// Do not re-do any operation until something changes.
mImpl->mOperationsPending = NO_OPERATION;
+ // Keep the current offset and alignment as it will be used to update the decorator's positions.
+ Vector2 offset;
+ if( mImpl->mEventData )
+ {
+ offset = mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition;
+ }
+
// After doing the text layout, the alignment offset to place the actor in the desired position can be calculated.
CalculateTextAlignment( size );
if( mImpl->mEventData )
{
+ // If there is a nex size, the scroll position needs to be clamped.
+ mImpl->ClampHorizontalScroll( layoutSize );
+
+ // Update the decorator's positions.
+ mImpl->mEventData->mDecorator->UpdatePositions( mImpl->mAlignmentOffset + mImpl->mEventData->mScrollPosition - offset );
+
// Move the cursor, grab handle etc.
updated = mImpl->ProcessInputEvents() || updated;
}
void Controller::LongPressEvent( Gesture::State state, float x, float y )
{
- DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected PanEvent" );
+ DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected LongPressEvent" );
- if ( mImpl->IsShowingPlaceholderText() || mImpl->mLogicalModel->mText.Count() == 0u )
+ if( state == Gesture::Started &&
+ mImpl->mEventData )
{
- if ( mImpl->mEventData )
+ if( ! mImpl->IsShowingRealText() )
{
Event event( Event::LONG_PRESS_EVENT );
event.p1.mInt = state;
mImpl->mEventData->mEventQueue.push_back( event );
mImpl->RequestRelayout();
}
- }
- else if( mImpl->mEventData )
- {
- SelectEvent( x, y, false );
+ else
+ {
+ // The 1st long-press on inactive text-field is treated as tap
+ if( EventData::INACTIVE == mImpl->mEventData->mState )
+ {
+ mImpl->ChangeState( EventData::EDITING );
+
+ Event event( Event::TAP_EVENT );
+ event.p1.mUint = 1;
+ event.p2.mFloat = x;
+ event.p3.mFloat = y;
+ mImpl->mEventData->mEventQueue.push_back( event );
+
+ mImpl->RequestRelayout();
+ }
+ else
+ {
+ SelectEvent( x, y, false );
+ }
+ }
}
}
{
mImpl->SendSelectionToClipboard( true ); // Synchronous call to modify text
mImpl->mOperationsPending = ALL_OPERATIONS;
+
+ // This is to reset the virtual keyboard to Upper-case
+ if( 0u == mImpl->mLogicalModel->mText.Count() )
+ {
+ NotifyImfManager();
+ }
+
if( 0u != mImpl->mLogicalModel->mText.Count() ||
!mImpl->IsPlaceholderAvailable() )
{
if( removed )
{
+ // This is to reset the virtual keyboard to Upper-case
+ if( 0u == mImpl->mLogicalModel->mText.Count() )
+ {
+ NotifyImfManager();
+ }
+
if( 0u != mImpl->mLogicalModel->mText.Count() ||
!mImpl->IsPlaceholderAvailable() )
{
return removed;
}
+void Controller::NotifyImfManager()
+{
+ if( mImpl->mEventData )
+ {
+ ImfManager imfManager = ImfManager::Get();
+
+ if( imfManager )
+ {
+ // Notifying IMF of a cursor change triggers a surrounding text request so updating it now.
+ std::string text;
+ GetText( text );
+ imfManager.SetSurroundingText( text );
+
+ imfManager.SetCursorPosition( GetLogicalCursorPosition() );
+ imfManager.NotifyCursorPosition();
+ }
+ }
+}
+
void Controller::ShowPlaceholderText()
{
if( mImpl->IsPlaceholderAvailable() )
* @brief Set the default font family.
*
* @param[in] defaultFontFamily The default font family.
+ * @param[in] userDefined If set by the user
*/
- void SetDefaultFontFamily( const std::string& defaultFontFamily );
+ void SetDefaultFontFamily( const std::string& defaultFontFamily, bool userDefined );
/**
* @brief Retrieve the default font family.
const std::string& GetDefaultFontFamily() const;
/**
- * @brief Set the default font style.
+ * @brief Sets the font's style string.
*
- * @param[in] defaultFontStyle The default font style.
+ * @note The style set may be changed by the underlying font system. The string is stored to be recovered.
+ *
+ * @param[in] style The font's style string.
*/
- void SetDefaultFontStyle( const std::string& defaultFontStyle );
+ void SetDefaultFontStyle( const std::string& style );
/**
- * @brief Retrieve the default font style.
+ * @brief Retrieves the font's style.
*
- * @return The default font style.
+ * @return The font's style.
*/
const std::string& GetDefaultFontStyle() const;
/**
+ * @brief Sets the default font width.
+ *
+ * @param[in] width The font width.
+ */
+ void SetDefaultFontWidth( FontWidth width );
+
+ /**
+ * @brief Retrieves the default font width.
+ *
+ * @return The default font width.
+ */
+ FontWidth GetDefaultFontWidth() const;
+
+ /**
+ * @brief Sets the default font weight.
+ *
+ * @param[in] weight The font weight.
+ */
+ void SetDefaultFontWeight( FontWeight weight );
+
+ /**
+ * @brief Retrieves the default font weight.
+ *
+ * @return The default font weight.
+ */
+ FontWeight GetDefaultFontWeight() const;
+
+ /**
+ * @brief Sets the default font slant.
+ *
+ * @param[in] slant The font slant.
+ */
+ void SetDefaultFontSlant( FontSlant slant );
+
+ /**
+ * @brief Retrieves the default font slant.
+ *
+ * @return The default font slant.
+ */
+ FontSlant GetDefaultFontSlant() const;
+
+ /**
* @brief Set the default point size.
*
- * @param[in] defaultFontStyle The default point size.
+ * @param[in] pointSize The default point size.
*/
void SetDefaultPointSize( float pointSize );
float GetDefaultPointSize() const;
/**
+ * @ brief Update the text after a font change
+ * @param[in] newDefaultFont The new font to change to
+ */
+ void UpdateAfterFontChange( std::string& newDefaultFont );
+
+ /**
* @brief Set the text color
*
* @param textColor The text color
bool BackspaceKeyEvent();
/**
+ * @brief Helper to notify IMF manager with surrounding text & cursor changes.
+ */
+ void NotifyImfManager();
+
+ /**
* @brief Helper to clear font-specific data.
*/
void ShowPlaceholderText();
// EXTERNAL INCLUDES
#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
+#include <dali/devel-api/text-abstraction/font-list.h>
#include <dali/devel-api/text-abstraction/font-metrics.h>
#include <dali/devel-api/text-abstraction/glyph-info.h>
#include <dali/devel-api/text-abstraction/script.h>
{
typedef TextAbstraction::FontId FontId; ///< The unique identifier for a font face (generated by FontClient).
+typedef TextAbstraction::FontWidth::Type FontWidth; ///< The font's width.
+typedef TextAbstraction::FontWeight::Type FontWeight; ///< The font's weight.
+typedef TextAbstraction::FontSlant::Type FontSlant; ///< The font's slant.
typedef TextAbstraction::FontMetrics FontMetrics; ///< The metrics for a Font expressed in 26.6 fractional pixel format.
typedef TextAbstraction::PointSize26Dot6 PointSize26Dot6; ///< The point size in 26.6 fractional points.
typedef TextAbstraction::FaceIndex FaceIndex; ///< Used with fonts which allow several font faces.
FontId id = fontRun[i].fontId;
TextAbstraction::FontDescription fontDescription;
fontClient.GetDescription( id, fontDescription );
- o << "ID:" << id << ", " << fontDescription.family << " style:" << fontDescription.style << " size:" << (fontClient.GetPointSize(id) / 64);
+ o << "ID:" << id << ", " << fontDescription.family << " width: " << fontDescription.width << " weight: " << fontDescription.weight << " slant: " << fontDescription.slant << " size:" << (fontClient.GetPointSize(id) / 64);
if( i+1 < fontRun.Count() )
{
{
class AccessibilityManager;
}
+/**
+ * @addtogroup dali-toolkit-accessibility-manager
+ * @{
+ */
/**
* @brief Manages registration of actors in a accessibility focus chain and changing the
}; // class AccessibilityManager
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class Alignment;
}
+/**
+ * @addtogroup dali-toolkit-controls-alignment
+ * @{
+ */
/**
* @brief Alignment is a container which provides an easy way to align other actors inside its boundary.
explicit DALI_INTERNAL Alignment( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class Button;
}
+/**
+ * @addtogroup dali-toolkit-controls-buttons
+ * @{
+ */
/**
* @brief Button is a base class for different kind of buttons.
DALI_INTERNAL Button( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class CheckBoxButton;
}
+/**
+ * @addtogroup dali-toolkit-controls-buttons
+ * @{
+ */
/**
* CheckBoxButton provides a check box button which user can check or uncheck.
DALI_INTERNAL CheckBoxButton( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
class PushButton;
}
+/**
+ * @addtogroup dali-toolkit-controls-buttons
+ * @{
+ */
/**
* @brief A PushButton changes its appearance when is pressed and returns to its original when is released.
DALI_INTERNAL PushButton( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
class RadioButton;
}
+/**
+ * @addtogroup dali-toolkit-controls-buttons
+ * @{
+ */
/**
* @brief A RadioButton provides a radio button which two states \e selected or \e unselected.
DALI_INTERNAL RadioButton( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
namespace Toolkit
{
+/**
+ * @addtogroup dali-toolkit-controls
+ * @{
+ */
+
enum ControlDepthIndexRanges
{
BACKGROUND_DEPTH_INDEX = static_cast<int>( -Dali::Layer::TREE_DEPTH_MULTIPLIER * 0.1f ),
DECORATION_DEPTH_INDEX = static_cast<int>( Dali::Layer::TREE_DEPTH_MULTIPLIER * 0.1f )
};
+/**
+ * @}
+ */
}
}
namespace Toolkit
{
+/**
+ * @addtogroup dali-toolkit-controls
+ * @{
+ */
+
class StyleManager;
namespace Internal
{
-
/**
* @brief This is the internal base class for all controls.
*
} // namespace Internal
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class Control;
}
+/**
+ * @addtogroup dali-toolkit-controls
+ * @{
+ */
/**
* @brief Control is the base class for all controls.
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
namespace Toolkit
{
-
/**
* @brief Creates a Dali::ImageActor with a solid color, optionally it creates a border.
*
* @return a handle to the new ImageActor
*/
DALI_IMPORT_API ImageActor CreateSolidColorActor( const Vector4& color, bool border = false, const Vector4& borderColor = Color::WHITE, const unsigned int borderSize = 1 );
-
} // namespace Toolkit
} // namespace Dali
class BloomView;
} // namespace Internal
+/**
+ * @addtogroup dali-toolkit-controls-gaussian-blur-view
+ * @{
+ */
/**
*
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class ImageView;
}
+/**
+ * @addtogroup dali-toolkit-controls-image-view
+ * @{
+ */
/**
*
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
class ScrollBar;
}
+/**
+ * @addtogroup dali-toolkit-controls-scroll-bar
+ * @{
+ */
/**
* ScrollBar is a UI component that can be linked to the scrollable objects
explicit DALI_INTERNAL ScrollBar( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
-/**
- * @}
- */
#endif // __DALI_TOOLKIT_SCROLL_BAR_H__
namespace Toolkit
{
+/**
+ * @addtogroup dali-toolkit-controls-item-view
+ * @{
+ */
namespace DefaultItemLayout
{
} // namespace DefaultItemLayout
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
namespace Toolkit
{
+/**
+ * @addtogroup dali-toolkit-controls-item-view
+ * @{
+ */
/**
* @brief ItemFactory is for providing actors to ItemView.
}
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
namespace Toolkit
{
+/**
+ * @addtogroup dali-toolkit-controls-item-view
+ * @{
+ */
class ItemLayout;
*/
DALI_IMPORT_API ItemLayout();
+private:
+
+ /**
+ * Don't allow copy constructor
+ */
+ ItemLayout( const ItemLayout& handle );
+
+ /**
+ * Don't allow copy operator
+ */
+ ItemLayout& operator=( const ItemLayout& handle );
+
protected:
struct Impl;
Impl* mImpl;
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
namespace Toolkit
{
+/**
+ * @addtogroup dali-toolkit-controls-item-view
+ * @{
+ */
typedef unsigned int ItemId; ///< Unique identity for each item in the view.
class ItemView;
class ItemLayout;
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class ItemView;
}
+/**
+ * @addtogroup dali-toolkit-controls-item-view
+ * @{
+ */
class ItemFactory;
class ItemLayout;
explicit DALI_INTERNAL ItemView( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
namespace Toolkit
{
+/**
+ * @addtogroup dali-toolkit-controls-scroll-view
+ * @{
+ */
// Constraints ////////////////////////////////////////////////////////////////////////////////////
*/
DALI_IMPORT_API void WrapActorConstraint( Vector3& position, const PropertyInputContainer& inputs );
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
class ScrollViewEffect;
class ScrollViewWobbleEffect;
}
+/**
+ * @addtogroup dali-toolkit-controls-scroll-view
+ * @{
+ */
class ScrollView;
class ScrollViewEffect;
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class ScrollViewPagePathEffect;
}
+/**
+ * @addtogroup dali-toolkit-controls-scroll-view
+ * @{
+ */
/**
* ScrollView Page Path Effect.
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class ScrollView;
}
+/**
+ * @addtogroup dali-toolkit-controls-scroll-view
+ * @{
+ */
/**
* @brief How axes/rotation or scale are clamped
explicit DALI_INTERNAL ScrollView( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class Scrollable;
}
+/**
+ * @addtogroup dali-toolkit-controls-scrollable
+ * @{
+ */
/**
* @brief Base class for derived Scrollables that contains actors that can be scrolled manually
explicit DALI_INTERNAL Scrollable( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class TableView;
}
+/**
+ * @addtogroup dali-toolkit-controls-table-view
+ * @{
+ */
/**
* @brief TableView is a layout container for aligning child actors in a grid like layout.
explicit DALI_INTERNAL TableView( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class TextField;
}
+/**
+ * @addtogroup dali-toolkit-controls-text-controls
+ * @{
+ */
/**
* @brief A control which provides a single-line editable text field.
PLACEHOLDER_TEXT, ///< name "placeholder-text", The text to display when the TextField is empty and inactive, type STRING
PLACEHOLDER_TEXT_FOCUSED, ///< name "placeholder-text-focused", The text to display when the TextField is empty with key-input focus, type STRING
FONT_FAMILY, ///< name "font-family", The requested font family, type STRING
- FONT_STYLE, ///< name "font-style", The requested font style e.g. Regular/Italic, type STRING
+ FONT_STYLE, ///< name "font-style", The requested font style, type STRING
POINT_SIZE, ///< name "point-size", The size of font in points, type FLOAT
MAX_LENGTH, ///< name "max-length" The maximum number of characters that can be inserted, type INTEGER
EXCEED_POLICY, ///< name "exceed-policy" Specifies how the text is truncated when it does not fit, type INTEGER
explicit DALI_INTERNAL TextField( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class TextLabel;
}
+/**
+ * @addtogroup dali-toolkit-controls-text-controls
+ * @{
+ */
/**
* @brief A control which renders a short text string.
RENDERING_BACKEND = PROPERTY_START_INDEX, ///< name "rendering-backend", The type or rendering e.g. bitmap-based, type INT
TEXT, ///< name "text", The text to display in UTF-8 format, type STRING
FONT_FAMILY, ///< name "font-family", The requested font family, type STRING
- FONT_STYLE, ///< name "font-style", The requested font style e.g. Regular/Italic, type STRING
+ FONT_STYLE, ///< name "font-style", The requested font style, type STRING
POINT_SIZE, ///< name "point-size", The size of font in points, type FLOAT
MULTI_LINE, ///< name "multi-line", The single-line or multi-line layout option, type BOOLEAN
HORIZONTAL_ALIGNMENT, ///< name "horizontal-alignment", The line horizontal alignment, type STRING, values "BEGIN", "CENTER", "END"
explicit DALI_INTERNAL TextLabel( Dali::Internal::CustomActor* internal );
};
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 1;
+const unsigned int TOOLKIT_MICRO_VERSION = 2;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
namespace Dali
{
-
/**
* @brief DALi Toolkit namespace.
*/
namespace Toolkit
{
+/**
+ * @addtogroup dali-toolkit-controls
+ * @{
+ */
/**
* @brief Control Orientation namespace.
*/
DALI_IMPORT_API bool IsHorizontal(ControlOrientation::Type orientation);
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
{
class KeyboardFocusManager;
}
+/**
+ * @addtogroup dali-toolkit-focus-manager
+ * @{
+ */
/**
* @brief Provides the functionality of handling keyboard navigation
}; // class KeyboardFocusManager
+/**
+ * @}
+ */
} // namespace Toolkit
} // namespace Dali
"label":
{
"point-size":8,
- "font-style":"Light"
+ "font-style":"{\"weight\":\"light\"}"
}
},
"scrollview":
"label":
{
"point-size":8,
- "font-style":"Light"
+ "font-style":"{\"weight\":\"light\"}"
}
},
"scrollview":
--- /dev/null
+#ifndef __DALI_TOOLKIT_DOC_H__
+#define __DALI_TOOLKIT_DOC_H__
+
+/**
+ * @defgroup dali DALi
+ * @ingroup CAPI_UI_FRAMEWORK
+ *
+ * @brief DALi is a cross-platform 3D UI Toolkit for embedded systems.
+ *
+ * @section dali-overview Overview
+ * DALi's 3D user interface engine enables you to create rich and high-performance
+ * UI applications. DALi is based on OpenGL ES 2.0, but provides a clean
+ * cross-platform C++ framework.
+ * This means that you can use high-level DALi APIs instead of accessing
+ * low-level OpenGL APIs directly.
+ * <ul>
+ * <li>DALi Core: This module provides scene graph-based rendering, animation, and event handling.</li>
+ * <li>DALi Adaptor: This module is a platform adaptation layer.</li>
+ * <li>DALi Toolkit: This module provides UI components and various effects on top of the dali-core.</li>
+ * </ul>
+ *
+ * @defgroup dali-toolkit DALi Toolkit
+ * @ingroup dali
+ *
+ * @brief This module provides UI components and various effects on top of the dali-core.
+ *
+ * @{
+ * @defgroup dali-toolkit-accessibility-manager Accessibility Manager
+ * @brief AccessibilityManager manages a accessibility focus chain.
+
+ * @defgroup dali-toolkit-controls Controls
+ * @brief Controls are interactive components for layouting the user interface.
+
+ * @{
+ * @defgroup dali-toolkit-controls-alignment Alignment
+ * @brief Alignment is a container which provides an easy way to align other actors inside its boundary.
+
+ * @defgroup dali-toolkit-controls-buttons Buttons
+ * @brief Button is a small object on UI that you can press.
+
+ * @defgroup dali-toolkit-controls-gaussian-blur-view Gaussian Blur View
+ * @brief GaussianBlurView provides a render process that blurs an image.
+
+ * @defgroup dali-toolkit-controls-image-view Image View
+ * @brief ImageView is a control displying an image.
+
+ * @defgroup dali-toolkit-controls-scroll-bar Scroll Bar
+ * @brief ScrollBar control.
+
+ * @defgroup dali-toolkit-controls-scrollable Scrollable
+ * @brief Scrollable container controls.
+
+ * @{
+ * @defgroup dali-toolkit-controls-item-view Item View
+ * @brief ItemView class is a scrollable container that can contain many items.
+
+ * @defgroup dali-toolkit-controls-scroll-view Scroll View
+ * @brief ScrollView class provides scrollable view which contains actors and can be scrolled automatically or manually by panning.
+
+ * @}
+ * @defgroup dali-toolkit-controls-table-view Table View
+ * @brief TableView class is a layout container for aligning child actors in a grid like layout.
+
+ * @defgroup dali-toolkit-controls-text-controls Text Controls
+ * @brief Controls for displaying text or text input.
+
+ * @}
+ * @defgroup dali-toolkit-focus-manager Focus Manager
+ * @brief Classes for handling keyboard navigation and maintaining the two dimensional keyboard focus chain.
+
+ * @}
+ */
+
+
+#endif /* __DALI_TOOLKIT_DOC_H__ */
--- /dev/null
+package_doxy_files = \
+ $(package_doxy_dir)/dali-toolkit-doc.h
+
--- /dev/null
+<!--
+/**-->
+
+# Font Selection {#font-selection}
+
+By default TextLabel or TextField will automatically select a suitable font from the platform.
+Typically fonts do not support all scripts, for example Latin fonts often do not provide Arabic glyphs.
+Therefore you should expect the text control to select different fonts for each script.
+
+Alternatively a font may be requested using either or all of FONT_FAMILY, FONT_STYLE, and POINT_SIZE properties:
+
+- FONT_FAMILY
+ Is a string with the font's family name. i.e. *FreeSerif*
+- FONT_STYLE
+ Is a json formatted string with the font's style. Possible *key, value* pairs are:
+ + *width* Modifies the space between glyphs. Possible values are:
+ - *ultra-condensed*
+ - *extra-condensed*
+ - *condensed*
+ - *semi-condensed*
+ - *normal*
+ - *semi-expanded*
+ - *expanded*
+ - *extra-expanded*
+ - *ultra-expanded*
+ + *weight* Modifies the thickness or darkness of the glyphs. Possible values are:
+ - *thin*
+ - *ultra-light*
+ - *extra-light*
+ - *light*
+ - *demi-light*
+ - *semi-light*
+ - *book*
+ - *normal*
+ - *regular*
+ - *medium*
+ - *demi-bold*
+ - *semi-bold*
+ - *bold*
+ - *ultra-bold*
+ - *extra-bold*
+ - *black*
+ - *heavy*
+ - *extra-black*
+ + *slant* Whether to use italics. Usually *italic* is a different font whilst the *oblique* has been generated by slanting the *normal* one. Possible values are:
+ - *normal*
+ - *roman* Same as *normal*
+ - *italic*
+ - *oblique*
+- POINT_SIZE
+ Is a float with the font's size in points. To get the point size from pixels, could use the formula: <em>point_size = 72 * pixels / vertical_dpi</em> where <em>vertical_dpi</em> is the device's vertical resolution in dots per inch.
+
+~~~{.cpp}
+// C++
+
+label.SetProperty( TextLabel::Property::FONT_FAMILY, "FreeSerif" );
+label.SetProperty( TextLabel::Property::FONT_STYLE, "{\"weight\":\"bold\",\"slant\":\"italic\"}" );
+label.SetProperty( TextLabel::Property::POINT_SIZE, 12.0f );
+~~~
+
+~~~{.js}
+// JavaScript
+
+label.fontFamily = "FreeSerif";
+label.fontStyle = "{\"weight\":\"bold\",\"slant\":\"italic\"}";
+label.pointSize = 12;
+~~~
+
+However the text control will fall-back to using the default font, if the requested font does not support the required scripts.
+
+### Font Styles
+
+Setting a font size programmatically is not ideal for applications which support multiple screen resolutions etc.
+A more flexible approach is to prepare various JSON stylesheets, and request a different style for each platform:
+
+~~~{.cpp}
+// C++
+StyleManager styleManager = StyleManager::Get();
+styleManager.RequestThemeChange( "example-path/example.json" );
+~~~
+
+To change the font for standard text controls, this JSON syntax can be used:
+
+~~~{.json}
+{
+ "styles":
+ {
+ "textlabel":
+ {
+ "font-family":"FreeSerif",
+ "font-style":"{\"weight\":\"bold\",\"slant\":\"italic\"}",
+ "point-size":8
+ }
+ }
+}
+~~~
+
+However the same point-size is unlikely to be suitable for all text controls in an application.
+To set custom sizes simply set a "style name" for each case, and then provide a style override in JSON:
+
+~~~{.cpp}
+ // C++
+
+ label.SetProperty( Control::Property::STYLE_NAME, "custom" );
+~~~
+~~~{.js}
+ // JavaScript
+
+ label.styleName = "custom"';
+~~~
+
+~~~{.json}
+{
+ "styles":
+ {
+ "textlabel":
+ {
+ "font-family":"FreeSerif",
+ "font-style":"{\"weight\":\"bold\",\"slant\":\"italic\"}",
+ "point-size":8
+ },
+
+ "custom":
+ {
+ "point-size":10
+ }
+ }
+}
+~~~
+
+In the example above, standard text labels will have point-size 8, and "custom" labels will have point-size 10.
+
+*/
### Font Selection
-TextField will automatically select a suitable fonts, in the same was as TextLabel.
-The preferred font can also be selected from a JSON stylesheet:
-
-~~~{.json}
-{
- "styles":
- {
- "textfield":
- {
- "font-family":"Arial",
- "font-style":"Regular",
- "point-size":8
- }
- }
-}
-~~~
+By default TextField will automatically select a suitable font from the platform. However, a different font could be selected. See the [Font Selection](@ref font-selection) section for more details.
### Text Alignment
### Font Selection
-By default TextLabel will automatically select a suitable font from the platform.
-Typically fonts do not support all scripts, for example Latin fonts often do not provide Arabic glyphs.
-Therefore you should expect TextLabel to select different fonts for each script.
-
-Alternatively a font may be requested using either or all of FONT_FAMILY, FONT_STYLE, and POINT_SIZE properties:
-
-~~~{.cpp}
-// C++
-
-label.SetProperty( TextLabel::Property::FONT_FAMILY, "HelveticaNue" );
-label.SetProperty( TextLabel::Property::FONT_STYLE, "Regular" );
-label.SetProperty( TextLabel::Property::POINT_SIZE, 12.0f );
-~~~
-
-~~~{.js}
-// JavaScript
-
-label.fontFamily = "HelveticaNue";
-label.fontStyle = "Regular";
-label.pointSize = 12;
-~~~
-
-However the TextLabel will fall-back to using the default font, if the requested font does not support the required scripts.
-
-### Font Styles
-
-Setting a font size programmatically is not ideal for applications which support multiple screen resolutions etc.
-A more flexible approach is to prepare various JSON stylesheets, and request a different style for each platform:
-
-~~~{.cpp}
-// C++
-StyleManager styleManager = StyleManager::Get();
-styleManager.RequestThemeChange( "example-path/example.json" );
-~~~
-
-To change the font for standard text labels, this JSON syntax can be used:
-
-~~~{.json}
-{
- "styles":
- {
- "textlabel":
- {
- "font-family":"Arial",
- "font-style":"Regular",
- "point-size":8
- }
- }
-}
-~~~
-
-However the same point-size is unlikely to be suitable for all labels in an application.
-To set custom sizes simply set a "style name" for each case, and then provide a style override in JSON:
-
-~~~{.cpp}
- // C++
-
- label.SetProperty( Control::Property::STYLE_NAME, "custom" );
-~~~
-~~~{.js}
- // JavaScript
-
- label.styleName = "custom"';
-~~~
-
-~~~{.json}
-{
- "styles":
- {
- "textlabel":
- {
- "font-family":"Arial",
- "font-style":"Regular",
- "point-size":8
- },
-
- "custom":
- {
- "point-size":10
- }
- }
-}
-~~~
-
-In the example above, standard text labels will have point-size 8, and "custom" labels will have point-size 10.
+By default TextLabel will automatically select a suitable font from the platform. However, a different font could be selected. See the [Font Selection](@ref font-selection) section for more details.
### Text Alignment
}
// fire the scene create signal
- adaptor->SceneCreated();
+ adaptor->NotifySceneCreated();
mInitialized = true;
}
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.1.1
+Version: 1.1.2
Release: 1
Group: System/Libraries
License: Apache-2.0, BSD-2.0, MIT
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 --enable-profile=%{dali_toolkit_profile} --with-style=%{dali_style_folder}
+%configure --enable-profile=%{dali_toolkit_profile} --with-style=%{dali_style_folder} --enable-i18n=yes
make %{?jobs:-j%jobs}
##############################