From: Francisco Santos Date: Mon, 20 Apr 2015 15:10:09 +0000 (+0100) Subject: Revert to tizen branch. X-Git-Tag: dali_1.0.47~13^2~33 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=cd7d41bc8e0a0816da28401207091344fbbe0b2c Revert to tizen branch. Change-Id: I265ba0f78f94a1831ac0256d0385351ba7654721 --- diff --git a/README b/README index dc7b5af..de9499c 100644 --- a/README +++ b/README @@ -23,7 +23,10 @@ T.O.C. gbs build -A [TARGET_ARCH] --define "%enable_dali_smack_rules 1" +1.3. MOBILE Profile +------------------- + gbs build -A [TARGET_ARCH] --spec dali-toolkit-mobile.spec 2. Building for Ubuntu desktop ============================== diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 029c12d..e7dc7cb 100644 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -8,10 +8,6 @@ SET(CAPI_LIB "dali-toolkit-internal") # List of test case sources (Only these get parsed for test cases) SET(TC_SOURCES utc-Dali-PushButton.cpp - utc-Dali-TextView-HelperAndDebug.cpp - utc-Dali-TextView-Processor-Types.cpp - utc-Dali-TextView-Processor.cpp - utc-Dali-TextView-Relayout-Utilities.cpp ) # Append list of test harness files (Won't get parsed for test cases) diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp index 05ced5a..8d2734b 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-PushButton.cpp @@ -713,7 +713,7 @@ int UtcDaliPushButtonProperties(void) // Button::PROPERTY_LABEL_ACTOR { button.SetLabel( "LABEL_TEXT_CUSTOM" ); - DALI_TEST_EQUALS( "TextView", button.GetProperty( Button::Property::LABEL_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION ); + DALI_TEST_EQUALS( "TextLabel", button.GetProperty( Button::Property::LABEL_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION ); Property::Map map; map[ "type" ] = "Actor"; diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-HelperAndDebug.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-HelperAndDebug.cpp deleted file mode 100644 index f5e39e6..0000000 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-HelperAndDebug.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include - -// Internal headers are allowed here -#include -#include -#include -#include -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Internal; - -void dali_text_view_helper_and_debug_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void dali_text_view_helper_and_debug_cleanup(void) -{ - test_return_value = TET_PASS; -} - - -namespace -{ -// Data structures used to create an 'experiment' in TET cases - -const Toolkit::Internal::TextView::LayoutParameters DEFAULT_LAYOUT_PARAMETERS; -const Toolkit::Internal::TextView::VisualParameters DEFAULT_VISUAL_PARAMETERS; - -struct GetIndicesFromGlobalCharacterIndexTest -{ - std::string description; - std::string input; - std::size_t position; - std::size_t paragraphIndex; - std::size_t wordIndex; - std::size_t characterIndex; -}; - -/** - * Gets the paragraph, word, and character indices for a given text and a given position and checks the results with the given indices. - * - * If the test fails it prints a short description and the line where this function was called. - * - * @param description Short description of the experiment. - * @param input The input text. - * @param position Global position of the character. i.e in a text with with 1000 characters, position could be any value from 0 to 1000. - * @param resultParagraphIndex Index to the paragraph where the character is located. - * @param resultWordIndex Index to the word within the paragraph where the character is located. - * @param resultCharacterIndex Index to the character within the word where the character is located. - * @param location Where this function has been called. - * - * @return \e true if the experiment is successful. Otherwise returns \e false. - */ -bool TestGetIndicesFromGlobalCharacterIndex( const std::string& description, - const std::string& input, - const std::size_t position, - const std::size_t resultParagraphIndex, - const std::size_t resultWordIndex, - const std::size_t resultCharacterIndex, - const char* location ) -{ - tet_printf( "%s", description.c_str() ); - - // Create natural size, layout and text-actor info for the input word. - Toolkit::Internal::TextView::RelayoutData relayoutData; - TextViewProcessor::TextLayoutInfo& inputLayout( relayoutData.mTextLayoutInfo ); - - MarkupProcessor::StyledTextArray inputStyledText; - MarkupProcessor::GetStyledTextArray( input, inputStyledText, true ); - - TextViewProcessor::CreateTextInfo( inputStyledText, - DEFAULT_LAYOUT_PARAMETERS, - relayoutData ); - - TextViewProcessor::TextInfoIndices indices; - TextViewProcessor::GetIndicesFromGlobalCharacterIndex( position, - inputLayout, - indices ); - - if( indices.mParagraphIndex != resultParagraphIndex ) - { - tet_printf( "Fail. different paragraph index. %s", location ); - return false; - } - if( indices.mWordIndex != resultWordIndex ) - { - tet_printf( "Fail. different word index. %s", location ); - return false; - } - if( indices.mCharacterIndex != resultCharacterIndex ) - { - tet_printf( "Fail. different character index. %s", location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// -} // namespace - - -int UtcDaliTextViewGetIndicesFromGlobalCharacterIndex(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewGetIndicesFromGlobalCharacterIndex : "); - struct GetIndicesFromGlobalCharacterIndexTest getIndicesFromGlobalCharacterIndexTests[] = - { - { - std::string( "Test position 0" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 0, - 0, - 0, - 0 - }, - { - std::string( "Test position 76. (just after the last \\n)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 76, - 4, - 0, - 0 - }, - { - std::string( "Test position 73. (the last \\n)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 75, - 3, - 0, - 0 - }, - { - std::string( "Test position 35. (first hebrew character)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 35, - 1, - 4, - 0 - }, - { - std::string( "Test position 3. (end of the first word)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 3, - 0, - 0, - 3 - }, - { - std::string( "Test position 33. (end of the second word of the second paragraph)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 33, - 1, - 2, - 3 - }, - { - std::string( "Test position 43. (last hebrew character)" ), - std::string( "text text text text text\n" - "text text טקסט טקסט text\n" - "text text text text text\n" - "\n" ), - 43, - 1, - 6, - 3 - }, - }; - const std::size_t numberOfTests( 7 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const GetIndicesFromGlobalCharacterIndexTest& test = getIndicesFromGlobalCharacterIndexTests[index]; - - if( !TestGetIndicesFromGlobalCharacterIndex( test.description, test.input, test.position, test.paragraphIndex, test.wordIndex, test.characterIndex, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewDebugCouts(void) -{ - ///////////////////////////////////////////////////// - // Text debug functions to not to penalize coverage - ///////////////////////////////////////////////////// - - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewDebugCouts : "); - - Toolkit::Internal::TextView::RelayoutData relayoutData; - - MarkupProcessor::StyledTextArray inputStyledText; - MarkupProcessor::GetStyledTextArray( std::string( "Hello world\nhello world" ), inputStyledText, true ); - - TextViewProcessor::CreateTextInfo( inputStyledText, - DEFAULT_LAYOUT_PARAMETERS, - relayoutData ); - - Actor dummy = Actor::New(); - Toolkit::Internal::SplitByNewLineChar::Relayout( dummy, - Toolkit::Internal::TextView::RELAYOUT_ALL, - DEFAULT_LAYOUT_PARAMETERS, - DEFAULT_VISUAL_PARAMETERS, - relayoutData ); - - TextViewProcessor::dbgPrint( relayoutData.mTextLayoutInfo ); - - TextStyle textStyle; - TextViewProcessor::dbgPrint( textStyle ); - - TextViewProcessor::TextInfoIndices indices; - TextViewProcessor::dbgPrint( indices ); - - TextViewProcessor::dbgPrint( inputStyledText ); - - tet_result( TET_PASS ); - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor-Types.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor-Types.cpp deleted file mode 100644 index 44e25c0..0000000 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor-Types.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include - - -// Internal headers are allowed here -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Internal; - -void dali_text_view_processor_types_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void dali_text_view_processor_types_cleanup(void) -{ - test_return_value = TET_PASS; -} - - -namespace -{ -// Data structures used to create an 'experiment' in TET cases - -////////////////////////////////////////////////////////////////// -} // namespace - - -int UtcDaliTextViewDefaultConstructorDestructor_PT(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewDefaultConstructorDestructor : "); - - TextViewProcessor::TextInfoIndices indices; - DALI_TEST_EQUALS( indices.mParagraphIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( indices.mWordIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( indices.mCharacterIndex, 0u, TEST_LOCATION ); - - TextViewProcessor::CharacterLayoutInfo characterLayoutInfo; - DALI_TEST_EQUALS( characterLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mBearing, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mPosition, Vector3::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mOffset, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mUnderlineThickness, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo.mUnderlinePosition, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( !characterLayoutInfo.mGlyphActor ); - DALI_TEST_EQUALS( characterLayoutInfo.mColorAlpha, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( NULL == characterLayoutInfo.mGradientInfo ); - DALI_TEST_CHECK( characterLayoutInfo.mIsVisible ); - DALI_TEST_CHECK( !characterLayoutInfo.mSetText ); - DALI_TEST_CHECK( !characterLayoutInfo.mSetStyle ); - - TextViewProcessor::WordLayoutInfo wordLayoutInfo; - DALI_TEST_EQUALS( wordLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo.mAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo.mType, TextViewProcessor::NoSeparator, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo.mCharactersLayoutInfo.size(), 0u, TEST_LOCATION ); - - TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo; - DALI_TEST_EQUALS( paragraphLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo.mAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo.mLineHeightOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo.mWordsLayoutInfo.size(), 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo.mNumberOfCharacters, 0u, TEST_LOCATION ); - - TextViewProcessor::TextLayoutInfo textLayoutInfo; - DALI_TEST_EQUALS( textLayoutInfo.mWholeTextSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mMaxWordWidth, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mParagraphsLayoutInfo.size(), 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mNumberOfCharacters, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mMaxItalicsOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mEllipsizeLayoutInfo.mSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mEllipsizeLayoutInfo.mAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mEllipsizeLayoutInfo.mType, TextViewProcessor::NoSeparator, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.size(), 0u, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliTextViewCopyConstructorOperator(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCopyConstructorOperator : "); - - TextViewProcessor::CharacterLayoutInfo characterLayoutInfo; - characterLayoutInfo.mSize = Vector2( 1.f, 1.f ); - characterLayoutInfo.mBearing = 1.f; - characterLayoutInfo.mPosition = Vector3( 1.f, 1.f, 1.f ); - characterLayoutInfo.mOffset = Vector2( 1.f, 1.f ); - characterLayoutInfo.mAscender = 1.f; - characterLayoutInfo.mUnderlineThickness = 1.f; - characterLayoutInfo.mUnderlinePosition = 1.f; - - characterLayoutInfo.mGlyphActor = TextActor::New( "Hello" ); - - TextViewProcessor::GradientInfo* info = new TextViewProcessor::GradientInfo(); - info->mGradientColor = Vector4( 1.f, 1.f, 1.f, 1.f ); - info->mStartPoint = Vector2( 1.f, 1.f ); - info->mEndPoint = Vector2( 1.f, 1.f ); - - characterLayoutInfo.mColorAlpha = 0.f; - characterLayoutInfo.mGradientInfo = info; - - characterLayoutInfo.mIsVisible = false; - characterLayoutInfo.mSetText = false; - characterLayoutInfo.mSetStyle = false; - - TextViewProcessor::CharacterLayoutInfo characterLayoutInfo1; - characterLayoutInfo1 = characterLayoutInfo; - - DALI_TEST_EQUALS( characterLayoutInfo1.mBearing, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mPosition, Vector3( 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mOffset, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( characterLayoutInfo1.mGlyphActor ); - DALI_TEST_EQUALS( characterLayoutInfo1.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo1.mGradientInfo->mEndPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( !characterLayoutInfo1.mIsVisible ); - DALI_TEST_CHECK( !characterLayoutInfo1.mSetText ); - DALI_TEST_CHECK( !characterLayoutInfo1.mSetStyle ); - - TextViewProcessor::CharacterLayoutInfo characterLayoutInfo2( characterLayoutInfo ); - DALI_TEST_EQUALS( characterLayoutInfo2.mBearing, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mPosition, Vector3( 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mOffset, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlineThickness, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mUnderlinePosition, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( characterLayoutInfo2.mGlyphActor ); - DALI_TEST_EQUALS( characterLayoutInfo2.mColorAlpha, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mGradientColor, Vector4( 1.f, 1.f, 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mStartPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( characterLayoutInfo2.mGradientInfo->mEndPoint, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( !characterLayoutInfo2.mIsVisible ); - DALI_TEST_CHECK( !characterLayoutInfo2.mSetText ); - DALI_TEST_CHECK( !characterLayoutInfo2.mSetStyle ); - - // Increases coverage. - characterLayoutInfo2.mGlyphActor.Reset(); - characterLayoutInfo1 = characterLayoutInfo2; - DALI_TEST_CHECK( !characterLayoutInfo1.mGlyphActor ); - - TextViewProcessor::WordLayoutInfo wordLayoutInfo; - wordLayoutInfo.mSize = Vector2( 1.f, 1.f ); - wordLayoutInfo.mAscender = 1.f; - wordLayoutInfo.mType = TextViewProcessor::ParagraphSeparator; - - TextViewProcessor::WordLayoutInfo wordLayoutInfo1; - wordLayoutInfo1 = wordLayoutInfo; - - DALI_TEST_EQUALS( wordLayoutInfo1.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo1.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo1.mType, TextViewProcessor::ParagraphSeparator, TEST_LOCATION ); - - TextViewProcessor::WordLayoutInfo wordLayoutInfo2( wordLayoutInfo ); - - DALI_TEST_EQUALS( wordLayoutInfo2.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo2.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( wordLayoutInfo2.mType, TextViewProcessor::ParagraphSeparator, TEST_LOCATION ); - - TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo; - paragraphLayoutInfo.mSize = Vector2( 1.f, 1.f ); - paragraphLayoutInfo.mAscender = 1.f; - paragraphLayoutInfo.mLineHeightOffset = 1.f; - paragraphLayoutInfo.mNumberOfCharacters = 1u; - - TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo1; - paragraphLayoutInfo1 = paragraphLayoutInfo; - - DALI_TEST_EQUALS( paragraphLayoutInfo1.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo1.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo1.mLineHeightOffset, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo1.mNumberOfCharacters, 1u, TEST_LOCATION ); - - TextViewProcessor::ParagraphLayoutInfo paragraphLayoutInfo2( paragraphLayoutInfo ); - - DALI_TEST_EQUALS( paragraphLayoutInfo2.mSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo2.mAscender, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo2.mLineHeightOffset, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( paragraphLayoutInfo2.mNumberOfCharacters, 1u, TEST_LOCATION ); - - TextViewProcessor::TextLayoutInfo textLayoutInfo; - textLayoutInfo.mWholeTextSize = Vector2( 1.f, 1.f ); - textLayoutInfo.mMaxWordWidth = 1.f; - textLayoutInfo.mNumberOfCharacters = 1u; - textLayoutInfo.mMaxItalicsOffset = 1.f; - - TextViewProcessor::TextLayoutInfo textLayoutInfo1; - textLayoutInfo1 = textLayoutInfo; - - DALI_TEST_EQUALS( textLayoutInfo1.mWholeTextSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo1.mMaxWordWidth, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo1.mNumberOfCharacters, 1u, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo1.mMaxItalicsOffset, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - - TextViewProcessor::TextLayoutInfo textLayoutInfo2( textLayoutInfo ); - - DALI_TEST_EQUALS( textLayoutInfo2.mWholeTextSize, Vector2( 1.f, 1.f ), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo2.mMaxWordWidth, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo2.mNumberOfCharacters, 1u, TEST_LOCATION ); - DALI_TEST_EQUALS( textLayoutInfo2.mMaxItalicsOffset, 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliTextViewEqualityOperator(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewEqualityOperator : "); - - TextViewProcessor::TextInfoIndices indices; - TextViewProcessor::TextInfoIndices indices1( 1u, 1u, 1u ); - - DALI_TEST_CHECK( !( indices == indices1 ) ); - - indices = indices1; - - DALI_TEST_CHECK( indices == indices1 ); - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor.cpp deleted file mode 100644 index 8fef857..0000000 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Processor.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include -#include -#include - -// Internal headers are allowed here -#include -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Internal; - -void dali_text_view_processor_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void dali_text_view_processor_cleanup(void) -{ - test_return_value = TET_PASS; -} - - -namespace -{ -// Data structures used to create an 'experiment' in TET cases - -////////////////////////////////////////////////////////////////// - -struct BeginsRightToLeftCharacterTest -{ - std::string description; - std::string input; - bool result; -}; - -bool TestBeginsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location ) -{ - // Creates a text with the string. - Text text( input ); - - const bool ret = ( result == TextProcessor::BeginsRightToLeftCharacter( text ) ); - - if( !ret ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Input : %s", input.c_str() ); - } - - return ret; -} - -////////////////////////////////////////////////////////////////// - -struct ContainsRightToLeftCharacterTest -{ - std::string description; - std::string input; - bool result; -}; - -bool TestContainsRightToLeftCharacter( const std::string& description, const std::string& input, const bool result, const char* location ) -{ - // Creates a text with the string. - Text text( input ); - - const bool ret = ( result == TextProcessor::ContainsRightToLeftCharacter( text ) ); - - if( !ret ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Input : %s", input.c_str() ); - } - - return ret; -} - -////////////////////////////////////////////////////////////////// - -struct FindNearestWordTest -{ - std::string description; - std::string input; - std::size_t offset; - std::size_t start; - std::size_t end; -}; - -bool TestFindNearestWord( const std::string& description, const std::string& input, const std::size_t offset, const std::size_t startResult, const std::size_t endResult, const char* location ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( input, styledText, true ); - - std::size_t start; - std::size_t end; - TextProcessor::FindNearestWord( styledText, offset, start, end ); - - const bool ret = ( start == startResult ) && ( end == endResult ); - - if( !ret ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Input : %s, offset %d, start %d, end %d", input.c_str(), offset, start, end ); - } - - return ret; -} - -////////////////////////////////////////////////////////////////// - -struct SplitInParagraphsTest -{ - std::string inputText; - - std::size_t resultNumberOfParagraphs; -}; - -bool TestSplitInParagraphs( const SplitInParagraphsTest& test, const char* location ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( test.inputText, styledText, true ); - - std::vector paragraphs; - std::vector< Vector > styles; - - TextProcessor::SplitInParagraphs( styledText, - paragraphs, - styles ); - - if( paragraphs.size() != test.resultNumberOfParagraphs ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Different number of paragraphs, result %d, expected result %d", paragraphs.size(), test.resultNumberOfParagraphs ); - - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -struct SplitInWordsTest -{ - std::string inputText; - - std::size_t resultNumberOfSeparators; -}; - -bool TestSplitInWords( const SplitInWordsTest& test, const char* location ) -{ - // Creates a text with the string. - Text text( test.inputText ); - - Vector positions; - - TextProcessor::SplitInWords( text, - positions ); - - if( positions.Count() != test.resultNumberOfSeparators ) - { - tet_printf( "Fail. %s", location ); - tet_printf( "Different number of separators, result %d, expected result %d", positions.Count(), test.resultNumberOfSeparators ); - - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -} // namespace - - -int UtcDaliTextViewSplitInParagraphs(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewSplitInParagraphs : "); - - struct SplitInParagraphsTest splitInParagraphsTest[] = - { - { - std::string( "Hello world\nhello world." ), - 2 - }, - { - std::string( "Hello world\nhello world.\n\n" ), - 4 - } - }; - const std::size_t numberOfTests( 2 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const SplitInParagraphsTest& test = splitInParagraphsTest[index]; - - if( !TestSplitInParagraphs( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewSplitInWords(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewSplitInWords : "); - - struct SplitInWordsTest splitInWordsTest[] = - { - { - std::string( "Hello world, hello word!" ), - 3u - }, - { - std::string( "Hello world\n" ), - 2u - } - }; - const std::size_t numberOfTests( 2u ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const SplitInWordsTest& test = splitInWordsTest[index]; - - if( !TestSplitInWords( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewBeginsRightToLeftCharacter(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewBeginsRightToLeftCharacter : "); - - struct BeginsRightToLeftCharacterTest beginsRightToLeftCharacterTest[] = - { - { - std::string( "Test if it begins with a right to left character. Should return false." ), - std::string( "Hello world مرحبا العالم." ), - false - }, - { - std::string( "Test if it begins with a right to left character. Should return true." ), - std::string( "مرحبا العالم Hola mundo." ), - true - } - }; - const std::size_t numberOfTests( 2 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const BeginsRightToLeftCharacterTest& test = beginsRightToLeftCharacterTest[index]; - - if( !TestBeginsRightToLeftCharacter( test.description, test.input, test.result, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewContainsRightToLeftCharacter(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewContainsRightToLeftCharacter : "); - - struct ContainsRightToLeftCharacterTest containsRightToLeftCharacterTest[] = - { - { - std::string( "Test if it contains a right to left character. Should return true." ), - std::string( "Hello world مرحبا العالم." ), - true - }, - { - std::string( "Test if it contains a right to left character. Should return true." ), - std::string( "مرحبا العالم Hola mundo." ), - true - }, - { - std::string( "Test if it contains a right to left character. Should return false." ), - std::string( "Hello world." ), - false - }, - { - std::string( "Test if it contains a right to left character. Should return true." ), - std::string( "مرحبا العالم." ), - true - } - }; - const std::size_t numberOfTests( 4 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const ContainsRightToLeftCharacterTest& test = containsRightToLeftCharacterTest[index]; - - if( !TestContainsRightToLeftCharacter( test.description, test.input, test.result, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewFindNearestWord(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewFindNearestWord : "); - - struct FindNearestWordTest findNearestWordTest[] = - { - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 0u, - 0u, - 5u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 7u, - 6u, - 12u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 11u, - 6u, - 12u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 23u, - 18u, - 23u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo" ), - 5u, - 0u, - 5u - }, - { - std::string( "" ), - std::string( "Hello world, hola mundo مرحبا العالم" ), - 24u, - 25u, - 30u - } - }; - - const std::size_t numberOfTests( 6 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const FindNearestWordTest& test = findNearestWordTest[index]; - - if( !TestFindNearestWord( test.description, test.input, test.offset, test.start, test.end, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Relayout-Utilities.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Relayout-Utilities.cpp deleted file mode 100644 index 3bf0a46..0000000 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-TextView-Relayout-Utilities.cpp +++ /dev/null @@ -1,833 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include -#include -#include - -// Internal headers are allowed here -#include -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Internal; - -void dali_text_view_relayout_utils_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void dali_text_view_relayout_utils_cleanup(void) -{ - test_return_value = TET_PASS; -} - -namespace -{ - -const Toolkit::Internal::TextView::LayoutParameters DEFAULT_LAYOUT_PARAMETERS; - -// Data structures used to create an 'experiment' in TET cases - - -bool TestEqual( float x, float y ) -{ - return ( fabsf( x - y ) < Math::MACHINE_EPSILON_1000 ); -} - -////////////////////////////////////////////////////////////////// - -struct CalculateLineLayoutTest -{ - std::string description; - std::string inputParagraph; - float parentWidth; - std::size_t wordIndex; - std::size_t characterIndex; - std::size_t characterParagraphIndex; - TextViewRelayout::HorizontalWrapType splitPolicy; - float shrinkFactor; - - float resultLineLength; - float resultMaxCharHeight; - float resultMaxAscender; -}; - -bool TestCalculateLineLayout( const CalculateLineLayoutTest& test, const char* location ) -{ - tet_printf( "%s", test.description.c_str() ); - - // Create styled text. - MarkupProcessor::StyledTextArray inputStyledText; - MarkupProcessor::GetStyledTextArray( test.inputParagraph, inputStyledText, true ); - - // Create styled text layout info. - Toolkit::Internal::TextView::RelayoutData relayoutData; - TextViewProcessor::CreateTextInfo( inputStyledText, - DEFAULT_LAYOUT_PARAMETERS, - relayoutData ); - - // Prepare input parameters and the result structure and call the function to be tested. - - // Creaqte indices. - TextViewProcessor::TextInfoIndices indices( 0u, test.wordIndex, test.characterIndex ); - indices.mCharacterParagraphIndex = test.characterParagraphIndex; - - // Get the input paragraph. - TextViewProcessor::ParagraphLayoutInfo inputParagraphLayout; - - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - inputParagraphLayout = *relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(); - } - - // Result struct. - TextViewRelayout::LineLayoutInfo resultLayoutInfo; - - CalculateLineLayout( test.parentWidth, - indices, - inputParagraphLayout, - test.splitPolicy, - test.shrinkFactor, - resultLayoutInfo ); - - // Check results. - if( !TestEqual( test.resultLineLength, resultLayoutInfo.mLineLength ) ) - { - tet_printf( "Fail. different line length %f == %f. %s", test.resultLineLength, resultLayoutInfo.mLineLength, location ); - return false; - } - - if( !TestEqual( test.resultMaxCharHeight, resultLayoutInfo.mMaxCharHeight ) ) - { - tet_printf( "Fail. different max character height %f == %f. %s", test.resultMaxCharHeight, resultLayoutInfo.mMaxCharHeight, location ); - return false; - } - - if( !TestEqual( test.resultMaxAscender, resultLayoutInfo.mMaxAscender ) ) - { - tet_printf( "Fail. different max ascender %f == %f. %s", test.resultMaxAscender, resultLayoutInfo.mMaxAscender, location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -struct AlignmentOffsetTest -{ - Toolkit::Alignment::Type alignment; - float parentSize; - float wholeTextSize; - - float resultOffset; -}; - -bool TestAlignmentOffset( const AlignmentOffsetTest& test, const char* location ) -{ - float offset = 0.f; - - switch( test.alignment ) - { - case Toolkit::Alignment::HorizontalLeft: - case Toolkit::Alignment::HorizontalCenter: - case Toolkit::Alignment::HorizontalRight: - { - offset = TextViewRelayout::CalculateXoffset( test.alignment, test.parentSize, test.wholeTextSize ); - break; - } - case Toolkit::Alignment::VerticalTop: - case Toolkit::Alignment::VerticalCenter: - case Toolkit::Alignment::VerticalBottom: - { - offset = TextViewRelayout::CalculateYoffset( test.alignment, test.parentSize, test.wholeTextSize ); - break; - } - } - - // Check results. - if( !TestEqual( test.resultOffset, offset ) ) - { - tet_printf( "Fail. different offset %f == %f. %s", test.resultOffset, offset, location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -struct JustificationOffsetTest -{ - Toolkit::TextView::LineJustification justification; - float wholeTextWidth; - float lineLength; - - float resultOffset; -}; - -bool TestJustificationOffset( const JustificationOffsetTest& test, const char* location ) -{ - float offset = TextViewRelayout::CalculateJustificationOffset( test.justification, test.wholeTextWidth, test.lineLength ); - - // Check results. - if( !TestEqual( test.resultOffset, offset ) ) - { - tet_printf( "Fail. different offset %f == %f. %s", test.resultOffset, offset, location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -struct CalculateVisibilityTest -{ - Vector3 position; - Size size; - Size parentSize; - TextViewRelayout::VisibilityTestType type; - - bool resultVisible; -}; - -bool TestCalculateVisibility( const CalculateVisibilityTest& test, const char* location ) -{ - if( test.resultVisible != TextViewRelayout::IsVisible( test.position, test.size, test.parentSize, test.type ) ) - { - tet_printf( "Fail. different visibility. Type %d, %s", test.type, location ); - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////// - -} // namespace - - -int UtcDaliTextViewDefaultConstructorDestructor_RU(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewDefaultConstructorDestructor : "); - - // Test RelayoutParameters defaults. - TextViewRelayout::RelayoutParameters relayoutParameters; - - DALI_TEST_EQUALS( relayoutParameters.mPositionOffset, Vector3::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mParagraphSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mWordSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mCharacterSize, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mIndices.mParagraphIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mIndices.mWordIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mIndices.mCharacterIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( relayoutParameters.mCharacterGlobalIndex, 0u, TEST_LOCATION ); - DALI_TEST_CHECK( !relayoutParameters.mIsFirstCharacter ); - DALI_TEST_CHECK( !relayoutParameters.mIsFirstCharacterOfWord ); - DALI_TEST_CHECK( !relayoutParameters.mIsNewLine ); - DALI_TEST_CHECK( !relayoutParameters.mIsNewParagraphCharacter ); - DALI_TEST_CHECK( !relayoutParameters.mIsWhiteSpace ); - DALI_TEST_CHECK( !relayoutParameters.mIsVisible ); - - // Test FadeParameter defaults - TextViewRelayout::FadeParameters fadeParameters; - - DALI_TEST_EQUALS( fadeParameters.mRightFadeBoundary, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mRightFadeThreshold, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mRightFadeBoundaryOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mRightFadeThresholdOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mRightAlphaCoeficients, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftFadeBoundary, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftFadeThreshold, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftFadeBoundaryOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftFadeThresholdOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mLeftAlphaCoeficients, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopFadeBoundary, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopFadeThreshold, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopFadeBoundaryOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopFadeThresholdOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mTopAlphaCoeficients, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomFadeBoundary, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomFadeThreshold, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomFadeBoundaryOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomFadeThresholdOffset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( fadeParameters.mBottomAlphaCoeficients, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_CHECK( !fadeParameters.mIsPartiallyVisible ); - - // Test EllipsizeParameters defaults - TextViewRelayout::EllipsizeParameters ellipsizeParameters; - - DALI_TEST_EQUALS( ellipsizeParameters.mPosition, Vector3::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mLineDescender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mLineWidth, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mEllipsizeBoundary, Vector2::ZERO, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mFirstIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( ellipsizeParameters.mLastIndex, 0u, TEST_LOCATION ); - DALI_TEST_CHECK( !ellipsizeParameters.mEllipsizeLine ); - DALI_TEST_CHECK( !ellipsizeParameters.mIsLineWidthFullyVisible ); - DALI_TEST_CHECK( !ellipsizeParameters.mIsLineHeightFullyVisible ); - DALI_TEST_CHECK( !ellipsizeParameters.mIsNextLineFullyVisibleHeight ); - DALI_TEST_CHECK( !ellipsizeParameters.mCreateEllipsizedTextActors ); - DALI_TEST_CHECK( !ellipsizeParameters.mLineFits ); - DALI_TEST_CHECK( !ellipsizeParameters.mWordFits ); - - // Test UnderlineInfo defaults - TextViewRelayout::UnderlineInfo underlineInfo; - - DALI_TEST_EQUALS( underlineInfo.mMaxHeight, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( underlineInfo.mMaxThickness, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( underlineInfo.mPosition, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - - // Test TextUnderlineStatus defaults - TextViewRelayout::TextUnderlineStatus textUnderlineStatus; - - DALI_TEST_CHECK( textUnderlineStatus.mUnderlineInfo.empty() ); - DALI_TEST_EQUALS( textUnderlineStatus.mCharacterGlobalIndex, 0u, TEST_LOCATION ); - DALI_TEST_EQUALS( textUnderlineStatus.mLineGlobalIndex, 0u, TEST_LOCATION ); - DALI_TEST_CHECK( !textUnderlineStatus.mCurrentUnderlineStatus ); - - // Test LineLayoutInfo defaults - TextViewRelayout::LineLayoutInfo lineLayoutInfo; - - DALI_TEST_EQUALS( lineLayoutInfo.mLineLength, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( lineLayoutInfo.mMaxCharHeight, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - DALI_TEST_EQUALS( lineLayoutInfo.mMaxAscender, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliTextViewCalculateLineLayout(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCalculateLineLayout : "); - - struct CalculateLineLayoutTest calculateLineLayoutTest[] = - { - //WrapByCharacter - { - "The paragraph is wraped by character. All characters have the same size.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices - 0, - 0, - TextViewRelayout::WrapByCharacter, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by character. There are characters with different sizes.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices - 0, - 0, - TextViewRelayout::WrapByCharacter, // split policy - 1.f, - // results - 94.835075f, // line length. (only fits 8 characters 6x11.38 + 2x13.27) - 13.276911f, // max character height - 11.949220f // max ascender - }, - { - "The paragraph is wraped by character. There are characters with different sizes. It calculates the layout for the second line.", - "Hello world hello world", // input paragraph - 100.f, // parent width - 2, // indices. The third character of the third word starts in a new line. - 2, - 8, - TextViewRelayout::WrapByCharacter, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by character. There are characters with different sizes. It calculates the layout for the third line.", - "Hello world hello world", // input paragraph - 100.f, // parent width - 4, // indices. The fifth character of the fifth word starts in a new line. - 4, - 16, - TextViewRelayout::WrapByCharacter, // split policy - 1.f, - // results - 92.938377f, // line length. (only fits 8 characters 8x11.38) - 13.276911f, // max character height - 11.949220f // max ascender - }, - - //WrapByWord - { - "The paragraph is wraped by word. All characters have the same size.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices. It shouldn't use the index character so 9999999 shouldn't make it crash. - 9999999, - 9999999, - TextViewRelayout::WrapByWord, // split policy - 1.f, - // results - 56.901047f, // line length. (only fits 5 characters 5x11.38, white space is not counted) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by word. There are characters with different sizes.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices. - 0, - 0, - TextViewRelayout::WrapByWord, // split policy - 1.f, - // results - 58.797747f, // line length. (only fits 5 characters 4x11.38 + 13.276911, white space is not counted) - 13.276911f, // max character height - 11.949220f // max ascender - }, - { - "The paragraph is wraped by word. There are characters with different sizes. It calculates the layout for the second line.", - "Hello world hello world", // input paragraph - 100.f, // parent width - 2, // indices. The third word starts in a new line. - 0, - 6, - TextViewRelayout::WrapByWord, // split policy - 1.f, - // results - 60.694449f, // line length. (only fits 5 characters 2x13.276911 + 3x11.38) - 13.276911f, // max character height - 11.949220f // max ascender - }, - { - "The paragraph is wraped by word. The word doen't fit.", - "Hello world", // input paragraph - 40.f, // parent width - 0, // indices. The third word starts in a new line. - 0, - 0, - TextViewRelayout::WrapByWord, // split policy - 1.f, - // results - 0.f, // line length. (The word doesn't fit) - 11.380209f, // max character height - 10.242188f // max ascender - }, - - //WrapByWordAndSplit - { - "The paragraph is wraped by word and by character. All characters have the same size. There is not a long word.", - "Hello world hello world", // input paragraph - 100.f, // parent width - 0, // indices. - 0, - 0, - TextViewRelayout::WrapByWordAndSplit, // split policy - 1.f, - // results - 56.901047f, // line length. (only fits 5 characters 5x11.38, white space is not counted) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by word and by character. All characters have the same size. There is a long word.", - "Helloooooooo world", // input paragraph - 100.f, // parent width - 0, // indices. - 0, - 0, - TextViewRelayout::WrapByWordAndSplit, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by word and by character. There are characters with different sizes. There is a long word. It calculates the layout for the second line.", - "Helloooooooo world", // input paragraph - 100.f, // parent width - 0, // indices. - 8, - 8, - TextViewRelayout::WrapByWordAndSplit, // split policy - 1.f, - // results - 45.520836f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by word and by character. There are characters with different sizes. There is a shrink factor.", - "Helloooooooo world", // input paragraph - 100.f, // parent width - 0, // indices. - 8, - 8, - TextViewRelayout::WrapByWordAndSplit, // split policy - 0.7f, - // results - 95.593755f, // line length. (only fits 12 characters 8x11.38) - 7.9661463f, // max character height - 7.169531f // max ascender - }, - - //WrapByParagraphCharacterAndSplit - { - "The paragraph is wraped by end of paragraph and by character. All characters have the same size.", - "Hello world", // input paragraph - 100.f, // parent width - 0, // indices - 0, - 0, - TextViewRelayout::WrapByParagraphCharacterAndSplit, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph fits in the width.", - "Hello", // input paragraph - 100.f, // parent width - 0, // indices - 0, - 0, - TextViewRelayout::WrapByParagraphCharacterAndSplit, // split policy - 1.f, - // results - 56.901047f, // line length. (only fits 5 characters 5x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - { - "The paragraph is wraped by end of paragraph and by character. All characters have the same size. It calculates the layout for the second line.", - "Hello world, hello world", // input paragraph - 100.f, // parent width - 2, // indices - 2, - 8, - TextViewRelayout::WrapByParagraphCharacterAndSplit, // split policy - 1.f, - // results - 91.041672f, // line length. (only fits 8 characters 8x11.38) - 11.380209f, // max character height - 10.242188f // max ascender - }, - }; - const std::size_t numberOfTests( 15 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const CalculateLineLayoutTest& test = calculateLineLayoutTest[index]; - - if( !TestCalculateLineLayout( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewCalculateAlignmentOffsets(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCalculateAlignmentOffsets : "); - - struct AlignmentOffsetTest alignmentOffsetTest[] = - { - { - Toolkit::Alignment::HorizontalLeft, - 100.f, - 75.f, - 0.f - }, - { - Toolkit::Alignment::HorizontalCenter, - 100.f, - 75.f, - 12.5f - }, - { - Toolkit::Alignment::HorizontalRight, - 100.f, - 75.f, - 25.f - }, - { - Toolkit::Alignment::VerticalTop, - 100.f, - 75.f, - 0.f - }, - { - Toolkit::Alignment::VerticalCenter, - 100.f, - 75.f, - 12.5f - }, - { - Toolkit::Alignment::VerticalBottom, - 100.f, - 75.f, - 25.f - } - }; - const std::size_t numberOfTests( 6 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const AlignmentOffsetTest& test = alignmentOffsetTest[index]; - - if( !TestAlignmentOffset( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewCalculateJustificationOffsets(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCalculateJustificationOffsets : "); - - struct JustificationOffsetTest justificationOffsetTest[] = - { - { - Toolkit::TextView::Left, - 100.f, - 75.f, - 0.f - }, - { - Toolkit::TextView::Justified, - 100.f, - 75.f, - 0.f - }, - { - Toolkit::TextView::Center, - 100.f, - 150.f, - -25.f - }, - { - Toolkit::TextView::Right, - 100.f, - 75.f, - 25.f - }, - }; - const std::size_t numberOfTests( 4 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const JustificationOffsetTest& test = justificationOffsetTest[index]; - - if( !TestJustificationOffset( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - - -int UtcDaliTextViewCalculateVisibility(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewCalculateVisibility : "); - - struct CalculateVisibilityTest calculateVisibilityTest[] = - { - { - Vector3( 0.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE, - true - }, - { - Vector3( 10.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE, - true - }, - { - Vector3( 0.f, 10.f, 0.f ), - Size( 150.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE, - false - }, - { - Vector3( 0.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE_WIDTH, - true - }, - { - Vector3( 95.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE_WIDTH, - false - }, - { - Vector3( 0.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE_HEIGHT, - true - }, - { - Vector3( 0.f, 0.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::FULLY_VISIBLE_HEIGHT, - false - }, - { - Vector3( -10.f, 10.f, 0.f ), - Size( 150.f, 150.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE, - true - }, - { - Vector3( -100.f, -100.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE, - false - }, - { - Vector3( -10.f, 10.f, 0.f ), - Size( 50.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE_WIDTH, - true - }, - { - Vector3( 110.f, 10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE_WIDTH, - false - }, - { - Vector3( 0.f, 20.f, 0.f ), - Size( 10.f, 50.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE_HEIGHT, - true - }, - { - Vector3( 0.f, -10.f, 0.f ), - Size( 10.f, 10.f ), - Size( 100.f, 100.f ), - TextViewRelayout::PARTIALLY_VISIBLE_HEIGHT, - false - }, - }; - const std::size_t numberOfTests( 13 ); - - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const CalculateVisibilityTest& test = calculateVisibilityTest[index]; - - if( !TestCalculateVisibility( test, TEST_LOCATION ) ) - { - tet_result( TET_FAIL ); - } - } - - tet_result( TET_PASS ); - END_TEST; -} - -int UtcDaliTextViewMiscelaneousAsserts(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliTextViewMiscelaneousAsserts : "); - - float offset = 0.f; - - bool assert1 = false; - bool assert2 = false; - try - { - offset = Toolkit::Internal::TextViewRelayout::CalculateXoffset( Toolkit::Alignment::VerticalTop, 100.f, 50.f ); - } - catch( Dali::DaliException& e ) - { - DALI_TEST_PRINT_ASSERT( e ); - DALI_TEST_EQUALS( e.condition, "!\"TextViewRelayout::CalculateXoffset: Wrong horizontal text alignment. Did you set a vertical one?\"", TEST_LOCATION ); - assert1 = true; - } - catch( ... ) - { - tet_result( TET_FAIL ); - } - DALI_TEST_EQUALS( offset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - - try - { - offset = Toolkit::Internal::TextViewRelayout::CalculateYoffset( Toolkit::Alignment::HorizontalRight, 100.f, 50.f ); - } - catch( Dali::DaliException& e ) - { - DALI_TEST_PRINT_ASSERT( e ); - DALI_TEST_EQUALS( e.condition, "!\"TextViewRelayout::CalculateXoffset: Wrong vertical text alignment. Did you set an horizontal one?\"", TEST_LOCATION ); - assert2 = true; - } - catch( ... ) - { - tet_result( TET_FAIL ); - } - DALI_TEST_EQUALS( offset, 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); - - DALI_TEST_CHECK( assert1 && assert2 ); - - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index a3f7172..62d0174 100644 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -37,6 +37,8 @@ SET(TC_SOURCES utc-Dali-SpotEffect.cpp utc-Dali-SquareDissolveEffect.cpp utc-Dali-TableView.cpp + utc-Dali-TextField.cpp + utc-Dali-TextLabel.cpp utc-Dali-ToolBar.cpp utc-Dali-View.cpp utc-Dali-WaterEffect.cpp @@ -51,7 +53,6 @@ SET(TC_SOURCES utc-Dali-ItemLayout.cpp utc-Dali-ItemView.cpp utc-Dali-KeyboardFocusManager.cpp - utc-Dali-MarkupProcessor.cpp utc-Dali-MaskEffect.cpp utc-Dali-NinePatchMaskEffect.cpp utc-Dali-Popup.cpp diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp index cc16ab0..92d1390 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp @@ -287,7 +287,7 @@ ConstraintAppliedCheck::ConstraintAppliedCheck( bool& signalReceived ) { } -void ConstraintAppliedCheck::operator()( ActiveConstraint& constraint ) +void ConstraintAppliedCheck::operator()( Constraint& constraint ) { mSignalReceived = true; } diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h index 98fc629..44f2da9 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h @@ -139,13 +139,13 @@ inline bool CompareType(Quaternion q1, Quaternion q2, float epsilon) template <> inline bool CompareType(Radian q1, Radian q2, float epsilon) { - return CompareType(float(q1), float(q2), epsilon); + return CompareType(q1.radian, q2.radian, epsilon); } template <> inline bool CompareType(Degree q1, Degree q2, float epsilon) { - return CompareType(float(q1), float(q2), epsilon); + return CompareType(q1.degree, q2.degree, epsilon); } bool operator==(TimePeriod a, TimePeriod b); @@ -296,41 +296,6 @@ void DALI_TEST_EQUALS( const std::string &str1, const char* str2, const char* lo void DALI_TEST_EQUALS( const char* str1, const std::string &str2, const char* location); /** - * Test whether two UTF32 strings are equal. - * @param[in] str1 The first string - * @param[in] str2 The second string - * @param[in] location The TEST_LOCATION macro should be used here - */ -template<> -inline void DALI_TEST_EQUALS( const Integration::TextArray& str1, const Integration::TextArray& str2, const char* location) -{ - if( !std::equal( str1.Begin(), str1.End(), str2.Begin() ) ) - { - fprintf(stderr, "%s, checking '", location); - - for( unsigned int i = 0; i < str1.Count(); ++i ) - { - fprintf(stderr, "%c", str1[i]); - } - - fprintf(stderr, "' == '"); - - for( unsigned int i = 0; i < str2.Count(); ++i ) - { - fprintf(stderr, "%c", str2[i]); - } - - fprintf(stderr, "'\n"); - - tet_result(TET_FAIL); - } - else - { - tet_result(TET_PASS); - } -} - -/** * Test whether one unsigned integer value is greater than another. * Test succeeds if value1 > value2 * @param[in] value1 The first value @@ -371,7 +336,7 @@ inline void DALI_TEST_PRINT_ASSERT( DaliException& e ) struct ConstraintAppliedCheck { ConstraintAppliedCheck( bool& signalReceived ); - void operator()( ActiveConstraint& constraint ); + void operator()( Constraint& constraint ); void Reset(); void CheckSignalReceived(); void CheckSignalNotReceived(); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp index e2b419e..3557c0d 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp @@ -110,8 +110,7 @@ DummyControlImplOverride::~DummyControlImplOverride() { } void DummyControlImplOverride::OnInitialize() { initializeCalled = true; } -void DummyControlImplOverride::OnThemeChange(StyleManager change) { themeChangeCalled = true;} -void DummyControlImplOverride::OnFontChange(bool defaultFontChange, bool defaultFontSizeChange) { fontChangeCalled = true; } +void DummyControlImplOverride::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) { themeChangeCalled = change.themeChange; fontChangeCalled = change.defaultFontSizeChange; } void DummyControlImplOverride::OnPinch(const PinchGesture& pinch) { pinchCalled = true; } void DummyControlImplOverride::OnPan(const PanGesture& pan) { panCalled = true; } void DummyControlImplOverride::OnTap(const TapGesture& tap) { tapCalled = true; } diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h index d923ac18..473a01d 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h @@ -102,8 +102,7 @@ private: private: // From Internal::Control virtual void OnInitialize(); - virtual void OnThemeChange( StyleManager styleManager ); - virtual void OnFontChange(bool defaultFontChange, bool defaultFontSizeChange); + virtual void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); virtual void OnPinch(const PinchGesture& pinch); virtual void OnPan(const PanGesture& pan); virtual void OnTap(const TapGesture& tap); diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h index b094fde..36cb94b 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h @@ -19,8 +19,10 @@ */ // EXTERNAL INCLUDES +#include // fprintf #include #include +#include // for strcpy, strncpy #include // INTERNAL INCLUDES diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp index 5ab4b7d..3d4d1d5 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp @@ -80,23 +80,13 @@ void TestPlatformAbstraction::GetClosestImageSize( Integration::ResourcePointer mTrace.PushCall("GetClosestImageSize", ""); } - /** * @copydoc PlatformAbstraction::LoadResource() */ void TestPlatformAbstraction::LoadResource(const Integration::ResourceRequest& request) { std::ostringstream out; - out << "Type:"; - if( request.GetType()->id == Integration::ResourceText ) - { - out << "Text"; - } - else - { - out << request.GetType()->id; - } - out << ", Path: " << request.GetPath() << std::endl ; + out << "Type:" << request.GetType()->id << ", Path: " << request.GetPath() << std::endl; mTrace.PushCall("LoadResource", out.str()); if(mRequest != NULL) @@ -170,145 +160,20 @@ bool TestPlatformAbstraction::IsLoading() } /** - * @copydoc PlatformAbstraction::GetDefaultFontFamily() + * @copydoc PlatformAbstraction::GetDefaultFontDescription() */ -const std::string& TestPlatformAbstraction::GetDefaultFontFamily() const +void TestPlatformAbstraction::GetDefaultFontDescription( std::string& family, std::string& style ) const { - mTrace.PushCall("GetDefaultFontFamily", ""); - return mGetDefaultFontFamilyResult; + // TODO } /** * @copydoc PlatformAbstraction::GetDefaultFontSize() */ -float TestPlatformAbstraction::GetDefaultFontSize() const -{ - mTrace.PushCall("GetDefaultFontSize", ""); - return mGetDefaultFontSizeResult; -} - -PixelSize TestPlatformAbstraction::GetFontLineHeightFromCapsHeight(const std::string& fontFamily, const std::string& fontStyle, CapsHeight capsHeight) const -{ - mTrace.PushCall("GetFontLineHeightFromCapsHeight", ""); - // LineHeight will be bigger than CapsHeight, so return capsHeight + 1 - return PixelSize(capsHeight + 1); -} - -/** - * @copydoc PlatformAbstraction::GetGlyphData() - */ - -Integration::GlyphSet* TestPlatformAbstraction::GetGlyphData ( const Integration::TextResourceType& textRequest, - const std::string& fontFamily, - bool getBitmap) const -{ - if( getBitmap ) - { - mTrace.PushCall("GetGlyphData", "getBitmap:true"); - } - else - { - mTrace.PushCall("GetGlyphData", "getBitmap:false"); - } - - // It creates fake metrics for the received characters. - - Integration::GlyphSet* set = new Dali::Integration::GlyphSet(); - Integration::BitmapPtr bitmapData; - - std::set characters; - - for( Integration::TextResourceType::CharacterList::const_iterator it = textRequest.mCharacterList.begin(), endIt = textRequest.mCharacterList.end(); it != endIt; ++it ) - { - if( characters.find( it->character ) == characters.end() ) - { - characters.insert( it->character ); - Integration::GlyphMetrics character = {it->character, Integration::GlyphMetrics::LOW_QUALITY, 10.0f, 10.0f, 9.0f, 1.0f, 10.0f, it->xPosition, it->yPosition }; - - if( getBitmap ) - { - bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD); - bitmapData->GetPackedPixelsProfile()->ReserveBuffer(Pixel::A8, 64, 64); - PixelBuffer* pixelBuffer = bitmapData->GetBuffer(); - memset( pixelBuffer, it->character, 64*64 ); - } - - set->AddCharacter(bitmapData, character); - } - } - - set->mLineHeight = 10.0f; - set->mAscender = 9.0f; - set->mUnitsPerEM = 2048.0f/64.0f; - set->SetAtlasResourceId( textRequest.mTextureAtlasId ); - set->mFontHash = textRequest.mFontHash; - - return set; -} - -/** - * @copydoc PlatformAbstraction::GetCachedGlyphData() - */ - -Integration::GlyphSet* TestPlatformAbstraction::GetCachedGlyphData( const Integration::TextResourceType& textRequest, - const std::string& fontFamily ) const -{ - mTrace.PushCall("GetCachedGlyphData", ""); - - // It creates fake metrics and bitmap for received numeric characters '0' through '9'. - Integration::GlyphSet* set = new Dali::Integration::GlyphSet(); - Integration::BitmapPtr bitmapData; - - std::set characters; - - for( Integration::TextResourceType::CharacterList::const_iterator it = textRequest.mCharacterList.begin(), endIt = textRequest.mCharacterList.end(); it != endIt; ++it ) - { - if( it->character >= '0' && it->character <= '9' && characters.find( it->character ) == characters.end() ) - { - characters.insert( it->character ); - Integration::GlyphMetrics character = {it->character, Integration::GlyphMetrics::HIGH_QUALITY, 10.0f, 10.0f, 9.0f, 1.0f, 10.0f, it->xPosition, it->yPosition }; - - bitmapData = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD); - bitmapData->GetPackedPixelsProfile()->ReserveBuffer(Pixel::A8, 64, 64); - PixelBuffer* pixelBuffer = bitmapData->GetBuffer(); - memset( pixelBuffer, it->character, 64*64 ); - set->AddCharacter(bitmapData, character); - } - } - - set->mLineHeight = 10.0f; - set->mAscender = 9.0f; - set->mUnitsPerEM = 2048.0f/64.0f; - set->SetAtlasResourceId( textRequest.mTextureAtlasId ); - set->mFontHash = textRequest.mFontHash; - - return set; -} - - -/** - * @copydoc PlatformAbstraction::GetGlobalMetrics() - */ -void TestPlatformAbstraction::GetGlobalMetrics( const std::string& fontFamily, - const std::string& fontStyle, - Integration::GlobalMetrics& globalMetrics ) const +int TestPlatformAbstraction::GetDefaultFontSize() const { - globalMetrics.lineHeight = 10.0f; - globalMetrics.ascender = 9.0f; - globalMetrics.unitsPerEM = 2048.0f/64.0f; - globalMetrics.underlineThickness = 2.f; - globalMetrics.underlinePosition = 1.f; -} - -/** - * @copydoc PlatformAbstraction::GetFontPath() - */ -std::string TestPlatformAbstraction::GetFontPath(const std::string& family, bool bold, bool italic) const -{ - mTrace.PushCall("GetFontPath", ""); - return mGetFontPathResult; - - // Do nothing with arguments + // TODO + return int(); } /** @@ -320,42 +185,6 @@ void TestPlatformAbstraction::SetDpi (unsigned int dpiHorizontal, unsigned int d } /** - * @copydoc PlatformAbstraction::GetFontFamilyForChars() - */ -const std::string& TestPlatformAbstraction::GetFontFamilyForChars(const Integration::TextArray& charsRequested) const -{ - mTrace.PushCall("GetFontFamilyForChars", ""); - return mGetDefaultFontFamilyResult; -} - -/** - * @copydoc PlatformAbstraction::AllGlyphsSupported() - */ -bool TestPlatformAbstraction::AllGlyphsSupported(const std::string& name, const std::string& fontStyle, const Integration::TextArray& text) const -{ - mTrace.PushCall("AllGlyphsSupported", ""); - return true; -} - -/** - * @copydoc PlatformAbstraction::ValidateFontFamilyName() - */ -bool TestPlatformAbstraction::ValidateFontFamilyName(const std::string& fontFamily, const std::string& fontStyle, bool& isDefaultSystemFont, std::string& closestMatch, std::string& closestStyleMatch) const -{ - mTrace.PushCall("ValidateFontFamilyName", ""); - return true; -} - -/** - * @copydoc PlatformAbstraction::GetFontList() - */ -void TestPlatformAbstraction::GetFontList( PlatformAbstraction::FontListMode mode, std::vector& fonstList ) const -{ - mFontListMode = mode; - mTrace.PushCall("ValidateGetFontList", ""); -} - -/** * @copydoc PlatformAbstraction::LoadFile() */ bool TestPlatformAbstraction::LoadFile( const std::string& filename, std::vector< unsigned char >& buffer ) const @@ -397,102 +226,21 @@ void TestPlatformAbstraction::JoinLoaderThreads() mTrace.PushCall("JoinLoaderThreads", ""); } -void TestPlatformAbstraction::UpdateDefaultsFromDevice() -{ - mTrace.PushCall("UpdateDefaultsFromDevice", ""); - mGetDefaultFontFamilyResult+=1.0f; -} - Integration::DynamicsFactory* TestPlatformAbstraction::GetDynamicsFactory() { mTrace.PushCall("GetDynamicsFactory", ""); return NULL; } -bool TestPlatformAbstraction::ReadGlobalMetricsFromCache( const std::string& fontFamily, - const std::string& fontStyle, - Integration::GlobalMetrics& globalMetrics ) -{ - mTrace.PushCall("ReadGlobalMetricsFromCacheFile", ""); - globalMetrics = mReadGlobalMetrics; // Want to copy contents... - return mReadGlobalMetricsResult; // Default false (will be set to true on subsequent write) -} - -void TestPlatformAbstraction::WriteGlobalMetricsToCache( const std::string& fontFamily, - const std::string& fontStyle, - const Integration::GlobalMetrics& globalMetrics ) -{ - // Copy so next read uses written values. TODO: Could add method - // to turn this behaviour off for more extensive testing. - mReadGlobalMetrics = globalMetrics; - mReadGlobalMetricsResult = true; - - mTrace.PushCall("WriteGlobalMetricsToCacheFile", ""); -} - -bool TestPlatformAbstraction::ReadMetricsFromCache( const std::string& fontFamily, - const std::string& fontStyle, - std::vector& glyphMetricsContainer ) -{ - mTrace.PushCall("ReadMetricsFromCacheFile", ""); - glyphMetricsContainer = mReadMetrics; - return mReadMetricsResult; // Default false (will be set to true on subsequent write) -} - -void TestPlatformAbstraction::WriteMetricsToCache( const std::string& fontFamily, - const std::string& fontStyle, - const Integration::GlyphSet& glyphSet ) -{ - // Copy so next read uses written values. TODO: Could add method - // to turn this behaviour off for more extensive testing. - const Integration::GlyphSet::CharacterList& charList = glyphSet.GetCharacterList(); - mReadMetrics.clear(); - for(std::size_t i=0, end=charList.size(); i& fileNames ) -{ - fileNames.push_back( std::string( "u1f004.png" ) ); - fileNames.push_back( std::string( "u1f0cf.png" ) ); - fileNames.push_back( std::string( "u1f170.png" ) ); - fileNames.push_back( std::string( "u1f601.png" ) ); -} - - -Integration::BitmapPtr TestPlatformAbstraction::GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character ) const -{ - Integration::BitmapPtr image = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::DISCARD ); - image->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 1, 1 ); - - mTrace.PushCall("GetGlyphImage", ""); - - return image; -} - - /** Call this every test */ void TestPlatformAbstraction::Initialize() { mTrace.Reset(); mTrace.Enable(true); memset(&mResources, 0, sizeof(Resources)); - memset(&mReadGlobalMetrics, 0, sizeof(Integration::GlobalMetrics)); mSeconds=0; mMicroSeconds=0; mIsLoadingResult=false; - mGetDefaultFontFamilyResult = "HelveticaNeue"; - mGetDefaultFontSizeResult=12.0f; - mGetFontPathResult="helvetica-12"; - mReadMetricsResult=false; - mReadGlobalMetricsResult=false; if(mRequest) { @@ -517,24 +265,9 @@ bool TestPlatformAbstraction::WasCalled(TestFuncEnum func) case CancelLoadFunc: return mTrace.FindMethod("CancelLoad"); case GetResourcesFunc: return mTrace.FindMethod("GetResources"); case IsLoadingFunc: return mTrace.FindMethod("IsLoading"); - case GetDefaultFontFamilyFunc: return mTrace.FindMethod("GetDefaultFontFamily"); - case GetDefaultFontSizeFunc: return mTrace.FindMethod("GetDefaultFontSize"); - case GetFontLineHeightFromCapsHeightFunc: return mTrace.FindMethod("GetFontLineHeightFromCapsHeight"); - case GetGlyphDataFunc: return mTrace.FindMethod("GetGlyphData"); - case GetCachedGlyphDataFunc: return mTrace.FindMethod("GetCachedGlyphData"); - case GetFontPathFunc: return mTrace.FindMethod("GetFontPath"); case SetDpiFunc: return mTrace.FindMethod("SetDpi"); case JoinLoaderThreadsFunc: return mTrace.FindMethod("JoinLoaderThreads"); - case GetFontFamilyForCharsFunc: return mTrace.FindMethod("GetFontFamilyForChars"); - case AllGlyphsSupportedFunc: return mTrace.FindMethod("AllGlyphsSupported"); - case ValidateFontFamilyNameFunc: return mTrace.FindMethod("ValidateFontFamilyName"); - case UpdateDefaultsFromDeviceFunc: return mTrace.FindMethod("UpdateDefaultsFromDevice"); case GetDynamicsFactoryFunc: return mTrace.FindMethod("GetDynamicsFactory"); - case ValidateGetFontListFunc: return mTrace.FindMethod("ValidateGetFontList"); - case ReadGlobalMetricsFromCacheFileFunc: return mTrace.FindMethod("ReadGlobalMetricsFromCacheFile"); - case WriteGlobalMetricsToCacheFileFunc: return mTrace.FindMethod("WriteGlobalMetricsToCacheFile"); - case ReadMetricsFromCacheFileFunc: return mTrace.FindMethod("ReadMetricsFromCacheFile"); - case WriteMetricsToCacheFileFunc: return mTrace.FindMethod("WriteMetricsToCacheFile"); } return false; } @@ -559,21 +292,6 @@ void TestPlatformAbstraction::SetIsLoadingResult(bool result) mIsLoadingResult = result; } -void TestPlatformAbstraction::SetGetDefaultFontFamilyResult(std::string result) -{ - mGetDefaultFontFamilyResult = result; -} - -void TestPlatformAbstraction::SetGetDefaultFontSizeResult(float result) -{ - mGetDefaultFontSizeResult = result; -} - -void TestPlatformAbstraction::SetGetFontPathResult(std::string& result) -{ - mGetFontPathResult = result; -} - void TestPlatformAbstraction::ClearReadyResources() { memset(&mResources, 0, sizeof(Resources)); @@ -643,21 +361,4 @@ void TestPlatformAbstraction::SetSaveFileResult( bool result ) mSaveFileResult = result; } -Integration::PlatformAbstraction::FontListMode TestPlatformAbstraction::GetLastFontListMode( ) -{ - return mFontListMode; -} - -void TestPlatformAbstraction::SetReadGlobalMetricsResult( bool success, Integration::GlobalMetrics& globalMetrics ) -{ - mReadGlobalMetricsResult = success; - mReadGlobalMetrics = globalMetrics; -} - -void TestPlatformAbstraction::SetReadMetricsResult( bool success, std::vector& glyphMetricsContainer ) -{ - mReadMetricsResult = success; - mReadMetrics = glyphMetricsContainer; // copy -} - } // namespace Dali diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h index 41b06cd..a4ec8d3 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h @@ -26,7 +26,6 @@ #include #include -#include #include "test-trace-call-stack.h" @@ -137,71 +136,19 @@ public: virtual bool IsLoading(); /** - * @copydoc PlatformAbstraction::GetDefaultFontFamily() + * @copydoc PlatformAbstraction::GetDefaultFontDescription() */ - virtual const std::string& GetDefaultFontFamily() const; + virtual void GetDefaultFontDescription( std::string& family, std::string& style ) const; /** * @copydoc PlatformAbstraction::GetDefaultFontSize() */ - virtual float GetDefaultFontSize() const; - - /** - * @copydoc PlatformAbstraction::GetFontLineHeightFromCapsHeight() - */ - virtual Dali::PixelSize GetFontLineHeightFromCapsHeight(const std::string& fontFamily, const std::string& fontStyle, CapsHeight capsHeight) const; - - /** - * @copydoc PlatformAbstraction::GetGlyphData() - */ - virtual Integration::GlyphSet* GetGlyphData ( const Integration::TextResourceType& textRequest, - const std::string& fontFamily, - bool getBitmap) const; - - /** - * @copydoc PlatformAbstraction::GetCachedGlyphData() - */ - virtual Integration::GlyphSet* GetCachedGlyphData( const Integration::TextResourceType& textRequest, - const std::string& fontFamily ) const; - - - /** - * @copydoc PlatformAbstraction::GetGlobalMetrics() - */ - virtual void GetGlobalMetrics( const std::string& fontFamily, - const std::string& fontStyle, - Integration::GlobalMetrics& globalMetrics ) const; - - /** - * @copydoc PlatformAbstraction::GetFontPath() - */ - virtual std::string GetFontPath(const std::string& family, bool bold, bool italic) const; + virtual int GetDefaultFontSize() const; /** * @copydoc PlatformAbstraction::SetDpi() */ virtual void SetDpi (unsigned int dpiHorizontal, unsigned int dpiVertical); - - /** - * @copydoc PlatformAbstraction::GetFontFamilyForChars() - */ - virtual const std::string& GetFontFamilyForChars(const Integration::TextArray& charsRequested) const; - - /** - * @copydoc PlatformAbstraction::AllGlyphsSupported() - */ - virtual bool AllGlyphsSupported(const std::string& name, const std::string& fontStyle, const Integration::TextArray& text) const; - - /** - * @copydoc PlatformAbstraction::ValidateFontFamilyName() - */ - virtual bool ValidateFontFamilyName(const std::string& fontFamily, const std::string& fontStyle, bool& isDefaultSystemFont, std::string& closestMatch, std::string& closestStyleMatch) const; - - /** - * @copydoc PlatformAbstraction::GetFontList() - */ - virtual void GetFontList( PlatformAbstraction::FontListMode mode, std::vector& fontList ) const; - /** * @copydoc PlatformAbstraction::LoadFile() */ @@ -219,31 +166,8 @@ public: virtual void JoinLoaderThreads(); - virtual void UpdateDefaultsFromDevice(); - virtual Integration::DynamicsFactory* GetDynamicsFactory(); - virtual bool ReadGlobalMetricsFromCache( const std::string& fontFamily, - const std::string& fontStyle, - Integration::GlobalMetrics& globalMetrics ); - - virtual void WriteGlobalMetricsToCache( const std::string& fontFamily, - const std::string& fontStyle, - const Integration::GlobalMetrics& globalMetrics ); - - virtual bool ReadMetricsFromCache( const std::string& fontFamily, - const std::string& fontStyle, - std::vector& glyphMetricsContainer ); - virtual void WriteMetricsToCache( const std::string& fontFamily, - const std::string& fontStyle, - const Integration::GlyphSet& glyphSet ); - - - virtual void GetFileNamesFromDirectory( const std::string& directoryName, - std::vector& fileNames ); - - virtual Integration::BitmapPtr GetGlyphImage( const std::string& fontFamily, const std::string& fontStyle, float fontSize, uint32_t character ) const; - public: // TEST FUNCTIONS // Enumeration of Platform Abstraction methods @@ -260,24 +184,9 @@ public: // TEST FUNCTIONS CancelLoadFunc, GetResourcesFunc, IsLoadingFunc, - GetDefaultFontFamilyFunc, - GetDefaultFontSizeFunc, - GetFontLineHeightFromCapsHeightFunc, - GetGlyphDataFunc, - GetCachedGlyphDataFunc, SetDpiFunc, - GetFontPathFunc, JoinLoaderThreadsFunc, - GetFontFamilyForCharsFunc, - AllGlyphsSupportedFunc, - ValidateFontFamilyNameFunc, - UpdateDefaultsFromDeviceFunc, GetDynamicsFactoryFunc, - ValidateGetFontListFunc, - ReadGlobalMetricsFromCacheFileFunc, - WriteGlobalMetricsToCacheFileFunc, - ReadMetricsFromCacheFileFunc, - WriteMetricsToCacheFileFunc, } TestFuncEnum; /** Call this every test */ @@ -326,33 +235,18 @@ public: // TEST FUNCTIONS void SetSaveFileResult( bool result ); - PlatformAbstraction::FontListMode GetLastFontListMode( ); - - void SetReadGlobalMetricsResult( bool success, Integration::GlobalMetrics& globalMetrics ); - - void SetReadMetricsResult( bool success, std::vector& glyphMetricsContainer ); - - private: mutable TraceCallStack mTrace; size_t mSeconds; size_t mMicroSeconds; bool mIsLoadingResult; - std::string mGetDefaultFontFamilyResult; - float mGetDefaultFontSizeResult; - std::string mGetFontPathResult; Resources mResources; Integration::ResourceRequest* mRequest; Vector2 mSize; Vector2 mClosestSize; - bool mReadGlobalMetricsResult; - bool mReadMetricsResult; - Integration::GlobalMetrics mReadGlobalMetrics; - std::vector mReadMetrics; LoadFileResult mLoadFileResult; bool mSaveFileResult; - mutable FontListMode mFontListMode; }; } // Dali diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Alignment.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Alignment.cpp index 4dcef68..0f62a2a 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Alignment.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Alignment.cpp @@ -935,7 +935,7 @@ int UtcDaliAlignmentOnSizeSet(void) application.SendNotification(); Vector2 size( 100.0f, 200.0f ); - alignment.SetPreferredSize(size); + alignment.SetSize(size); application.Render(); application.SendNotification(); @@ -1010,7 +1010,7 @@ int UtcDaliAlignmentOnSizeAnimation(void) Stage::GetCurrent().Add(alignment); Animation animation = Animation::New(100.0f); - animation.Resize(alignment, Vector3(100.0f, 150.0f, 200.0f)); + animation.AnimateTo( Property( alignment, Actor::Property::SIZE ), Vector3( 100.0f, 150.0f, 200.0f ) ); animation.Play(); application.Render(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp index d403477..cc03bb1 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp @@ -26,131 +26,6 @@ using namespace Toolkit; namespace { -// -// Note: To avoid escaping double quotes single quotes are used and then replaced -// before parsing. JSON uses double quotes -// - - std::string JSON_TEXT_ACTOR("\ -{ \ - 'templates': \ - { \ - 'basic-text': \ - { \ - 'type':'TextActor', \ - 'text':'Template Hello', \ - 'size': [150,170,1], \ - 'position':[-10,10,0] \ - } \ - }, \ - 'styles': \ - { \ - 'basic-text': \ - { \ - 'text':'Hello', \ - 'font':'', \ - 'parent-origin':[0.0,0.0,0], \ - 'anchor-point' :[0.5,0.5,0], \ - 'size': [150,170,1], \ - 'position':[-10,10,0] \ - } \ - }, \ - 'animations': \ - { \ - 'rotate': \ - { \ - 'duration': 10, \ - 'properties': \ - [ \ - { \ - 'actor':'text', \ - 'property':'orientation', \ - 'value':[0, 3, 0, 0], \ - 'alpha-function': 'EASE_IN_OUT', \ - 'time-period': {'delay': 0, 'duration': 3 } \ - } \ - ] \ - } \ - }, \ - 'stage': \ - [ \ - { \ - 'name':'text', \ - 'type':'basic-text', \ - 'text':'Hello' \ - }, \ - { \ - 'name':'text2', \ - 'type':'basic-text', \ - 'text':'Hello', \ - 'signals': \ - [ \ - { 'name': 'on-stage', 'action':'set', 'actor':'text2', 'property':'text', 'value':'Jaylo' } \ - ] \ - } \ - ], \ - 'other': \ - [ \ - { \ - 'name':'other-text', \ - 'type':'basic-text', \ - 'text':'Hello' \ - } \ - ] \ -} \ -"); - - - std::string JSON_CORE_ACTOR_TREE("\ -{ \ - 'templates': \ - { \ - 'my-camera': { \ - 'type':'CameraActor', \ - 'camera-type':'FreeLook', \ - 'field-of-view': 0.125, \ - 'aspect-ratio':5.0, \ - 'near-plane-distance': 100, \ - 'far-plane-distance': 200 \ - }, \ - 'basic-text': { \ - 'type':'TextActor', \ - 'text':'Hello', \ - 'font':'Freesans', \ - 'smooth-edge':0.2, \ - 'position': [-10.0, 10.0, -1000.0], \ - 'size': [300.0, 250.0, 0.0] \ - } \ - }, \ - 'styles': \ - { \ - 'theme2-text': { \ - 'type':'TextActor', \ - 'text':'Hello', \ - 'font':'Freesans', \ - 'smooth-edge':0.8 \ - } \ - }, \ - 'stage': \ - [ \ - {'name':'txt1', \ - 'type':'TextActor', \ - 'text':'Hello World', \ - 'font':'freesans', \ - 'parent-origin':'CENTER', \ - 'actors': \ - [ \ - { 'type':'basic-text', 'text':'Hello', 'position-y':50 }, \ - { 'type':'basic-text', 'text':'Hello', 'position-y':100 }, \ - { 'type':'basic-text', 'text':'Hello', 'position-y':150 }, \ - { 'type':'basic-text', 'text':'Hello', 'position-y':200 }, \ - { 'type':'basic-text', 'text':'Hello', 'position-y':250 } \ - ] \ - } \ - ] \ -} \ -"); - std::string ReplaceQuotes(const std::string &in_s) { @@ -189,263 +64,6 @@ void builder_cleanup(void) test_return_value = TET_PASS; } -int UtcDaliBuilderTextActorCreate(void) -{ - ToolkitTestApplication application; - Stage stage = Stage::GetCurrent(); - - tet_infoline(" UtcDaliBuilderTextActorCreate"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - TextActor actor( TextActor::DownCast( builder.Create("basic-text") ) ); - - DALI_TEST_CHECK( actor ); - - stage.GetRootLayer().Add( actor ); - - application.SendNotification(); - application.Render(); - - Vector3 v; - - v = actor.GetCurrentPosition(); - DALI_TEST_CHECK(v.x == -10.0); - DALI_TEST_CHECK(v.y == 10.0); - DALI_TEST_CHECK(v.z == 0.0); - - v = actor.GetCurrentSize(); - DALI_TEST_CHECK(v.x == 150.0); - DALI_TEST_CHECK(v.y == 170.0); - DALI_TEST_CHECK(v.z == 1.0); - - DALI_TEST_CHECK(actor.GetText() == "Template Hello"); - - actor = TextActor::DownCast( builder.Create("*(&^") ); - DALI_TEST_CHECK(!actor); - - END_TEST; -} - -int UtcDaliBuilderTextActorCreateAnimation(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderTextActorCreateAnimation"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - builder.AddActors( Stage::GetCurrent().GetRootLayer() ); - - Animation anim = builder.CreateAnimation("rotate"); - DALI_TEST_CHECK( anim ); - - DALI_TEST_CHECK( 10.0f == anim.GetDuration() ); - - END_TEST; -} - -int UtcDaliBuilderTextActorApplyFromStyle(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderTextActorApplyFromStyle"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - TextActor actor = TextActor::New("a"); - - builder.ApplyStyle("basic-text", actor); - - DALI_TEST_CHECK( actor ); - - Stage::GetCurrent().GetRootLayer().Add( actor ); - - application.SendNotification(); - application.Render(); - - Vector3 v; - - v = actor.GetCurrentPosition(); - DALI_TEST_CHECK(v.x == -10.0); - DALI_TEST_CHECK(v.y == 10.0); - DALI_TEST_CHECK(v.z == 0.0); - - v = actor.GetCurrentSize(); - DALI_TEST_CHECK(v.x == 150.0); - DALI_TEST_CHECK(v.y == 170.0); - DALI_TEST_CHECK(v.z == 1.0); - - DALI_TEST_CHECK(actor.GetText() == "Hello"); - - END_TEST; -} - -int UtcDaliBuilderAddActors(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderAddActors"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - builder.AddActors( Stage::GetCurrent().GetRootLayer() ); - - application.SendNotification(); - application.Render(); - - TextActor actor = TextActor::DownCast( Stage::GetCurrent().GetRootLayer().FindChildByName("text") ); - - DALI_TEST_CHECK( actor ); - DALI_TEST_CHECK(actor.GetText() == "Hello"); - - END_TEST; -} - -int UtcDaliBuilderAddActorsOther(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderAddActorsOther"); - - Actor rootActor = Stage::GetCurrent().GetRootLayer(); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - builder.AddActors( "other", rootActor ); - - application.SendNotification(); - application.Render(); - - TextActor actor = TextActor::DownCast( Stage::GetCurrent().GetRootLayer().FindChildByName("other-text") ); - - DALI_TEST_CHECK( actor ); - DALI_TEST_CHECK(actor.GetText() == "Hello"); - - END_TEST; -} - - -int UtcDaliBuilderStyles(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderStyles"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_CORE_ACTOR_TREE)); - - BaseHandle handle = builder.Create("my-camera"); - CameraActor camera = CameraActor::DownCast(handle); - - DALI_TEST_CHECK(camera); - - Property::Value v; - - v = camera.GetProperty( camera.GetPropertyIndex("field-of-view") ); - DALI_TEST_CHECK( 0.125f == v.Get() ); - - v = camera.GetProperty( camera.GetPropertyIndex("aspect-ratio") ); - DALI_TEST_CHECK( 5.0f == v.Get() ); - - handle = builder.Create("basic-text"); - TextActor textActor = TextActor::DownCast(handle); - - v = textActor.GetProperty( textActor.GetPropertyIndex("smooth-edge") ); - - DALI_TEST_CHECK( 0.2f == v.Get() ); - - // test ApplyStyle another - builder.ApplyStyle("theme2-text", textActor); - - v = textActor.GetProperty( textActor.GetPropertyIndex("smooth-edge") ); - DALI_TEST_CHECK( 0.8f == v.Get() ); - - END_TEST; -} - -int UtcDaliBuilderSetProperty(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderSetProperty"); - - Builder builder = Builder::New(); - - builder.LoadFromString(ReplaceQuotes(JSON_TEXT_ACTOR)); - - builder.AddActors( Stage::GetCurrent().GetRootLayer() ); - - application.SendNotification(); - application.Render(); - - TextActor actor = TextActor::DownCast( Stage::GetCurrent().GetRootLayer().FindChildByName("text2") ); - - DALI_TEST_CHECK( actor ); - DALI_TEST_CHECK( actor.GetText() == "Jaylo" ); - - END_TEST; -} - -int UtcDaliBuilderCreateFromJson(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderCreateFromJson"); - - Builder builder = Builder::New(); - - TextActor actor = TextActor::DownCast( builder.CreateFromJson("foobar") ); - - DALI_TEST_CHECK( !actor ); - - actor = TextActor::DownCast( - builder.CreateFromJson( - ReplaceQuotes("{'type':'TextActor','text':'Hi'}") ) ); - - DALI_TEST_CHECK( actor ); - - DALI_TEST_CHECK( actor.GetText() == "Hi" ); - - END_TEST; -} - -int UtcDaliBuilderApplyFromJson(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliBuilderApplyFromJson"); - - Builder builder = Builder::New(); - - TextActor actor = TextActor::DownCast( - builder.CreateFromJson( - ReplaceQuotes("{'type':'TextActor','text':'Hi'}") ) ); - - DALI_TEST_CHECK( actor ); - - DALI_TEST_CHECK( actor.GetText() == "Hi" ); - - DALI_TEST_CHECK( !builder.ApplyFromJson(actor, ReplaceQuotes("foobar") ) ); - - builder.ApplyFromJson(actor, ReplaceQuotes("{'text':'low'}") ); - - DALI_TEST_CHECK( actor.GetText() == "low" ); - - END_TEST; -} - int UtcDaliBuilderQuitSignal(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Button.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Button.cpp index 3a6900e..12e85b6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Button.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Button.cpp @@ -144,6 +144,7 @@ int UtcDaliButtonSize(void) // First an image is set, then SetSize is called. pushButton = PushButton::New(); + Stage::GetCurrent().Add( pushButton ); pushButton.SetBackgroundImage( image01 ); pushButton.SetSize( 10.f, 10.f ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-CheckBoxButton.cpp b/automated-tests/src/dali-toolkit/utc-Dali-CheckBoxButton.cpp index 32bb9de..d6dc8d4 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-CheckBoxButton.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-CheckBoxButton.cpp @@ -111,6 +111,7 @@ int UtcDaliCheckBoxButtonSetImages(void) Image image02 = CreateSolidColorImage( Color::RED, 30, 30 ); ImageActor imageActor02 = CreateSolidColorActor( Color::RED ); imageActor02.SetSize( 40, 40 ); + imageActor02.SetName( "imageActor02" ); Image image03 = CreateSolidColorImage( Color::RED, 50, 50 ); ImageActor imageActor03 = CreateSolidColorActor( Color::RED ); @@ -122,6 +123,8 @@ int UtcDaliCheckBoxButtonSetImages(void) Vector3 size; CheckBoxButton checkBoxButton = CheckBoxButton::New(); + checkBoxButton.SetName( "UtcDaliCheckBoxButtonSetImages" ); + Stage::GetCurrent().Add( checkBoxButton ); application.SendNotification(); application.Render(); @@ -133,79 +136,12 @@ int UtcDaliCheckBoxButtonSetImages(void) application.SendNotification(); application.Render(); - size = checkBoxButton.GetBackgroundImage().GetCurrentSize(); + size = checkBoxButton.GetCurrentSize(); DALI_TEST_EQUALS( size.width, 10.f, TEST_LOCATION ); DALI_TEST_EQUALS( size.height, 10.f, TEST_LOCATION ); checkBoxButton.SetBackgroundImage( imageActor01 ); - application.SendNotification(); - application.Render(); - - size = checkBoxButton.GetBackgroundImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 20.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 20.f, TEST_LOCATION ); - - checkBoxButton.SetSelectedImage( image02 ); - - application.SendNotification(); - application.Render(); - - size = checkBoxButton.GetSelectedImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 30.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 30.f, TEST_LOCATION ); - - checkBoxButton.SetSelectedImage( imageActor02 ); - - application.SendNotification(); - application.Render(); - - size = checkBoxButton.GetSelectedImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 40.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 40.f, TEST_LOCATION ); - - checkBoxButton.SetDisabledBackgroundImage( image03 ); - - application.SendNotification(); - application.Render(); - - size = checkBoxButton.GetDisabledBackgroundImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 50.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 50.f, TEST_LOCATION ); - - checkBoxButton.SetDisabledBackgroundImage( imageActor03 ); - - application.SendNotification(); - application.Render(); - - size = checkBoxButton.GetDisabledBackgroundImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 60.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 60.f, TEST_LOCATION ); - - checkBoxButton.SetDisabledSelectedImage( image04 ); - - application.SendNotification(); - application.Render(); - - size = checkBoxButton.GetDisabledSelectedImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 70.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 70.f, TEST_LOCATION ); - - checkBoxButton.SetDisabledSelectedImage( imageActor04 ); - - application.SendNotification(); - application.Render(); - - size = checkBoxButton.GetDisabledSelectedImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 80.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 80.f, TEST_LOCATION ); END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Cluster.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Cluster.cpp index 6a35824..b83ff8c 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Cluster.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Cluster.cpp @@ -169,7 +169,7 @@ int UtcDaliClusterExpandAndCollapseChild(void) DALI_TEST_CHECK( cluster.GetExpandedCount() == 0 ); // Transform and restore the child - cluster.TransformChild(1, Vector3(10.0f, 10.0f, 1.0f), Vector3(1.0f, 1.0f, 1.0f), Quaternion(0.0f, Vector3::YAXIS), AlphaFunctions::EaseOut, 0.5f); + cluster.TransformChild(1, Vector3(10.0f, 10.0f, 1.0f), Vector3(1.0f, 1.0f, 1.0f), Quaternion( Radian(0.0f), Vector3::YAXIS), AlphaFunctions::EaseOut, 0.5f); cluster.RestoreChild(1, AlphaFunctions::EaseOut, 0.25f, true); END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp index aa9e46c..beeb619 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Control.cpp @@ -328,6 +328,12 @@ int UtcDaliControlTestParameters(void) DummyControl test = DummyControl::New(); test.SetSize( 0.7f, 0.7f, 0.7f ); + + Stage::GetCurrent().Add( test ); + + application.SendNotification(); + application.Render(); + float width = 640.0f; float height = test.GetHeightForWidth( width ); DALI_TEST_CHECK( test.GetWidthForHeight( height ) == width ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ControlImpl.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ControlImpl.cpp index c0cf98c..f7926a5 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ControlImpl.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ControlImpl.cpp @@ -219,7 +219,7 @@ int UtcDaliControlImplOnGestureMethods(void) { DummyControl dummy = DummyControl::New(true); dummy.SetRelayoutEnabled( true ); - dummy.SetPreferredSize( Vector2(100.0f, 100.0f ) ); + dummy.SetSize( Vector2(100.0f, 100.0f ) ); dummy.SetAnchorPoint(AnchorPoint::TOP_LEFT); Stage::GetCurrent().Add(dummy); @@ -280,7 +280,7 @@ int UtcDaliControlImplOnGestureMethods(void) { DummyControl dummy = DummyControl::New(); dummy.SetRelayoutEnabled( true ); - dummy.SetPreferredSize( Vector2( 100.0f, 100.0f ) ); + dummy.SetSize( Vector2( 100.0f, 100.0f ) ); dummy.SetAnchorPoint(AnchorPoint::TOP_LEFT); Stage::GetCurrent().Add(dummy); @@ -454,7 +454,7 @@ int UtcDaliControlImplSizeSet(void) DALI_TEST_EQUALS( dummyImpl.sizeSetCalled, true, TEST_LOCATION ); // Called from size negotiation Vector2 size(100.0f, 200.0f); - dummy.SetPreferredSize(size); + dummy.SetSize(size); application.Render(); application.SendNotification(); @@ -479,7 +479,7 @@ int UtcDaliControlImplSizeSet(void) application.Render(); application.SendNotification(); - dummy.SetPreferredSize(size); + dummy.SetSize(size); application.Render(); application.SendNotification(); @@ -505,7 +505,7 @@ int UtcDaliControlImplSizeAnimation(void) DALI_TEST_EQUALS( dummyImpl.sizeAnimationCalled, false, TEST_LOCATION ); Animation animation = Animation::New(1.0f); - animation.Resize(dummy, Vector3(100.0f, 150.0f, 200.0f)); + animation.AnimateTo( Property( dummy, Actor::Property::SIZE ), Vector3( 100.0f, 150.0f, 200.0f ) ); animation.Play(); application.Render(); @@ -525,7 +525,7 @@ int UtcDaliControlImplSizeAnimation(void) Stage::GetCurrent().Add(dummy); Animation animation = Animation::New(1.0f); - animation.Resize(dummy, Vector3(100.0f, 150.0f, 200.0f)); + animation.AnimateTo( Property( dummy, Actor::Property::SIZE ), Vector3( 100.0f, 150.0f, 200.0f ) ); animation.Play(); application.Render(); @@ -549,7 +549,7 @@ int UtcDaliControlImplTouchEvent(void) dummy.SetRelayoutEnabled( true ); DummyControlImplOverride& dummyImpl = static_cast(dummy.GetImplementation()); - dummy.SetPreferredSize( Vector2( 100.0f, 100.0f ) ); + dummy.SetSize( Vector2( 100.0f, 100.0f ) ); dummy.SetAnchorPoint(AnchorPoint::TOP_LEFT); Stage::GetCurrent().Add(dummy); @@ -573,7 +573,7 @@ int UtcDaliControlImplTouchEvent(void) DummyControl dummy = DummyControl::New(); dummy.SetRelayoutEnabled( true ); - dummy.SetPreferredSize( Vector2( 100.0f, 100.0f ) ); + dummy.SetSize( Vector2( 100.0f, 100.0f ) ); dummy.SetAnchorPoint(AnchorPoint::TOP_LEFT); Stage::GetCurrent().Add(dummy); @@ -776,7 +776,7 @@ int UtcDaliControlImplMouseWheelEvent(void) dummy.SetRelayoutEnabled( true ); DummyControlImplOverride& dummyImpl = static_cast(dummy.GetImplementation()); - dummy.SetPreferredSize( Vector2( 100.0f, 100.0f ) ); + dummy.SetSize( Vector2( 100.0f, 100.0f ) ); dummy.SetAnchorPoint(AnchorPoint::TOP_LEFT); Stage::GetCurrent().Add(dummy); @@ -803,7 +803,7 @@ int UtcDaliControlImplMouseWheelEvent(void) DummyControl dummy = DummyControl::New(); dummy.SetRelayoutEnabled( true ); - dummy.SetPreferredSize( Vector2( 100.0f, 100.0f ) ); + dummy.SetSize( Vector2( 100.0f, 100.0f ) ); dummy.SetAnchorPoint(AnchorPoint::TOP_LEFT); Stage::GetCurrent().Add(dummy); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-CubeTransitionEffect.cpp b/automated-tests/src/dali-toolkit/utc-Dali-CubeTransitionEffect.cpp index 28690e8..055b122 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-CubeTransitionEffect.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-CubeTransitionEffect.cpp @@ -386,28 +386,28 @@ int UtcDaliCubeTransitionWaveEffectStartTransition(void) waveEffect.SetTargetImage( imageActor ); waveEffect.StartTransition(true); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); waveEffect.SetTargetImage( imageActor ); waveEffect.StartTransition(PAN_POSITION1, PAN_DISPLACEMENT1); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -2.f*Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_180, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); waveEffect.SetTargetImage( imageActor ); waveEffect.StartTransition(false); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); waveEffect.SetTargetImage( imageActor ); waveEffect.StartTransition(PAN_POSITION2, PAN_DISPLACEMENT2); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( 0.f, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); END_TEST; @@ -437,8 +437,8 @@ int UtcDaliCubeTransitionCrossEffectStartTransition(void) crossEffect.SetTargetImage( imageActor ); crossEffect.StartTransition(true); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Math::PI_2, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_90, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -446,8 +446,8 @@ int UtcDaliCubeTransitionCrossEffectStartTransition(void) crossEffect.SetTargetImage( imageActor ); crossEffect.StartTransition(PAN_POSITION1, PAN_DISPLACEMENT1); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -2.f*Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( 2.f*Math::PI_2, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_180, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_180, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -455,16 +455,16 @@ int UtcDaliCubeTransitionCrossEffectStartTransition(void) crossEffect.SetTargetImage( imageActor ); crossEffect.StartTransition(false); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Math::PI_2, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_90, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); crossEffect.SetTargetImage( imageActor ); crossEffect.StartTransition(PAN_POSITION2, PAN_DISPLACEMENT2); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( 0.f, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( 0.f, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); END_TEST; @@ -493,16 +493,16 @@ int UtcDaliCubeTransitionFoldEffectStartTransition(void) foldEffect.SetTargetImage( imageActor ); foldEffect.StartTransition(true); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); foldEffect.SetTargetImage( imageActor ); foldEffect.StartTransition(PAN_POSITION1, PAN_DISPLACEMENT1); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -2.f*Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( 2.f*Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_180, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_180, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -510,16 +510,16 @@ int UtcDaliCubeTransitionFoldEffectStartTransition(void) foldEffect.SetTargetImage( imageActor ); foldEffect.StartTransition(false); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(),fullBrightness, FLT_EPISILON, TEST_LOCATION ); foldEffect.SetTargetImage( imageActor ); foldEffect.StartTransition(PAN_POSITION2, PAN_DISPLACEMENT2); Wait( application, TRANSITION_DURATION ); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( 0.f, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( 0.f, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); END_TEST; @@ -749,7 +749,7 @@ int UtcDaliCubeTransitionWaveEffectStopTransition(void) waveEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -759,7 +759,7 @@ int UtcDaliCubeTransitionWaveEffectStopTransition(void) waveEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -2.f*Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_180, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -769,7 +769,7 @@ int UtcDaliCubeTransitionWaveEffectStopTransition(void) waveEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -779,7 +779,7 @@ int UtcDaliCubeTransitionWaveEffectStopTransition(void) waveEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( 0.f, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); END_TEST; @@ -813,8 +813,8 @@ int UtcDaliCubeTransitionCrossEffectStopTransition(void) crossEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Math::PI_2, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_90, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -825,8 +825,8 @@ int UtcDaliCubeTransitionCrossEffectStopTransition(void) crossEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -2.f*Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( 2.f*Math::PI_2, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_180, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_180, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -836,8 +836,8 @@ int UtcDaliCubeTransitionCrossEffectStopTransition(void) crossEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Math::PI_2, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_90, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -847,8 +847,8 @@ int UtcDaliCubeTransitionCrossEffectStopTransition(void) crossEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( 0.f, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( 0.f, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::XAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); END_TEST; @@ -881,8 +881,8 @@ int UtcDaliCubeTransitionFoldEffectStopTransition(void) foldEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -892,8 +892,8 @@ int UtcDaliCubeTransitionFoldEffectStopTransition(void) foldEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -2.f*Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( 2.f*Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_180, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_180, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -903,8 +903,8 @@ int UtcDaliCubeTransitionFoldEffectStopTransition(void) foldEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Math::PI_2, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( -Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_90, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); @@ -914,8 +914,8 @@ int UtcDaliCubeTransitionFoldEffectStopTransition(void) foldEffect.StopTransition(); application.SendNotification(); application.Render(RENDER_FRAME_INTERVAL); - DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( 0.f, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); - DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( 0.f, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube1.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); + DALI_TEST_EQUALS( cube0.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS), FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(0).GetCurrentColor(), fullBrightness, FLT_EPISILON, TEST_LOCATION ); DALI_TEST_EQUALS( cube0.GetChildAt(1).GetCurrentColor(), halfBrightness, FLT_EPISILON, TEST_LOCATION ); END_TEST; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-DepthLayout.cpp b/automated-tests/src/dali-toolkit/utc-Dali-DepthLayout.cpp index 9462c28..90b92f6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-DepthLayout.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-DepthLayout.cpp @@ -164,7 +164,7 @@ int UtcDaliDepthLayoutSetAndGetTiltAngle(void) depthLayout->SetTiltAngle(Degree(25.0f)); // Check whether we get the correct tilt angle - DALI_TEST_EQUALS(float(depthLayout->GetTiltAngle()), 25.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS(depthLayout->GetTiltAngle(), Degree(25.0f), 0.001f, TEST_LOCATION ); END_TEST; } @@ -209,7 +209,7 @@ int UtcDaliDepthLayoutSetAndGetItemTiltAngle(void) depthLayout->SetItemTiltAngle(Degree(5.0f)); // Check whether we get the correct item's tilt angle - DALI_TEST_EQUALS(float(depthLayout->GetItemTiltAngle()), 5.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS(depthLayout->GetItemTiltAngle(), Degree(5.0f), 0.001f, TEST_LOCATION ); END_TEST; } @@ -587,7 +587,7 @@ int UtcDaliDepthLayoutScrollDirection(void) application.Render(); Degree deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == 180.0f); + DALI_TEST_CHECK(deg.degree == 180.0f); navigationLayout->SetOrientation(ControlOrientation::Down); view.ActivateLayout(0, vec, 0.0f); @@ -595,7 +595,7 @@ int UtcDaliDepthLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK((deg == 0.0f)); + DALI_TEST_CHECK((deg.degree == 0.0f)); layout->SetOrientation(ControlOrientation::Left); view.ActivateLayout(0, vec, 0.0f); @@ -603,7 +603,7 @@ int UtcDaliDepthLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == 270.0f); + DALI_TEST_CHECK(deg.degree == 270.0f); navigationLayout->SetOrientation(ControlOrientation::Right); view.ActivateLayout(0, vec, 0.0f); @@ -611,7 +611,7 @@ int UtcDaliDepthLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == 90.0f); + DALI_TEST_CHECK(deg.degree == 90.0f); Stage::GetCurrent().Remove(view); END_TEST; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-GridLayout.cpp b/automated-tests/src/dali-toolkit/utc-Dali-GridLayout.cpp index 7e9d341..6b050bc 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-GridLayout.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-GridLayout.cpp @@ -517,7 +517,7 @@ int UtcDaliGridLayoutScrollDirection(void) application.Render(); Degree deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == 0.0f); + DALI_TEST_CHECK(deg.degree == 0.0f); gridLayout->SetOrientation(ControlOrientation::Down); view.ActivateLayout(0, vec, 0.0f); @@ -525,7 +525,7 @@ int UtcDaliGridLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK((deg == 180.0f)); + DALI_TEST_CHECK((deg.degree == 180.0f)); layout->SetOrientation(ControlOrientation::Left); view.ActivateLayout(0, vec, 0.0f); @@ -533,7 +533,7 @@ int UtcDaliGridLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == 90.f); + DALI_TEST_CHECK(deg.degree == 90.f); gridLayout->SetOrientation(ControlOrientation::Right); view.ActivateLayout(0, vec, 0.0f); @@ -541,7 +541,7 @@ int UtcDaliGridLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == 270.0f); + DALI_TEST_CHECK(deg.degree == 270.0f); Stage::GetCurrent().Remove(view); END_TEST; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-MarkupProcessor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-MarkupProcessor.cpp deleted file mode 100644 index d2317a7..0000000 --- a/automated-tests/src/dali-toolkit/utc-Dali-MarkupProcessor.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include -#include - -// Need to override adaptor classes for toolkit test harness, so include -// test harness headers before dali headers. -#include - -#include -#include - -using namespace Dali; - -void utc_dali_toolkit_markup_processor_startup(void) -{ - test_return_value = TET_UNDEF; -} - -void utc_dali_toolkit_markup_processor_cleanup(void) -{ - test_return_value = TET_PASS; -} - -namespace -{ - -struct MarkupStringTest -{ - std::string input; - std::string expectedResult; -}; - -bool TestMarkupString( const std::string& input, const std::string& expectedResult, std::string& result ) -{ - Toolkit::MarkupProcessor::StyledTextArray styledTextArray; - - GetStyledTextArray( input, styledTextArray, true ); - GetMarkupString( styledTextArray, result ); - - return expectedResult == result; -} - -} // namespace - - -// Positive test case for a method -int UtcDaliMarkupProcessor(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliMarkupProcessor "); - - const std::string text1( "Text" ); - const std::string text2( "< font face ='FreeSerif' color= 'green' >t< / font >" ); - const std::string text3( "< font face = 'FreeSerif' size= '16' style = 'Bold' color='red'>< i>Styled< / u> Text< /i >< / font >< br / >" ); - const std::string text4( "Styled Text< br/>" ); - const std::string text5( "< shadow color = 'blue' paramx = '1' paramy = '0.75' >Shadow< / shadow>
" ); - const std::string text6( "< glow color = 'red' param = '0.1' >Glow< br />" ); - const std::string text7( "< outline color = 'red' paramx = '0.7' paramy = '0.7' >Outline< / outline >< /font >< br / >" ); - const std::string text8( "Smooth< br / >" ); - const std::string text9( "\\<" ); - const std::string text10( "\\>" ); - - char crlf[2]; - crlf[0] = 0x0D; - crlf[1] = 0x0A; - const std::string text11( crlf, 2 ); - - const std::string result1( text1 ); - const std::string result2( "t" ); - const std::string result3( "Styled Text
" ); - const std::string result4( "Styled Text
" ); - const std::string result5( "Shadow
" ); - const std::string result6( "Glow
" ); - const std::string result7( "Outline
" ); - const std::string result8( "Smooth
" ); - const std::string result9( text9 ); - const std::string result10( text10 ); - const std::string result11( "
" ); - - std::string markupString; - Toolkit::MarkupProcessor::StyledTextArray styledTextArray; - - GetStyledTextArray( text1, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result1, markupString, TEST_LOCATION ); - - GetStyledTextArray( text2, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result2, markupString, TEST_LOCATION ); - - GetStyledTextArray( text3, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result3, markupString, TEST_LOCATION ); - - GetStyledTextArray( text4, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result4, markupString, TEST_LOCATION ); - - GetStyledTextArray( text5, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result5, markupString, TEST_LOCATION ); - - GetStyledTextArray( text6, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result6, markupString, TEST_LOCATION ); - - GetStyledTextArray( text7, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result7, markupString, TEST_LOCATION ); - - GetStyledTextArray( text8, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result8, markupString, TEST_LOCATION ); - - GetStyledTextArray( text9, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - DALI_TEST_EQUALS( result9, markupString, TEST_LOCATION ); - - GetStyledTextArray( text10, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result10, markupString, TEST_LOCATION ); - - GetStyledTextArray( text11, styledTextArray, true ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result11, markupString, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliMarkupProcessorSetTextStyle01(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliMarkupProcessorSetTextStyle01 "); - - const std::string text1( "Text with no defined style" ); - const std::string result1( "Text with no defined style" ); - const std::string result2( "Text with no defined style" ); - - std::string markupString; - Toolkit::MarkupProcessor::StyledTextArray styledTextArray; - - GetStyledTextArray( text1, styledTextArray, true ); - - TextStyle style; - style.SetItalics( true ); - style.SetTextColor( Color::GREEN ); - - SetTextStyle( styledTextArray, style ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result1, markupString, TEST_LOCATION ); - - styledTextArray.clear(); - SetTextStyle( text1, styledTextArray, style ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result1, markupString, TEST_LOCATION ); - - GetStyledTextArray( text1, styledTextArray, true ); - SetTextStyleToRange( styledTextArray, style, TextStyle::ALL, 0, text1.size() - 1 ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result1, markupString, TEST_LOCATION ); - - GetStyledTextArray( text1, styledTextArray, true ); - SetTextStyleToRange( styledTextArray, style, TextStyle::ALL, 10, 19 ); - GetMarkupString( styledTextArray, markupString ); - - DALI_TEST_EQUALS( result2, markupString, TEST_LOCATION ); - - std::string plainString; - GetPlainString( styledTextArray, plainString ); - - DALI_TEST_EQUALS( text1, plainString, TEST_LOCATION ); - END_TEST; -} - -int UtcDaliMarkupProcessorSetTextStyle02(void) -{ - ToolkitTestApplication application; - - tet_infoline(" UtcDaliMarkupProcessorSetTextStyle02 "); - - Toolkit::MarkupProcessor::StyledTextArray styledTextArray; - - // Test style applied to and empty string doesn't crash - - TextStyle style; - style.SetItalics( true ); - style.SetTextColor( Color::GREEN ); - - bool fails = false; - try - { - SetTextStyle( styledTextArray, style ); - } - catch( ... ) - { - fails = true; - } - - DALI_TEST_CHECK( !fails ); - END_TEST; -} - -int UtcDaliMarkupProcessorTestColors(void) -{ - ToolkitTestApplication application; - - tet_infoline("UtcDaliMarkupProcessorTestColors "); - - struct MarkupStringTest colorTests[] = - { - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "white" ), - std::string( "white" ) - }, - { - std::string( "red" ), - std::string( "red" ) - }, - { - std::string( "green" ), - std::string( "green" ) - }, - { - std::string( "blue" ), - std::string( "blue" ) - }, - { - std::string( "yellow" ), - std::string( "yellow" ) - }, - { - std::string( "magenta" ), - std::string( "magenta" ) - }, - { - std::string( "cyan" ), - std::string( "cyan" ) - }, - { - std::string( "transparent" ), - std::string( "transparent" ) - }, - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "white" ), - std::string( "white" ) - }, - { - std::string( "red" ), - std::string( "red" ) - }, - { - std::string( "green" ), - std::string( "green" ) - }, - { - std::string( "blue" ), - std::string( "blue" ) - }, - { - std::string( "yellow" ), - std::string( "yellow" ) - }, - { - std::string( "magenta" ), - std::string( "magenta" ) - }, - { - std::string( "cyan" ), - std::string( "cyan" ) - }, - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "white" ), - std::string( "white" ) - }, - { - std::string( "red" ), - std::string( "red" ) - }, - { - std::string( "green" ), - std::string( "green" ) - }, - { - std::string( "blue" ), - std::string( "blue" ) - }, - { - std::string( "yellow" ), - std::string( "yellow" ) - }, - { - std::string( "magenta" ), - std::string( "magenta" ) - }, - { - std::string( "cyan" ), - std::string( "cyan" ) - }, - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "black" ), - std::string( "black" ) - }, - { - std::string( "white" ), - std::string( "white" ) - }, - { - std::string( "red" ), - std::string( "red" ) - }, - { - std::string( "green" ), - std::string( "green" ) - }, - { - std::string( "blue" ), - std::string( "blue" ) - }, - { - std::string( "yellow" ), - std::string( "yellow" ) - }, - { - std::string( "magenta" ), - std::string( "magenta" ) - }, - { - std::string( "cyan" ), - std::string( "cyan" ) - }, - { - std::string( "transparent" ), - std::string( "transparent" ) - }, - { - std::string( "outline" ), - std::string( "outline" ) - }, - }; - - const std::size_t numberOfTests( 36 ); - - bool fails = false; - for( std::size_t index = 0; index < numberOfTests; ++index ) - { - const MarkupStringTest& test = colorTests[index]; - - std::string result; - if( !TestMarkupString( test.input, test.expectedResult, result ) ) - { - TestMarkupString( test.input, test.expectedResult, result ); - tet_printf( "%s\n input : %s\nexpected result : %s\n result : %s\n", TEST_LOCATION, test.input.c_str(), test.expectedResult.c_str(), result.c_str() ); - - fails = true; - } - } - - DALI_TEST_CHECK( !fails ); - END_TEST; -} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-NavigationControl.cpp b/automated-tests/src/dali-toolkit/utc-Dali-NavigationControl.cpp index a2c7d54..4e81bf6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-NavigationControl.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-NavigationControl.cpp @@ -327,13 +327,12 @@ int UtcDaliNavigationControlCreateNavigationTitleBar(void) tet_infoline( "UtcDaliNavigationControlCreateNavigationTitleBar" ); ImageActor background = CreateSolidColorActor( Color::RED ); - TextStyle textStyle; Stage stage = Stage::GetCurrent(); NavigationControl naviControl = NavigationControl::New(); stage.Add( naviControl ); - Toolkit::NaviTitleBarStyle titleBarStyle( background, textStyle, textStyle, 720, 111, 68, 48, 34, 16, 11, 45, 63, 26, 14, 22 ); + Toolkit::NaviTitleBarStyle titleBarStyle( background, 720, 111, 68, 48, 34, 16, 11, 45, 63, 26, 14, 22 ); naviControl.CreateNavigationTitleBar( titleBarStyle, titleBarStyle ); Page naviItem = Page::New(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-PageTurnView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-PageTurnView.cpp index 443de6f..955f19d 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-PageTurnView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-PageTurnView.cpp @@ -371,6 +371,7 @@ int UtcDaliPageTurnViewEnterLeaveEditMode(void) factory.EnableOffscreenRendering( ); PageTurnView pageTurnView = PageTurnLandscapeView::New( factory, PAGE_SIZE ); + pageTurnView.SetRelayoutEnabled( false ); pageTurnView.SetPositionInheritanceMode( USE_PARENT_POSITION ); Stage::GetCurrent().Add( pageTurnView ); @@ -422,6 +423,7 @@ int UtcDaliPageTurnViewGetHitActor(void) factory.EnableOffscreenRendering( ); PageTurnView pageTurnView = PageTurnPortraitView::New( factory, PAGE_SIZE ); + pageTurnView.SetRelayoutEnabled( false ); pageTurnView.SetParentOrigin( ParentOrigin::TOP_LEFT ); pageTurnView.SetAnchorPoint( AnchorPoint::TOP_LEFT ); Stage::GetCurrent().Add( pageTurnView ); @@ -458,6 +460,7 @@ int UtcDaliPageTurnViewRefresh(void) TestPageFactory factory(application); factory.EnableOffscreenRendering( ); PageTurnView pageTurnView = PageTurnPortraitView::New( factory, PAGE_SIZE ); + pageTurnView.SetRelayoutEnabled( false ); pageTurnView.SetParentOrigin( ParentOrigin::TOP_LEFT ); pageTurnView.SetAnchorPoint( AnchorPoint::TOP_LEFT ); Stage::GetCurrent().Add( pageTurnView ); @@ -498,6 +501,7 @@ int UtcDaliPageTurnViewSignals(void) TestPageFactory factory(application); Vector2 size = Stage::GetCurrent().GetSize(); PageTurnView portraitView = PageTurnPortraitView::New( factory, size ); + portraitView.SetRelayoutEnabled( false ); portraitView.SetPositionInheritanceMode( USE_PARENT_POSITION ); Stage::GetCurrent().Add( portraitView ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Popup.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Popup.cpp index 1f2ecc7..0aaf295 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Popup.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Popup.cpp @@ -168,7 +168,7 @@ int UtcDaliPopoupSetProperty(void) //Test properties std::string testString = "Hello World"; popup.SetProperty(popup.GetPropertyIndex("title"), testString); - DALI_TEST_EQUALS( testString, popup.GetTitle().GetText(), TEST_LOCATION ); + DALI_TEST_EQUALS( testString, popup.GetTitle(), TEST_LOCATION ); END_TEST; } @@ -200,54 +200,10 @@ int UtcDaliPopupSetTitle(void) // Put in show state so it's layer is connected to popup (for ancestor check). popup.SetState(Popup::POPUP_SHOW, 0.0f); - TextView titleActor = TextView::New(); - titleActor.SetText("title"); - - DALI_TEST_CHECK( !popup.GetTitle() ); - popup.SetTitle(titleActor); - DALI_TEST_CHECK( popup.GetTitle() == titleActor ); - DALI_TEST_CHECK( (popup.GetTitle()) && (popup.GetTitle().GetText() == "title") ); - // verify titleActor is actually inside popup, and not elsewhere on stage, or off even. - DALI_TEST_CHECK( HasAncestor(titleActor, popup) ); - - TextView titleActor2 = TextView::New(); - titleActor2.SetText("anothertitle"); - popup.SetTitle(titleActor2); - DALI_TEST_CHECK( popup.GetTitle() != titleActor ); - DALI_TEST_CHECK( popup.GetTitle() == titleActor2 ); - DALI_TEST_CHECK( (popup.GetTitle()) && (popup.GetTitle().GetText() == "anothertitle") ); - // verify titleActor is actually inside popup, and not elsewhere on stage, or off even. - DALI_TEST_CHECK( HasAncestor(titleActor2, popup) ); - END_TEST; -} - -int UtcDaliPopupSetTitleText(void) -{ - ToolkitTestApplication application; // Exceptions require ToolkitTestApplication - tet_infoline(" UtcDaliPopupSetTitleText"); + popup.SetTitle("title"); - // Create the Popup actor - Popup popup = Popup::New(); - Stage::GetCurrent().Add( popup ); - // Put in show state so it's layer is connected to popup (for ancestor check). - popup.SetState(Popup::POPUP_SHOW, 0.0f); + DALI_TEST_CHECK( popup.GetTitle() == "title" ); - TextView titleActor = TextView::New(); - titleActor.SetText("title"); - - DALI_TEST_CHECK( !popup.GetTitle() ); - popup.SetTitle(titleActor); - DALI_TEST_CHECK( popup.GetTitle() == titleActor ); - DALI_TEST_CHECK( (popup.GetTitle()) && (popup.GetTitle().GetText() == "title") ); - // verify titleActor is actually inside popup, and not elsewhere on stage, or off even. - DALI_TEST_CHECK( HasAncestor(titleActor, popup) ); - - // this text should replace titleImage actor. - popup.SetTitle("newtext"); - DALI_TEST_CHECK( popup.GetTitle() != titleActor ); - DALI_TEST_CHECK( (popup.GetTitle()) && (popup.GetTitle().GetText() == "newtext") ); - // verify titleActor is no longer inside popup. (been displaced by newtext actor) - DALI_TEST_CHECK( !HasAncestor(titleActor, popup) ); END_TEST; } @@ -342,9 +298,9 @@ int UtcDaliPopupShowHide(void) PushButton button1 = PushButton::New(); PushButton button2 = PushButton::New(); - button1.SetPreferredSize(DEFAULT_BUTTON_SIZE.GetVectorXY()); + button1.SetSize(DEFAULT_BUTTON_SIZE.GetVectorXY()); popup.AddButton(button1); - button2.SetPreferredSize(DEFAULT_BUTTON_SIZE.GetVectorXY()); + button2.SetSize(DEFAULT_BUTTON_SIZE.GetVectorXY()); popup.AddButton(button2); // Showing/Hiding popup, results in all child Actors being diff --git a/automated-tests/src/dali-toolkit/utc-Dali-PushButton.cpp b/automated-tests/src/dali-toolkit/utc-Dali-PushButton.cpp index 4a2a33d..0d259d9 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-PushButton.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-PushButton.cpp @@ -279,27 +279,10 @@ int UtcDaliPushButtonSetImages(void) Actor imageActor; Image image01 = CreateSolidColorImage( Color::RED, 10, 10 ); - ImageActor imageActor01 = CreateSolidColorActor( Color::RED ); - imageActor01.SetSize( 20.f, 20.f ); - - Image image02 = CreateSolidColorImage( Color::RED, 30, 30 ); - ImageActor imageActor02 = CreateSolidColorActor( Color::RED ); - imageActor02.SetSize( 40.f, 40.f ); - - Image image03 = CreateSolidColorImage( Color::RED, 50, 50 ); - ImageActor imageActor03 = CreateSolidColorActor( Color::RED ); - imageActor03.SetSize( 60.f, 60.f ); - - Image image04 = CreateSolidColorImage( Color::RED, 70, 70 ); - ImageActor imageActor04 = CreateSolidColorActor( Color::RED ); - imageActor04.SetSize( 80.f, 80.f ); - - Image image05 = CreateSolidColorImage( Color::RED, 90, 90 ); - ImageActor imageActor05 = CreateSolidColorActor( Color::RED ); - imageActor05.SetSize( 100.f, 100.f ); Vector3 size; PushButton pushButton = PushButton::New(); + Stage::GetCurrent().Add( pushButton ); application.SendNotification(); application.Render(); @@ -311,100 +294,11 @@ int UtcDaliPushButtonSetImages(void) application.SendNotification(); application.Render(); - size = pushButton.GetButtonImage().GetCurrentSize(); + size = pushButton.GetCurrentSize(); DALI_TEST_EQUALS( size.width, 10.f, TEST_LOCATION ); DALI_TEST_EQUALS( size.height, 10.f, TEST_LOCATION ); - pushButton.SetButtonImage( imageActor01 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetButtonImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 20.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 20.f, TEST_LOCATION ); - - pushButton.SetBackgroundImage( image02 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetBackgroundImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 30.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 30.f, TEST_LOCATION ); - - pushButton.SetBackgroundImage( imageActor02 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetBackgroundImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 40.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 40.f, TEST_LOCATION ); - - pushButton.SetSelectedImage( image03 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetSelectedImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 50.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 50.f, TEST_LOCATION ); - - pushButton.SetSelectedImage( imageActor03 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetSelectedImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 60.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 60.f, TEST_LOCATION ); - - pushButton.SetDisabledBackgroundImage( image04 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetDisabledBackgroundImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 70.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 70.f, TEST_LOCATION ); - - pushButton.SetDisabledBackgroundImage( imageActor04 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetDisabledBackgroundImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 80.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 80.f, TEST_LOCATION ); - - pushButton.SetDisabledImage( image05 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetDisabledImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 90.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 90.f, TEST_LOCATION ); - - pushButton.SetDisabledImage( imageActor05 ); - - application.SendNotification(); - application.Render(); - - size = pushButton.GetDisabledImage().GetCurrentSize(); - - DALI_TEST_EQUALS( size.width, 100.f, TEST_LOCATION ); - DALI_TEST_EQUALS( size.height, 100.f, TEST_LOCATION ); END_TEST; } @@ -420,18 +314,11 @@ int UtcDaliPushButtonSetLabelText(void) application.SendNotification(); application.Render(); - TextView textView; - pushButton.SetLabel( STR ); - textView = TextView::DownCast( pushButton.GetLabel() ); - DALI_TEST_CHECK( STR == textView.GetText() ); - - TextView text = TextView::New( STR ); - pushButton.SetLabel( text ); + TextLabel label = TextLabel::DownCast( pushButton.GetLabel() ); + DALI_TEST_CHECK( STR == label.GetProperty( TextLabel::Property::TEXT ) ); - textView = TextView::DownCast( pushButton.GetLabel() ); - DALI_TEST_CHECK( STR == textView.GetText() ); END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-RadioButton.cpp b/automated-tests/src/dali-toolkit/utc-Dali-RadioButton.cpp index d53084c..c20a167 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-RadioButton.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-RadioButton.cpp @@ -105,12 +105,12 @@ int UtcDaliRadioButtonLabelActor(void) { ToolkitTestApplication application; - TextView actor1 = TextView::New( "test actor 1" ); + TextLabel actor1 = TextLabel::New( "test actor 1" ); RadioButton radioButton = RadioButton::New( actor1 ); DALI_TEST_CHECK( actor1 == radioButton.GetLabel() ); - TextView actor2 = TextView::New( "test actor 2" ); + TextLabel actor2 = TextLabel::New( "test actor 2" ); radioButton.SetLabel( actor2 ); DALI_TEST_CHECK( actor2 == radioButton.GetLabel() ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ScrollView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ScrollView.cpp index 9b9cad1..39af3d3 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ScrollView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ScrollView.cpp @@ -207,25 +207,13 @@ struct TestSumConstraint /** * @param[in] current The current base value - * @param[in] property The property to be added to current. + * @param[in] inputs Contains the property to be added to current. * @return The new current Vector. */ - Vector3 operator()(const Vector3& current) + void operator()( Vector3& current, const PropertyInputContainer& inputs ) { - gConstraintResult = current + mOffset; - return gConstraintResult; - } - - /** - * @param[in] current The current base value - * @param[in] property The property to be added to current. - * @return The new current Vector. - */ - Vector3 operator()(const Vector3& current, - const PropertyInput& property) - { - gConstraintResult = current + property.GetVector3() + mOffset; - return gConstraintResult; + gConstraintResult = current + inputs[0]->GetVector3() + mOffset; + current = gConstraintResult; } Vector3 mOffset; @@ -239,14 +227,11 @@ struct TestSumConstraint */ static float TestOvershootSnapDuration(ToolkitTestApplication &application, ScrollView scrollView) { - Property::Index overshootPropertyX = scrollView.GetPropertyIndex(ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME); - Property::Index overshootPropertyY = scrollView.GetPropertyIndex(ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME); - int timeToReachOrigin = -1; for(int i = 0;i(overshootPropertyX); - float overshootYValue = scrollView.GetProperty(overshootPropertyY); + float overshootXValue = scrollView.GetProperty(ScrollView::Property::OVERSHOOT_X); + float overshootYValue = scrollView.GetProperty(ScrollView::Property::OVERSHOOT_Y); if(overshootXValue == 0.0f && overshootYValue == 0.0f) { break; @@ -817,10 +802,8 @@ int UtcDaliScrollViewConstraints(void) a.SetPosition( TEST_ACTOR_POSITION ); Wait(application); - Property::Index scrollPositionProperty = scrollView.GetPropertyIndex(ScrollView::SCROLL_POSITION_PROPERTY_NAME); - Constraint constraint = Constraint::New( Actor::Property::POSITION, - Source(scrollView, scrollPositionProperty), - TestSumConstraint( TEST_CONSTRAINT_OFFSET ) ); + Constraint constraint = Constraint::New( scrollView, Actor::Property::POSITION, TestSumConstraint( TEST_CONSTRAINT_OFFSET ) ); + constraint.AddSource( Source(scrollView, ScrollView::Property::SCROLL_POSITION) ); constraint.SetRemoveAction(Constraint::Discard); scrollView.ApplyConstraintToChildren(constraint); Wait(application); @@ -865,12 +848,9 @@ int UtcDaliScrollViewBind(void) a.SetPosition( TEST_ACTOR_POSITION ); Wait(application); - Property::Index scrollPositionProperty = scrollView.GetPropertyIndex(ScrollView::SCROLL_POSITION_PROPERTY_NAME); // apply this constraint to scrollview - Constraint constraint = Constraint::New( Actor::Property::POSITION, - Source(scrollView, scrollPositionProperty), - TestSumConstraint( TEST_CONSTRAINT_OFFSET ) ); - + Constraint constraint = Constraint::New( scrollView, Actor::Property::POSITION, TestSumConstraint( TEST_CONSTRAINT_OFFSET ) ); + constraint.AddSource( Source(scrollView, ScrollView::Property::SCROLL_POSITION) ); constraint.SetRemoveAction(Constraint::Discard); scrollView.ApplyConstraintToChildren(constraint); @@ -1034,12 +1014,9 @@ int UtcDaliScrollViewOvershoot(void) // 1. Scroll page in NW (-500,-500 pixels), then inspect overshoot. (don't release touch) Vector2 currentPos = Vector2(100.0f, 100.0f); currentPos = PerformGestureDiagonalSwipe(application, currentPos, Vector2(5.0f, 5.0f), 100, false); - Property::Index overshootXProperty = scrollView.GetPropertyIndex(ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME); - Property::Index overshootYProperty = scrollView.GetPropertyIndex(ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME); - Property::Index scrollPositionProperty = scrollView.GetPropertyIndex(ScrollView::SCROLL_POSITION_PROPERTY_NAME); - float overshootXValue = scrollView.GetProperty(overshootXProperty); - float overshootYValue = scrollView.GetProperty(overshootYProperty); - Vector3 positionValue = scrollView.GetProperty(scrollPositionProperty); + float overshootXValue = scrollView.GetProperty(ScrollView::Property::OVERSHOOT_X); + float overshootYValue = scrollView.GetProperty(ScrollView::Property::OVERSHOOT_Y); + Vector3 positionValue = scrollView.GetProperty(ScrollView::Property::SCROLL_POSITION); DALI_TEST_EQUALS(overshootXValue, 1.0f, TEST_LOCATION); DALI_TEST_EQUALS(overshootYValue, 1.0f, TEST_LOCATION); DALI_TEST_EQUALS(positionValue, Vector3::ZERO, TEST_LOCATION); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ScrollViewEffect.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ScrollViewEffect.cpp index 5cda497..1b6f1c6 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ScrollViewEffect.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ScrollViewEffect.cpp @@ -137,11 +137,17 @@ static void OnScrollComplete( const Vector3& position ) ScrollView SetupTestScrollView(int rows, int columns, Vector2 size) { + Constraint constraint; + ScrollView scrollView = ScrollView::New(); scrollView.SetSize(size); scrollView.SetAnchorPoint(AnchorPoint::CENTER); scrollView.SetParentOrigin(ParentOrigin::CENTER); - scrollView.ApplyConstraint( Constraint::New( Dali::Actor::Property::SIZE, Dali::ParentSource( Dali::Actor::Property::SIZE ), Dali::EqualToConstraint() ) ); + + constraint = Constraint::New( scrollView, Dali::Actor::Property::SIZE, Dali::EqualToConstraint() ); + constraint.AddSource( Dali::ParentSource( Dali::Actor::Property::SIZE ) ); + constraint.Apply(); + scrollView.SetWrapMode(false); scrollView.ScrollStartedSignal().Connect( &OnScrollStart ); scrollView.ScrollUpdatedSignal().Connect( &OnScrollUpdate ); @@ -175,7 +181,10 @@ ScrollView SetupTestScrollView(int rows, int columns, Vector2 size) container.SetAnchorPoint(AnchorPoint::CENTER); container.SetSize( size ); scrollView.Add( container ); - container.ApplyConstraint( Constraint::New( Actor::Property::SIZE, ParentSource( Actor::Property::SIZE ), EqualToConstraint() ) ); + + constraint = Constraint::New( container, Actor::Property::SIZE, EqualToConstraint() ); + constraint.AddSource( Dali::ParentSource( Dali::Actor::Property::SIZE ) ); + constraint.Apply(); gPages.clear(); for(int row = 0;row( Actor::Property::SIZE, ParentSource( Actor::Property::SIZE ), EqualToConstraint() ) ); + + constraint = Constraint::New( page, Actor::Property::SIZE, EqualToConstraint() ); + constraint.AddSource( Dali::ParentSource( Dali::Actor::Property::SIZE ) ); + constraint.Apply(); page.SetParentOrigin( ParentOrigin::CENTER ); page.SetAnchorPoint( AnchorPoint::CENTER ); page.SetPosition( column * size.x, row * size.y ); @@ -322,7 +334,10 @@ int UtcDaliScrollViewSpiralEffectTest(void) { Actor page = *pageIter; page.RemoveConstraints(); - page.ApplyConstraint( Constraint::New( Actor::Property::SIZE, ParentSource( Actor::Property::SIZE ), EqualToConstraint() ) ); + + Constraint constraint = Constraint::New( page, Actor::Property::SIZE, EqualToConstraint() ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.Apply(); effect.ApplyToPage(page, Vector2(Math::PI_2, 0.0f)); } Wait(application); @@ -431,7 +446,9 @@ int UtcDaliScrollViewPageCubeEffectTest(void) { Actor page = *pageIter; page.RemoveConstraints(); - page.ApplyConstraint( Constraint::New( Actor::Property::SIZE, ParentSource( Actor::Property::SIZE ), EqualToConstraint() ) ); + Constraint constraint = Constraint::New( page, Actor::Property::SIZE, EqualToConstraint() ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.Apply(); effect.ApplyToPage(page, Vector2(Math::PI_2, 0.0f)); } Wait(application); @@ -466,7 +483,9 @@ int UtcDaliScrollViewPageCarouselEffectTest(void) { Actor page = *pageIter; page.RemoveConstraints(); - page.ApplyConstraint( Constraint::New( Actor::Property::SIZE, ParentSource( Actor::Property::SIZE ), EqualToConstraint() ) ); + Constraint constraint = Constraint::New( page, Actor::Property::SIZE, EqualToConstraint() ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.Apply(); effect.ApplyToPage(page); } Wait(application); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp index d5d2ef0..89090da 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Slider.cpp @@ -125,7 +125,7 @@ int UtcDaliSliderSignals(void) Stage::GetCurrent().Add( slider ); slider.SetParentOrigin(ParentOrigin::TOP_LEFT); slider.SetAnchorPoint(ParentOrigin::TOP_LEFT); - slider.SetPreferredSize( Vector2( Stage::GetCurrent().GetSize().x, 20.0f ) ); + slider.SetSize( Vector2( Stage::GetCurrent().GetSize().x, 20.0f ) ); slider.SetPosition( 0.0f, 0.0f ); const float MIN_BOUND = 0.0f; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-SpiralLayout.cpp b/automated-tests/src/dali-toolkit/utc-Dali-SpiralLayout.cpp index ea4e8d1..2bed81a 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-SpiralLayout.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-SpiralLayout.cpp @@ -130,7 +130,7 @@ int UtcDaliSpiralSetAndGetItemSpacing(void) spiralLayout->SetItemSpacing(Radian(0.6f)); // Check whether we get the correct item spacing - DALI_TEST_EQUALS(spiralLayout->GetItemSpacing(), 0.6f, TEST_LOCATION ); + DALI_TEST_EQUALS(spiralLayout->GetItemSpacing(), Radian(0.6f), TEST_LOCATION ); END_TEST; } @@ -464,7 +464,7 @@ int UtcDaliSpiralLayoutScrollDirection(void) application.Render(); Degree deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == -45.0f); + DALI_TEST_CHECK(deg.degree == -45.0f); navigationLayout->SetOrientation(ControlOrientation::Down); view.ActivateLayout(0, vec, 0.0f); @@ -472,7 +472,7 @@ int UtcDaliSpiralLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK((deg == 180.0f - 45.0f)); + DALI_TEST_CHECK((deg.degree == 180.0f - 45.0f)); layout->SetOrientation(ControlOrientation::Left); view.ActivateLayout(0, vec, 0.0f); @@ -480,7 +480,7 @@ int UtcDaliSpiralLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == 45.0f); + DALI_TEST_CHECK(deg.degree == 45.0f); navigationLayout->SetOrientation(ControlOrientation::Right); view.ActivateLayout(0, vec, 0.0f); @@ -488,7 +488,7 @@ int UtcDaliSpiralLayoutScrollDirection(void) application.Render(); deg = layout->GetScrollDirection(); - DALI_TEST_CHECK(deg == (270.0f - 45.0f)); + DALI_TEST_CHECK(deg.degree == (270.0f - 45.0f)); Stage::GetCurrent().Remove(view); END_TEST; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-SuperBlurView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-SuperBlurView.cpp index 5fd205c..b7e662e 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-SuperBlurView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-SuperBlurView.cpp @@ -197,6 +197,7 @@ int UtcDaliSuperBlurViewGetBlurredImage(void) tet_infoline( "UtcDaliSuperBlurViewGetBlurredImage" ); SuperBlurView blurView = SuperBlurView::New( BLUR_LEVELS ); + blurView.SetRelayoutEnabled( false ); blurView.SetSize( 100.f,100.f ); Image inputImage = CreateSolidColorImage( application, Color::GREEN, 100, 100 ); blurView.SetImage( inputImage ); @@ -207,8 +208,8 @@ int UtcDaliSuperBlurViewGetBlurredImage(void) DALI_TEST_CHECK( image1 ); Image image2 = blurView.GetBlurredImage( 2 ); - DALI_TEST_CHECK( image2.GetWidth() == 25 ); - DALI_TEST_CHECK( image2.GetHeight() == 25 ); + DALI_TEST_EQUALS( image2.GetWidth(), 25, TEST_LOCATION ); + DALI_TEST_EQUALS( image2.GetHeight(), 25, TEST_LOCATION ); Image image3 = blurView.GetBlurredImage( 3 ); DALI_TEST_CHECK( FrameBufferImage::DownCast( image2 ) ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp index 484453c..dc6b0af 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp @@ -58,9 +58,9 @@ struct Constraint100 /** * function operator to apply the parent size */ - Dali::Vector3 operator()(const Dali::Vector3& current) + void operator()( Dali::Vector3& current, const PropertyInputContainer& /* inputs */ ) { - return Dali::Vector3( 100.0f, 100.0f, 100.0f ); + current.x = current.y = current.z = 100.0f; } }; @@ -73,18 +73,18 @@ static void SetupTableViewAndActors(TableView& tableView, Actor& actor1, Actor& tableView.SetRelayoutEnabled( true ); Stage::GetCurrent().Add( tableView ); - tableView.SetPreferredSize( Dali::Vector2( 100.0f, 100.0f ) ); + tableView.SetSize( Dali::Vector2( 100.0f, 100.0f ) ); actor1 = Actor::New(); actor2 = Actor::New(); actor3 = Actor::New(); actor1.SetRelayoutEnabled( true ); - actor1.SetPreferredSize( Dali::Vector2( 10, 10 ) ); + actor1.SetSize( Dali::Vector2( 10, 10 ) ); actor2.SetRelayoutEnabled( true ); - actor2.SetPreferredSize( Dali::Vector2( 10, 10 ) ); + actor2.SetSize( Dali::Vector2( 10, 10 ) ); actor3.SetRelayoutEnabled( true ); - actor3.SetPreferredSize( Dali::Vector2( 10, 10 ) ); + actor3.SetSize( Dali::Vector2( 10, 10 ) ); tableView.AddChild( actor1, TableView::CellPosition( 0, 0 ) ); tableView.AddChild( actor2, TableView::CellPosition( 0, 1 ) ); @@ -541,7 +541,7 @@ int UtcDaliTableViewSetGetProperty(void) // Create a 1x1 table-view TableView tableView = TableView::New(1,1); - tableView.SetPreferredSize( Vector2( 100.0f, 100.0f ) ); + tableView.SetSize( Vector2( 100.0f, 100.0f ) ); DALI_TEST_CHECK( tableView ); // Test "rows" property @@ -642,7 +642,8 @@ int UtcDaliTableViewCustomProperties(void) // Create a 10x10 table-view TableView tableView = TableView::New(10,10); - tableView.ApplyConstraint( Constraint::New( Actor::Property::SIZE, Constraint100() ) ); + Constraint constraint = Constraint::New( tableView, Actor::Property::SIZE, Constraint100() ); + constraint.Apply(); DALI_TEST_CHECK( tableView ); // Create a child actor with the custom properties diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp new file mode 100644 index 0000000..9069525 --- /dev/null +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +using namespace Dali; +using namespace Toolkit; + +void dali_textfield_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void dali_textfield_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +const char* const PROPERTY_NAME_RENDERING_BACKEND = "rendering-backend"; +const char* const PROPERTY_NAME_PLACEHOLDER_TEXT = "placeholder-text"; +const char* const PROPERTY_NAME_FONT_FAMILY = "font-family"; +const char* const PROPERTY_NAME_FONT_STYLE = "font-style"; +const char* const PROPERTY_NAME_POINT_SIZE = "point-size"; +const char* const PROPERTY_NAME_EXCEED_POLICY = "exceed-policy"; +const char* const PROPERTY_NAME_PRIMARY_CURSOR_COLOR = "primary-cursor-color"; +const char* const PROPERTY_NAME_SECONDARY_CURSOR_COLOR = "secondary-cursor-color"; +const char* const PROPERTY_NAME_ENABLE_CURSOR_BLINK = "enable-cursor-blink"; +const char* const PROPERTY_NAME_CURSOR_BLINK_INTERVAL = "cursor-blink-interval"; +const char* const PROPERTY_NAME_CURSOR_BLINK_DURATION = "cursor-blink-duration"; +const char* const PROPERTY_NAME_GRAB_HANDLE_IMAGE = "grab-handle-image"; +const char* const PROPERTY_NAME_DECORATION_BOUNDING_BOX = "decoration-bounding-box"; +const char* const PROPERTY_NAME_HORIZONTAL_ALIGNMENT = "horizontal-alignment"; +const char* const PROPERTY_NAME_VERTICAL_ALIGNMENT = "vertical-alignment"; + +static bool gObjectCreatedCallBackCalled; + +static void TestCallback(BaseHandle handle) +{ + gObjectCreatedCallBackCalled = true; +} + +} // namespace + +int UtcDaliTextFieldNew(void) +{ + ToolkitTestApplication application; + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + //Additional check to ensure object is created by checking if it's registered + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + DALI_TEST_CHECK( registry ); + + gObjectCreatedCallBackCalled = false; + registry.ObjectCreatedSignal().Connect(&TestCallback); + { + TextField field = TextField::New(); + } + DALI_TEST_CHECK( gObjectCreatedCallBackCalled ); + END_TEST; +} + +int UtcDaliTextFieldGetSetProperty(void) +{ + ToolkitTestApplication application; + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + // Check Property Indices are correct + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_RENDERING_BACKEND ) == TextField::Property::RENDERING_BACKEND ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER_TEXT ) == TextField::Property::PLACEHOLDER_TEXT ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_FONT_FAMILY ) == TextField::Property::FONT_FAMILY ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_FONT_STYLE ) == TextField::Property::FONT_STYLE ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_POINT_SIZE ) == TextField::Property::POINT_SIZE ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_EXCEED_POLICY ) == TextField::Property::EXCEED_POLICY ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PRIMARY_CURSOR_COLOR ) == TextField::Property::PRIMARY_CURSOR_COLOR ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SECONDARY_CURSOR_COLOR ) == TextField::Property::SECONDARY_CURSOR_COLOR ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_CURSOR_BLINK ) == TextField::Property::ENABLE_CURSOR_BLINK ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_CURSOR_BLINK_INTERVAL ) == TextField::Property::CURSOR_BLINK_INTERVAL ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_CURSOR_BLINK_DURATION ) == TextField::Property::CURSOR_BLINK_DURATION ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_GRAB_HANDLE_IMAGE ) == TextField::Property::GRAB_HANDLE_IMAGE ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_DECORATION_BOUNDING_BOX ) == TextField::Property::DECORATION_BOUNDING_BOX ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_HORIZONTAL_ALIGNMENT ) == TextField::Property::HORIZONTAL_ALIGNMENT ); + DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_VERTICAL_ALIGNMENT ) == TextField::Property::VERTICAL_ALIGNMENT ); + + // Check exceed policy + field.SetProperty( TextField::Property::EXCEED_POLICY, TextField::EXCEED_POLICY_CLIP ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::EXCEED_POLICY ), TextField::EXCEED_POLICY_CLIP, TEST_LOCATION ); + + // Check cursor properties + field.SetProperty( TextField::Property::ENABLE_CURSOR_BLINK, true ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::ENABLE_CURSOR_BLINK ), true, TEST_LOCATION ); + field.SetProperty( TextField::Property::PRIMARY_CURSOR_COLOR, Color::RED ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::RED, TEST_LOCATION ); + field.SetProperty( TextField::Property::SECONDARY_CURSOR_COLOR, Color::BLUE ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLUE, TEST_LOCATION ); + field.SetProperty( TextField::Property::CURSOR_BLINK_DURATION, 10.0f ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::CURSOR_BLINK_DURATION ), 10.0f, TEST_LOCATION ); + + // Blink interval gets converted to milliseconds.... + field.SetProperty( TextField::Property::CURSOR_BLINK_INTERVAL, 1.0f ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::CURSOR_BLINK_INTERVAL ), 1000.0f, TEST_LOCATION ); + + // Decoration bounding box + field.SetProperty( TextField::Property::DECORATION_BOUNDING_BOX, Rect( 0, 0, 1, 1 ) ); + DALI_TEST_EQUALS( field.GetProperty >( TextField::Property::DECORATION_BOUNDING_BOX ), Rect( 0, 0, 1, 1 ), TEST_LOCATION ); + + // Check that the Alignment properties can be correctly set + field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "BEGIN" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION ); + field.SetProperty( TextField::Property::VERTICAL_ALIGNMENT, "TOP" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION ); + END_TEST; +} + +int utcDaliTextFieldBasicRender(void) +{ + ToolkitTestApplication application; + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "BEGIN" ); + + try + { + // Render some text with the basic backend + field.SetProperty( TextField::Property::RENDERING_BACKEND, Text::RENDERING_BASIC ); + application.SendNotification(); + application.Render(); + } + catch( ... ) + { + tet_result(TET_FAIL); + } + END_TEST; +} + +int utcDaliTextFieldAtlasRender(void) +{ + ToolkitTestApplication application; + TextField field = TextField::New(); + DALI_TEST_CHECK( field ); + + field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + try + { + // Render some text with the shared atlas backend + field.SetProperty( TextField::Property::RENDERING_BACKEND, Text::RENDERING_SHARED_ATLAS ); + application.SendNotification(); + application.Render(); + } + catch( ... ) + { + tet_result(TET_FAIL); + } + END_TEST; +} + diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp new file mode 100644 index 0000000..3365605 --- /dev/null +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +using namespace Dali; +using namespace Toolkit; + +void dali_textlabel_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void dali_textlabel_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +const char* const PROPERTY_NAME_RENDERING_BACKEND = "rendering-backend"; +const char* const PROPERTY_NAME_TEXT = "text"; +const char* const PROPERTY_NAME_FONT_FAMILY = "font-family"; +const char* const PROPERTY_NAME_FONT_STYLE = "font-style"; +const char* const PROPERTY_NAME_POINT_SIZE = "point-size"; +const char* const PROPERTY_NAME_MULTI_LINE = "multi-line"; +const char* const PROPERTY_NAME_HORIZONTAL_ALIGNMENT = "horizontal-alignment"; +const char* const PROPERTY_NAME_VERTICAL_ALIGNMENT = "vertical-alignment"; +const char* const PROPERTY_NAME_TEXT_COLOR = "text-color"; +const char* const PROPERTY_NAME_SHADOW_OFFSET = "shadow-offset"; +const char* const PROPERTY_NAME_SHADOW_COLOR = "shadow-color"; +const char* const PROPERTY_NAME_UNDERLINE_ENABLED = "underline-enabled"; +const char* const PROPERTY_NAME_UNDERLINE_COLOR = "underline-color"; + +static bool gObjectCreatedCallBackCalled; + +static void TestCallback(BaseHandle handle) +{ + gObjectCreatedCallBackCalled = true; +} + +} // namespace + +int UtcDaliTextLabelNew(void) +{ + ToolkitTestApplication application; + TextLabel label = TextLabel::New("Test Text"); + DALI_TEST_CHECK( label ); + + //Additional check to ensure object is created by checking if it's registered + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + DALI_TEST_CHECK( registry ); + + gObjectCreatedCallBackCalled = false; + registry.ObjectCreatedSignal().Connect(&TestCallback); + { + TextLabel label = TextLabel::New("Test Text"); + } + DALI_TEST_CHECK( gObjectCreatedCallBackCalled ); + END_TEST; +} + +int UtcDaliTextLabelGetSetProperty(void) +{ + ToolkitTestApplication application; + TextLabel label = TextLabel::New("Test Text"); + DALI_TEST_CHECK( label ); + + // Check Property Indices are correct + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_RENDERING_BACKEND ) == TextLabel::Property::RENDERING_BACKEND ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_TEXT ) == TextLabel::Property::TEXT ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_FONT_FAMILY ) == TextLabel::Property::FONT_FAMILY ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_FONT_STYLE ) == TextLabel::Property::FONT_STYLE ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_POINT_SIZE ) == TextLabel::Property::POINT_SIZE ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_MULTI_LINE ) == TextLabel::Property::MULTI_LINE ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_HORIZONTAL_ALIGNMENT ) == TextLabel::Property::HORIZONTAL_ALIGNMENT ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_VERTICAL_ALIGNMENT ) == TextLabel::Property::VERTICAL_ALIGNMENT ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_TEXT_COLOR ) == TextLabel::Property::TEXT_COLOR ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_SHADOW_OFFSET ) == TextLabel::Property::SHADOW_OFFSET ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_SHADOW_COLOR ) == TextLabel::Property::SHADOW_COLOR ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE_ENABLED ) == TextLabel::Property::UNDERLINE_ENABLED ); + DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE_COLOR ) == TextLabel::Property::UNDERLINE_COLOR ); + + // Check label defaults are correct + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::RENDERING_BACKEND ), Text::RENDERING_SHARED_ATLAS, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::TEXT_COLOR ), Color::WHITE, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_COLOR ), Vector4::ZERO, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_ENABLED ), false, TEST_LOCATION ); + + // Check that text can be correctly reset + label.SetProperty( TextLabel::Property::TEXT, "Setting Text" ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::TEXT ), "Setting Text", TEST_LOCATION ); + + // Check that the Alignment properties can be correctly set + label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "BEGIN" ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION ); + label.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "TOP" ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION ); + + // Check that shadow parameters can be correctly set + label.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 3.0f, 3.0f ) ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_OFFSET ), Vector2( 3.0f, 3.0f ), TEST_LOCATION ); + label.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLUE ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_COLOR ), Color::BLUE, TEST_LOCATION ); + + // Check that underline parameters can be correctly set + label.SetProperty( TextLabel::Property::UNDERLINE_ENABLED, true ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_ENABLED ), true, TEST_LOCATION ); + label.SetProperty( TextLabel::Property::UNDERLINE_COLOR, Color::RED ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_COLOR ), Color::RED, TEST_LOCATION ); + + // Toggle multi-line + label.SetProperty( TextLabel::Property::MULTI_LINE, true ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::MULTI_LINE ), true, TEST_LOCATION ); + END_TEST; +} + +int utcDaliTextlabelBasicRender(void) +{ + ToolkitTestApplication application; + TextLabel label = TextLabel::New("Test Text"); + DALI_TEST_CHECK( label ); + + label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "BEGIN" ); + label.SetProperty( TextLabel::Property::MULTI_LINE, true ); + + try + { + // Render some text with the basic backend + label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Text::RENDERING_BASIC ); + application.SendNotification(); + application.Render(); + } + catch( ... ) + { + tet_result(TET_FAIL); + } + END_TEST; +} + +int utcDaliTextlabelAtlasRender(void) +{ + ToolkitTestApplication application; + TextLabel label = TextLabel::New("Test Text"); + DALI_TEST_CHECK( label ); + + // Turn on all the effects + label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + label.SetProperty( TextLabel::Property::MULTI_LINE, true ); + label.SetProperty( TextLabel::Property::UNDERLINE_ENABLED, true ); + label.SetProperty( TextLabel::Property::UNDERLINE_COLOR, Color::RED ); + label.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 1.0f, 1.0f ) ); + label.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLUE ); + try + { + // Render some text with the shared atlas backend + label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Text::RENDERING_SHARED_ATLAS ); + application.SendNotification(); + application.Render(); + } + catch( ... ) + { + tet_result(TET_FAIL); + } + END_TEST; +} + diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ToolBar.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ToolBar.cpp index e1042b2..d359334 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ToolBar.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ToolBar.cpp @@ -114,23 +114,18 @@ int UtcDaliToolBarAddControl01(void) try { ImageActor control1 = CreateSolidColorActor( Color::RED ); - control1.SetPreferredSize( Vector2( 100.f, 100.f ) ); - control1.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + control1.SetSize( Vector2( 100.f, 100.f ) ); ImageActor control2 = CreateSolidColorActor( Color::RED ); - control2.SetPreferredSize( Vector2( 100.f, 100.f ) ); - control2.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + control2.SetSize( Vector2( 100.f, 100.f ) ); ImageActor control3 = CreateSolidColorActor( Color::RED ); - control3.SetPreferredSize( Vector2( 100.f, 100.f ) ); - control3.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + control3.SetSize( Vector2( 100.f, 100.f ) ); ImageActor control4 = CreateSolidColorActor( Color::RED ); - control4.SetPreferredSize( Vector2( 100.f, 100.f ) ); - control4.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + control4.SetSize( Vector2( 100.f, 100.f ) ); ImageActor control5 = CreateSolidColorActor( Color::RED ); - control5.SetPreferredSize( Vector2( 100.f, 100.f ) ); - control5.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + control5.SetSize( Vector2( 100.f, 100.f ) ); ToolBar toolbar = ToolBar::New(); - toolbar.SetPreferredSize( Vector2( 600.f, 100.f ) ); + toolbar.SetSize( Vector2( 600.f, 100.f ) ); application.Render(); application.SendNotification(); @@ -144,14 +139,11 @@ int UtcDaliToolBarAddControl01(void) toolbar.AddControl( control5, 0.1f, Alignment::HorizontalRight, Alignment::Padding( 1.f, 1.f, 1.f, 1.f ) ); ImageActor control6 = CreateSolidColorActor( Color::RED ); - control6.SetPreferredSize( Vector2( 100.f, 100.f ) ); - control6.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + control6.SetSize( Vector2( 100.f, 100.f ) ); ImageActor control7 = CreateSolidColorActor( Color::RED ); - control7.SetPreferredSize( Vector2( 100.f, 100.f ) ); - control7.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + control7.SetSize( Vector2( 100.f, 100.f ) ); ImageActor control8 = CreateSolidColorActor( Color::RED ); - control8.SetPreferredSize( Vector2( 100.f, 100.f ) ); - control8.SetResizePolicy( FIXED, ALL_DIMENSIONS ); + control8.SetSize( Vector2( 100.f, 100.f ) ); application.Render(); application.SendNotification(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-View.cpp b/automated-tests/src/dali-toolkit/utc-Dali-View.cpp index 2d28fd2..ad124e1 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-View.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-View.cpp @@ -308,7 +308,7 @@ int UtcDaliViewOrientationChanged(void) view.SetRelayoutEnabled( true ); Stage::GetCurrent().Add( view ); - view.SetPreferredSize( Vector2( 480, 800 ) ); + view.SetSize( Vector2( 480, 800 ) ); view.OrientationAnimationStartedSignal().Connect( &StartAnimation ); diff --git a/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.cpp b/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.cpp deleted file mode 100644 index a291096..0000000 --- a/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include - -using namespace Dali; -using namespace Dali::Toolkit; -using namespace Dali::Toolkit::Text; - -#define NO_MESH 1 - -namespace -{ - -const std::size_t PADDING = 2; //< To avoid GL filtering artefacts - -struct TextureCoordinates -{ - TextureCoordinates() - : topLeft( 0.0f, 0.0f ), - topRight( 1.0f, 0.0f ), - bottomLeft( 0.0f, 1.0f ), - bottomRight( 1.0f, 1.0f ) - { - } - - Vector2 topLeft; - Vector2 topRight; - Vector2 bottomLeft; - Vector2 bottomRight; -}; - -struct AtlasHelperGlyph -{ - AtlasHelperGlyph() - : fontId( 0 ), - index( 0 ), - xOffset( 0 ), - width( 0 ), - height( 0 ) - { - } - - AtlasHelperGlyph( FontId id, - GlyphIndex glyphIndex, - std::size_t offset, - std::size_t widthPixels, - std::size_t heightPixels ) - : fontId( id ), - index( glyphIndex ), - xOffset( offset ), - width( widthPixels ), - height( heightPixels ) - { - } - - FontId fontId; - GlyphIndex index; - std::size_t xOffset; - std::size_t width; - std::size_t height; - TextureCoordinates coords; -}; - -struct AtlasHelper -{ - AtlasHelper() - : mWidth( 0.0f ), - mHeight( 0.0f ) - { - mFontClient = TextAbstraction::FontClient::Get(); - } - - void Reset() - { - mWidth = 0.0f; - mHeight = 0.0f; - mGlyphs.clear(); - } - - void Reserve( std::size_t size ) - { - mGlyphs.reserve( size ); - } - - bool GlyphFound( FontId fontId, GlyphIndex index ) const - { - for( unsigned int i=0; i(glyph.xOffset) / static_cast(mWidth); - coords.topLeft.y = 0.0f; - coords.topRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(mWidth); - coords.topRight.y = 0.0f; - coords.bottomLeft.x = static_cast(glyph.xOffset) / static_cast(mWidth); - coords.bottomLeft.y = static_cast(glyph.height) / static_cast(mHeight); - coords.bottomRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(mWidth); - coords.bottomRight.y = static_cast(glyph.height) / static_cast(mHeight); - } - - return atlas; - } - - void GetTextureCoordinates( FontId fontId, GlyphIndex index, TextureCoordinates& coords ) - { - for( unsigned int i=0; i mGlyphs; - - TextAbstraction::FontClient mFontClient; -}; - -} // unnamed namespace - -struct BasicRenderer::Impl -{ - /** - * @brief Ccreate an Atlas, uploading the necessary glyph bitmaps - * - * @param[in] glyphs The glyphs to upload. - */ - Atlas CreateAtlas( const Vector& glyphs ) - { - AtlasHelper& helper = mAtlasHelper; - - // Clear previous atlas - helper.Reset(); - helper.Reserve( glyphs.Count() ); - - for( unsigned int i=0; i 0 && - height > 0 ) // skip whitespace - { - if( !helper.GlyphFound( glyphs[i].fontId, glyphs[i].index ) ) - { - helper.AddGlyph( glyphs[i] ); - } - } - } - - // Uploads the bitmaps to Dali - return helper.CreateAtlas(); - } - - -#if ! defined( NO_MESH ) - /** - * @brief Helper method to create a mesh with one quad per glyph. - * - * @param[in] glyphs The glyphs to display. - * @param[in] positions The 2D positions of the glyphs. - * @param[in] image The material uses this as a diffuse texture. - */ - Mesh CreateMesh( const Vector& glyphs, const std::vector& positions, Image image ) - { - MeshData::VertexContainer vertices( 4 * glyphs.Count() ); // 1 quad per glyph - - MeshData::FaceIndices faces; - faces.reserve( 6 * glyphs.Count() ); // 2 triangles per quad - - for( unsigned int i=0; i 0 && - height > 0 ) // skip whitespace - { - const Vector2& position = positions[i]; - - TextureCoordinates coords; - mAtlasHelper.GetTextureCoordinates( glyphs[i].fontId, glyphs[i].index, coords ); - - vertices[ i*4 + 0 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 0.0f*height, 0.0f ), coords.topLeft, Vector3( 1.0f, 0.0f, 0.0f ) ); - vertices[ i*4 + 1 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 0.0f*height, 0.0f ), coords.topRight, Vector3( 1.0f, 1.0f, 0.0f ) ); - vertices[ i*4 + 2 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomLeft, Vector3( 0.0f, 1.0f, 0.0f ) ); - vertices[ i*4 + 3 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomRight, Vector3( 0.0f, 0.0f, 1.0f ) ); - - faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 3 ); faces.push_back( i*4 + 1 ); - faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 2 ); faces.push_back( i*4 + 3 ); - } - } - - Material material = Material::New( "Material" ); - material.SetDiffuseTexture( image ); - - // Create the mesh data from the vertices and faces - MeshData meshData; - meshData.SetHasColor( false ); - meshData.SetMaterial( material ); - meshData.SetVertices( vertices ); - meshData.SetFaceIndices( faces ); - - // Create a mesh from the data - Dali::Mesh mesh = Mesh::New( meshData ); - return mesh; - } -#endif - - RenderableActor mActor; ///< The actor which renders the text - - AtlasHelper mAtlasHelper; ///< A helper class for storing atlas positions etc. -}; - -Text::RendererPtr BasicRenderer::New() -{ - return Text::RendererPtr( new BasicRenderer() ); -} - -RenderableActor BasicRenderer::Render( Text::ViewInterface& view ) -{ - Text::Length numberOfGlyphs = view.GetNumberOfGlyphs(); - - if( numberOfGlyphs > 0 ) - { - Vector glyphs; - glyphs.Resize( numberOfGlyphs ); - - view.GetGlyphs( 0, &glyphs[0], numberOfGlyphs ); - - std::vector positions; - positions.resize( numberOfGlyphs ); - view.GetGlyphPositions( 0, &positions[0], numberOfGlyphs ); - - Atlas atlas = mImpl->CreateAtlas( glyphs ); - -#if ! defined( NO_MESH ) - MeshActor actor = MeshActor::New( mImpl->CreateMesh( glyphs, positions, atlas ) ); - actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - actor.SetAffectedByLighting( false ); - - ShaderEffect shader = BasicShader::New(); - actor.SetShaderEffect( shader ); - - mImpl->mActor = actor; -#endif - } - - return mImpl->mActor; -} - -BasicRenderer::BasicRenderer() -{ - mImpl = new Impl(); -} - -BasicRenderer::~BasicRenderer() -{ - delete mImpl; -} diff --git a/build/tizen/configure.ac b/build/tizen/configure.ac index 5f027e6..006e192 100644 --- a/build/tizen/configure.ac +++ b/build/tizen/configure.ac @@ -30,7 +30,6 @@ AC_SUBST(DALI_TOOLKIT_VERSION) PKG_CHECK_MODULES(DALICORE, dali-core) PKG_CHECK_MODULES(DALI, dali) -PKG_CHECK_MODULES(FRIBIDI, fribidi) DALI_TOOLKIT_CFLAGS=-DPLATFORM_TIZEN @@ -57,8 +56,8 @@ AC_ARG_ENABLE([javascript], [AC_HELP_STRING([--enable-javascript], [Enable JavaScript plugin])] , [enable_javascript=$enableval], - [enable_javascript=no]) -#TODO MESH_REWORK Change default back to automatic + [enable_javascript=automatic]) + if test "x$enable_debug" = "xyes"; then DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -DDEBUG_ENABLED" @@ -90,6 +89,10 @@ else dataReadOnlyDir=${prefix}/share/dali/ fi +DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -DDALI_PROFILE_${enable_profile}" +AM_CONDITIONAL([COMMON_PROFILE], [test x$enable_profile = xCOMMON]) +AM_CONDITIONAL([MOBILE_PROFILE], [test x$enable_profile = xMOBILE]) + # v8 version 4+ requires c++11 PKG_CHECK_MODULES(V8, v8 = 3.32.7, [ pkg_check_v8=yes ], [ pkg_check_v8=no ] ) diff --git a/build/tizen/dali-toolkit/Makefile.am b/build/tizen/dali-toolkit/Makefile.am index e966482..18ed54d 100644 --- a/build/tizen/dali-toolkit/Makefile.am +++ b/build/tizen/dali-toolkit/Makefile.am @@ -18,10 +18,15 @@ toolkit_images_dir = ../../../dali-toolkit/images toolkit_sounds_dir = ../../../dali-toolkit/sounds -toolkit_styles_dir = ../../../dali-toolkit/styles toolkit_src_dir = ../../../dali-toolkit/internal public_api_src_dir = ../../../dali-toolkit/public-api +if MOBILE_PROFILE +toolkit_styles_dir = ../../../dali-toolkit/styles/mobile +else +toolkit_styles_dir = ../../../dali-toolkit/styles +endif + include ../../../dali-toolkit/images/file.list include ../../../dali-toolkit/sounds/file.list include ../../../dali-toolkit/styles/file.list @@ -99,19 +104,17 @@ publicapishadowviewdir = $(publicapicontrolsdir)/shadow-view publicapisliderdir = $(publicapicontrolsdir)/slider publicapisuperblurviewdir = $(publicapicontrolsdir)/super-blur-view publicapitableviewdir = $(publicapicontrolsdir)/table-view -publicapitextviewdir = $(publicapicontrolsdir)/text-view -publicapitextinputdir = $(publicapicontrolsdir)/text-input +publicapitextcontrolsdir = $(publicapidir)/controls/text-controls publicapitoolbardir = $(publicapicontrolsdir)/tool-bar publicapiviewdir = $(publicapicontrolsdir)/view - publicapibuilderdir = $(publicapidir)/builder publicapifocusmanagerdir = $(publicapidir)/focus-manager -publicapimarkupprocessordir = $(publicapidir)/markup-processor publicapishadereffectsdir = $(publicapidir)/shader-effects publicapibubbleeffectdir = $(publicapidir)/shader-effects/bubble-effect publicapistylingdir = $(publicapidir)/styling publicapitransitioneffectsdir = $(publicapidir)/transition-effects publicapiscriptingdir = $(publicapidir)/scripting +publicapirenderingbackenddir = $(publicapidir)/text publicapi_HEADERS = $(public_api_header_files) publicapicontrols_HEADERS = $(public_api_controls_header_files) @@ -139,17 +142,15 @@ publicapishadowview_HEADERS = $(public_api_shadow_view_header_files) publicapislider_HEADERS = $(public_api_slider_header_files) publicapisuperblurview_HEADERS = $(public_api_super_blur_view_header_files) publicapitableview_HEADERS = $(public_api_table_view_header_files) -publicapitextview_HEADERS = $(public_api_text_view_header_files) -publicapitextinput_HEADERS = $(public_api_text_input_header_files) +publicapitextcontrols_HEADERS = $(public_api_text_controls_header_files) publicapitoolbar_HEADERS = $(public_api_tool_bar_header_files) publicapiview_HEADERS = $(public_api_view_header_files) - publicapibuilder_HEADERS = $(public_api_builder_header_files) publicapifocusmanager_HEADERS = $(public_api_focus_manager_header_files) -publicapimarkupprocessor_HEADERS = $(public_api_markup_processor_header_files) publicapishadereffects_HEADERS = $(public_api_shader_effects_header_files) publicapibubbleeffect_HEADERS = $(public_api_bubble_effect_header_files) publicapistyling_HEADERS = $(public_api_styling_header_files) publicapitransitioneffects_HEADERS = $(public_api_transition_effects_header_files) publicapiscripting_HEADERS = $(public_api_scripting_header_files) +publicapirenderingbackend_HEADERS = $(public_api_rendering_backend_header_files) diff --git a/build/tizen/plugins/Makefile.am b/build/tizen/plugins/Makefile.am index bb89f6c..557c8c2 100644 --- a/build/tizen/plugins/Makefile.am +++ b/build/tizen/plugins/Makefile.am @@ -46,6 +46,7 @@ libdali_script_plugin_v8_la_CXXFLAGS = -DDALI_COMPILATION \ $(DALI_CFLAGS) \ $(DLOG_CFLAGS) \ $(script_plugin_v8_includes) \ + $(V8_CFLAGS) \ -Werror -Wall libdali_script_plugin_v8_la_LIBADD = \ diff --git a/dali-toolkit/dali-toolkit.h b/dali-toolkit/dali-toolkit.h index 8e4120f..0e705e2 100644 --- a/dali-toolkit/dali-toolkit.h +++ b/dali-toolkit/dali-toolkit.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -72,8 +73,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -81,14 +82,15 @@ #include #include -#include - #include #include +#include + #include #include #include +#include #include #include #include @@ -102,6 +104,8 @@ #include #include #include +#include +#include #include #include #include @@ -114,6 +118,8 @@ #include #include +#include + #include #include #include diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp new file mode 100644 index 0000000..853c0ae --- /dev/null +++ b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.cpp @@ -0,0 +1,836 @@ +/* + * 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. + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDE +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + const uint32_t DEFAULT_ATLAS_WIDTH( 512u ); + const uint32_t DEFAULT_ATLAS_HEIGHT( 512u ); + const uint32_t DEFAULT_BLOCK_WIDTH( 16u ); + const uint32_t DEFAULT_BLOCK_HEIGHT( 16u ); + const uint32_t SINGLE_PIXEL_PADDING( 1u ); + const uint32_t DOUBLE_PIXEL_PADDING( SINGLE_PIXEL_PADDING << 1 ); + const uint32_t FILLED_PIXEL( -1 ); + Toolkit::AtlasManager::AtlasSize EMPTY_SIZE; +} + +AtlasManager::AtlasManager() +: mAddFailPolicy( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES ), + mFilledPixel( FILLED_PIXEL ) +{ + mNewAtlasSize.mWidth = DEFAULT_ATLAS_WIDTH; + mNewAtlasSize.mHeight = DEFAULT_ATLAS_HEIGHT; + mNewAtlasSize.mBlockWidth = DEFAULT_BLOCK_WIDTH; + mNewAtlasSize.mBlockHeight = DEFAULT_BLOCK_HEIGHT; +} + +AtlasManagerPtr AtlasManager::New() +{ + AtlasManagerPtr internal = new AtlasManager(); + return internal; +} + +AtlasManager::~AtlasManager() +{ + for ( uint32_t i = 0; i < mAtlasList.size(); ++i ) + { + delete[] mAtlasList[ i ].mStripBuffer; + } +} + +Toolkit::AtlasManager::AtlasId AtlasManager::CreateAtlas( const Toolkit::AtlasManager::AtlasSize& size, Pixel::Format pixelformat ) +{ + SizeType width = size.mWidth; + SizeType height = size.mHeight; + SizeType blockWidth = size.mBlockWidth; + SizeType blockHeight = size.mBlockHeight; + + // Check to see if the atlas is large enough to hold a single block even ? + if ( blockWidth > width || blockHeight > height ) + { + DALI_LOG_ERROR("Atlas %i x %i too small. Dimensions need to be at least %ix%i\n", + width, height, blockWidth, blockHeight ); + return 0; + } + + Dali::Atlas atlas = Dali::Atlas::New( width, height, pixelformat ); + AtlasDescriptor atlasDescriptor; + atlasDescriptor.mAtlas = atlas; + atlasDescriptor.mSize = size; + atlasDescriptor.mPixelFormat = pixelformat; + std::stringstream materialLabel; + materialLabel << "Atlas Material - "; + materialLabel << mAtlasList.size(); + atlasDescriptor.mMaterial = Material::New( materialLabel.str() ); + atlasDescriptor.mMaterial.SetDiffuseTexture( atlas ); + atlasDescriptor.mNextFreeBlock = 1u; // indicate next free block will be the first ( +1 ) + + // What size do we need for this atlas' strip buffer ( assume 32bit pixel format )? + uint32_t neededStripSize =( blockWidth > blockHeight - DOUBLE_PIXEL_PADDING ? blockWidth : blockHeight - DOUBLE_PIXEL_PADDING ) << 2; + atlasDescriptor.mStripBuffer = new PixelBuffer[ neededStripSize ]; + memset( atlasDescriptor.mStripBuffer, 0, neededStripSize ); + + atlasDescriptor.mHorizontalStrip = BufferImage::New( atlasDescriptor.mStripBuffer, + blockWidth, + SINGLE_PIXEL_PADDING, + pixelformat ); + + atlasDescriptor.mVerticalStrip = BufferImage::New( atlasDescriptor.mStripBuffer, + SINGLE_PIXEL_PADDING, + blockHeight - DOUBLE_PIXEL_PADDING, + pixelformat ); + atlasDescriptor.mFilledPixelImage = BufferImage::New( reinterpret_cast< PixelBuffer* >( &mFilledPixel ), 1, 1, pixelformat ); + atlas.Upload( atlasDescriptor.mFilledPixelImage, 0, 0 ); + mAtlasList.push_back( atlasDescriptor ); + return mAtlasList.size(); +} + +void AtlasManager::SetAddPolicy( Toolkit::AtlasManager::AddFailPolicy policy ) +{ + mAddFailPolicy = policy; +} + +void AtlasManager::Add( const BufferImage& image, + Toolkit::AtlasManager::AtlasSlot& slot, + Toolkit::AtlasManager::AtlasId atlas ) +{ + // See if there's a slot in an atlas that matches the requirements of this image + // A bitmap must be sliceable into a single atlas + Pixel::Format pixelFormat = image.GetPixelFormat(); + SizeType width = image.GetWidth(); + SizeType height = image.GetHeight(); + SizeType blockArea = 0; + SizeType totalBlocks = 0; + SizeType foundAtlas = 0; + SizeType index = 0; + slot.mImageId = 0; + + AtlasSlotDescriptor desc; + + // If there is a preferred atlas then check for room in that first + if ( atlas-- ) + { + foundAtlas = CheckAtlas( atlas, width, height, pixelFormat, blockArea, totalBlocks ); + } + + // Search current atlases to see if there is a good match + + while( !foundAtlas && index < mAtlasList.size() ) + { + foundAtlas = CheckAtlas( index, width, height, pixelFormat, blockArea, totalBlocks ); + ++index; + } + + // If we can't find a suitable atlas then check the policy to determine action + if ( !foundAtlas-- ) + { + if ( Toolkit::AtlasManager::FAIL_ON_ADD_CREATES == mAddFailPolicy ) + { + SizeType newAtlas = CreateAtlas( mNewAtlasSize, pixelFormat ); + if ( !newAtlas-- ) + { + return; + } + else + { + foundAtlas = CheckAtlas( newAtlas, width, height, pixelFormat, blockArea, totalBlocks ); + } + } + + if ( Toolkit::AtlasManager::FAIL_ON_ADD_FAILS == mAddFailPolicy || !foundAtlas-- ) + { + // Haven't found an atlas for this image!!!!!! + return; + } + } + + // Work out where the blocks are we're going to use + for ( SizeType i = 0; i < blockArea; ++i ) + { + // Is there currently a next free block available ? + if ( mAtlasList[ foundAtlas ].mNextFreeBlock ) + { + // Yes, so use this for our next block + SizeType selectedBlock = mAtlasList[ foundAtlas ].mNextFreeBlock - 1u; + desc.mBlocksList.PushBack( selectedBlock ); + + // Any blocks going to be available after this one (adjust to store +1 )? + selectedBlock++; + selectedBlock++; + if ( selectedBlock > totalBlocks ) + { + // No so start trying to use free blocks list + selectedBlock = 0; + } + mAtlasList[ foundAtlas ].mNextFreeBlock = selectedBlock; + } + else + { + // Our next block must be from the free list, fetch from the start of the list + desc.mBlocksList.PushBack( mAtlasList[ foundAtlas ].mFreeBlocksList[ 0 ] ); + mAtlasList[ foundAtlas ].mFreeBlocksList.Remove( mAtlasList[ foundAtlas ].mFreeBlocksList.Begin() ); + } + } + + desc.mImageWidth = width; + desc.mImageHeight = height; + desc.mAtlasId = foundAtlas + 1u; + desc.mCount = 1u; + + // See if there's a previously freed image ID that we can assign to this new image + uint32_t imageId = 0; + for ( uint32_t i = 0; i < mImageList.size(); ++i ) + { + if ( !mImageList[ i ].mCount ) + { + imageId = i + 1u; + break; + } + } + if ( !imageId ) + { + mImageList.push_back( desc ); + slot.mImageId = mImageList.size(); + } + else + { + mImageList[ imageId - 1u ] = desc; + slot.mImageId = imageId; + } + slot.mAtlasId = foundAtlas + 1u; + UploadImage( image, desc ); +} + +AtlasManager::SizeType AtlasManager::CheckAtlas( SizeType atlas, + SizeType width, + SizeType height, + Pixel::Format pixelFormat, + SizeType& blockArea, + SizeType& totalBlocks ) +{ + if ( pixelFormat == mAtlasList[ atlas ].mPixelFormat ) + { + // Check to see if there are any unused blocks in this atlas to accomodate our image + SizeType blocksInX = mAtlasList[ atlas ].mSize.mWidth / mAtlasList[ atlas ].mSize.mBlockWidth; + SizeType blocksInY = mAtlasList[ atlas ].mSize.mHeight / mAtlasList[ atlas ].mSize.mBlockHeight; + totalBlocks = blocksInX * blocksInY; + SizeType blocksFree = mAtlasList[ atlas ].mNextFreeBlock ? + totalBlocks - mAtlasList[ atlas ].mNextFreeBlock + 1u : + mAtlasList[ atlas ].mFreeBlocksList.Size(); + + // Check to see if the image will fit in these blocks, if not we'll need to create a new atlas + if ( blocksFree + && width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockWidth + && height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mBlockHeight ) + { + blockArea = 1u; + return ( atlas + 1u ); + } + } + return 0; +} + +void AtlasManager::CreateMesh( SizeType atlas, + SizeType imageWidth, + SizeType imageHeight, + const Vector2& position, + SizeType widthInBlocks, + SizeType heightInBlocks, + Dali::MeshData& meshData, + AtlasSlotDescriptor& desc ) +{ + Dali::MeshData::Vertex vertex; + Dali::MeshData::VertexContainer vertices; + Dali::MeshData::FaceIndices faces; + Dali::MeshData::FaceIndex faceIndex = 0; + meshData.SetHasNormals( false ); + meshData.SetHasColor( true ); + meshData.SetHasTextureCoords( true ); + + SizeType blockWidth = mAtlasList[ atlas ].mSize.mBlockWidth; + SizeType blockHeight = mAtlasList[ atlas ].mSize.mBlockHeight; + + float vertexBlockWidth = static_cast< float >( blockWidth ); + float vertexBlockHeight = static_cast< float >( blockHeight ); + + SizeType width = mAtlasList[ atlas ].mSize.mWidth; + SizeType height = mAtlasList[ atlas ].mSize.mHeight; + + SizeType atlasWidthInBlocks = width / blockWidth; + + // Get the normalized size of a texel in both directions + // TODO when texture resizing and passing texture size via uniforms is available, + // we will encode pixel positions into the vertex data rather than normalized + // meaning that geometry needn't be changed on an atlas resize + float texelX = 1.0f / static_cast< float >( width ); + float texelY = 1.0f / static_cast< float >( height ); + + // Get the normalized size of a block in texels + float texelBlockWidth = texelX * vertexBlockWidth; + float texelBlockHeight = texelY * vertexBlockHeight; + + // Get partial block space + float vertexEdgeWidth = static_cast< float >( imageWidth % blockWidth ); + float vertexEdgeHeight = static_cast< float >( imageHeight % blockHeight ); + + // And in texels + float texelEdgeWidth = vertexEdgeWidth * texelX; + float texelEdgeHeight = vertexEdgeHeight * texelY; + + // Block by block create the two triangles for the quad + SizeType blockIndex = 0; + float ndcWidth; + float ndcHeight; + float ndcVWidth; + float ndcVHeight; + + Vector2 topLeft = position; + + for ( SizeType y = 0; y < heightInBlocks; ++y ) + { + + float currentX = position.x; + + if ( ( heightInBlocks - 1u ) == y && vertexEdgeHeight > 0.0f ) + { + ndcHeight = texelEdgeHeight; + ndcVHeight = vertexEdgeHeight; + } + else + { + ndcHeight = texelBlockHeight; + ndcVHeight = vertexBlockHeight; + } + + for ( SizeType x = 0; x < widthInBlocks; ++x ) + { + SizeType block = desc.mBlocksList[ blockIndex++ ]; + + float fBlockX = texelBlockWidth * static_cast< float >( block % atlasWidthInBlocks ); + float fBlockY = texelBlockHeight * static_cast< float >( block / atlasWidthInBlocks ); + + // Add on texture filtering compensation + fBlockX += texelX; + fBlockY += texelY; + + if ( ( widthInBlocks - 1u ) == x && vertexEdgeWidth > 0.0f ) + { + ndcWidth = texelEdgeWidth; + ndcVWidth = vertexEdgeWidth; + } + else + { + ndcWidth = texelBlockWidth; + ndcVWidth = vertexBlockWidth; + } + + // Top left + vertex.x = topLeft.x; + vertex.y = topLeft.y; + vertex.z = 0.0f; + vertex.u = fBlockX; + vertex.v = fBlockY; + + vertices.push_back( vertex ); + + // Top Right + vertex.x = topLeft.x + ndcVWidth; + vertex.y = topLeft.y; + vertex.z = 0.0f; + vertex.u = fBlockX + ndcWidth; + vertex.v = fBlockY; + + vertices.push_back( vertex ); + + // Bottom Left + vertex.x = topLeft.x; + vertex.y = topLeft.y + ndcVHeight; + vertex.z = 0.0f; + vertex.u = fBlockX; + vertex.v = fBlockY + ndcHeight; + + vertices.push_back( vertex ); + + // Bottom Right + topLeft.x += ndcVWidth; + vertex.x = topLeft.x; + vertex.y = topLeft.y + ndcVHeight; + vertex.z = 0.0f; + vertex.u = fBlockX + ndcWidth; + vertex.v = fBlockY + ndcHeight; + + vertices.push_back( vertex ); + + // Six indices in counter clockwise winding + faces.push_back( faceIndex + 1u ); + faces.push_back( faceIndex ); + faces.push_back( faceIndex + 2u ); + faces.push_back( faceIndex + 2u ); + faces.push_back( faceIndex + 3u ); + faces.push_back( faceIndex + 1u ); + faceIndex += 4; + } + + // Move down a row + topLeft.x = currentX; + topLeft.y += vertexBlockHeight; + } + + // If there's only one block then skip this next vertex optimisation + if ( widthInBlocks * heightInBlocks > 1 ) + { + Dali::MeshData::VertexContainer optimizedVertices; + OptimizeVertices( vertices, faces, optimizedVertices ); + meshData.SetVertices( optimizedVertices ); + } + else + { + meshData.SetVertices( vertices ); + } + + meshData.SetFaceIndices( faces ); + meshData.SetMaterial( mAtlasList[ atlas ].mMaterial ); +} + +void AtlasManager::PrintMeshData( const MeshData& meshData ) +{ + std::cout << "\nMesh Data for Image: VertexCount = " << meshData.GetVertexCount(); + std::cout << ", Triangles = " << meshData.GetFaceCount() << std::endl; + + Dali::MeshData::VertexContainer vertices = meshData.GetVertices(); + Dali::MeshData::FaceIndices faces = meshData.GetFaces(); + + for ( SizeType v = 0; v < vertices.size(); ++v ) + { + std::cout << " Vertex(" << v << ") x = " << vertices[v].x << ", "; + std::cout << "y = " << vertices[v].y << ", " << "z = " << vertices[v].z << ", "; + std::cout << "u = " << vertices[v].u << ", " << "v = " << vertices[v].v << std::endl; + } + + std::cout << "\n Indices: "; + for ( SizeType i = 0; i < faces.size(); ++i ) + { + std::cout << " " << faces[ i ]; + } + std::cout << std::endl; +} + +void AtlasManager::OptimizeVertices( const MeshData::VertexContainer& in, + MeshData::FaceIndices& faces, + MeshData::VertexContainer& out ) +{ + unsigned short vertexIndex = 0; + + // We could check to see if blocks are next to each other, but it's probably just as quick to compare verts + for ( SizeType i = 0; i < faces.size(); ++i ) + { + // Fetch a vertex, has it already been assigned? + bool foundVertex = false; + Dali::MeshData::Vertex v = in[ faces [ i ] ]; + for ( SizeType j = 0; j < vertexIndex; ++j ) + { + if ( v.x == out[ j ].x && v.y == out[ j ].y && v.z == out[ j ].z && + v.u == out[ j ].u && v.v == out[ j ].v && v.nX == out[ j ].nX && + v.nY == out[ j ].nY && v.nZ == out[ j ].nZ ) + { + // Yes, so store this down as the vertex to use + faces[ i ] = j; + foundVertex = true; + break; + } + } + + // Did we find a vertex ? + if ( !foundVertex ) + { + // Add a new vertex + faces[ i ] = vertexIndex++; + out.push_back( v ); + } + } +} + +void AtlasManager::StitchMesh( MeshData& first, + const MeshData& second, + bool optimize ) +{ + + // Would be much quicker to be able to get a non-const reference to these containers and update in situ + MeshData::VertexContainer v1 = first.GetVertices(); + MeshData::VertexContainer v2 = second.GetVertices(); + MeshData::FaceIndices f1 = first.GetFaces(); + MeshData::FaceIndices f2 = second.GetFaces(); + + uint32_t vc1 = first.GetVertexCount(); + uint32_t vc2 = second.GetVertexCount(); + + for ( uint32_t v = 0; v < vc2; ++v ) + { + v1.push_back( v2[ v ] ); + } + + for ( uint32_t f = 0; f < f2.size(); ++f ) + { + f1.push_back( f2[ f ] + vc1 ); + } + + if ( optimize ) + { + MeshData::VertexContainer optimizedVertices; + OptimizeVertices( v1, f1, optimizedVertices ); + first.SetVertices( optimizedVertices ); + } + else + { + first.SetVertices( v1 ); + } + + first.SetFaceIndices( f1 ); +} + +void AtlasManager::StitchMesh( const MeshData& first, + const MeshData& second, + MeshData& out, + bool optimize ) +{ + MeshData::VertexContainer v1 = first.GetVertices(); + MeshData::VertexContainer v2 = second.GetVertices(); + MeshData::FaceIndices f1 = first.GetFaces(); + MeshData::FaceIndices f2 = second.GetFaces(); + + uint32_t vc1 = first.GetVertexCount(); + uint32_t vc2 = second.GetVertexCount(); + + MeshData::VertexContainer vertices; + + MeshData::FaceIndices faces; + + MeshData::Vertex vertex; + + for ( uint32_t v = 0; v < vc1; ++v ) + { + vertices.push_back( v1[ v ] ); + } + + for ( uint32_t v = 0; v < vc2; ++v ) + { + vertices.push_back( v2[ v ] ); + } + + for ( uint32_t f = 0; f < f1.size(); ++f ) + { + faces.push_back( f1[ f ] ); + } + + for ( uint32_t f = 0; f < f2.size(); ++f ) + { + faces.push_back( f2[ f ] + vc1 ); + } + + if ( optimize ) + { + MeshData::VertexContainer optimizedVertices; + OptimizeVertices( vertices, faces, optimizedVertices ); + out.SetVertices( optimizedVertices ); + } + else + { + out.SetVertices( vertices ); + } + + out.SetMaterial( first.GetMaterial() ); + out.SetFaceIndices( faces ); +} + +void AtlasManager::UploadImage( const BufferImage& image, + const AtlasSlotDescriptor& desc ) +{ + // Get the atlas to upload the image to + SizeType atlas = desc.mAtlasId - 1u; + + // Check to see that the pixel formats are compatible + if ( image.GetPixelFormat() != mAtlasList[ atlas ].mPixelFormat ) + { + DALI_LOG_ERROR("Cannot upload an image with a different PixelFormat to the Atlas.\n"); + return; + } + + SizeType atlasBlockWidth = mAtlasList[ atlas ].mSize.mBlockWidth; + SizeType atlasBlockHeight = mAtlasList[ atlas ].mSize.mBlockHeight; + SizeType atlasWidthInBlocks = mAtlasList[ atlas ].mSize.mWidth / mAtlasList[ atlas ].mSize.mBlockWidth; + + SizeType block = desc.mBlocksList[ 0 ]; + SizeType blockX = block % atlasWidthInBlocks; + SizeType blockY = block / atlasWidthInBlocks; + SizeType blockOffsetX = blockX * atlasBlockWidth; + SizeType blockOffsetY = blockY * atlasBlockHeight; + + SizeType width = image.GetWidth(); + SizeType height = image.GetHeight(); + + // Blit image 1 pixel to the right and down into the block to compensate for texture filtering + if ( !mAtlasList[ atlas ].mAtlas.Upload( image, + blockOffsetX + SINGLE_PIXEL_PADDING, + blockOffsetY + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading image to Atlas Failed!.\n"); + } + + // If this is the first block then we need to keep the first pixel free for underline texture + if ( block ) + { + + // Blit top strip + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip, + blockOffsetX, + blockOffsetY ) ) + { + DALI_LOG_ERROR("Uploading top strip to Atlas Failed!\n"); + } + + // Blit left strip + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip, + blockOffsetX, + blockOffsetY + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading left strip to Atlas Failed!\n"); + } + } + + // Blit bottom strip + if ( blockOffsetY + height + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mHeight ) + { + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mHorizontalStrip, + blockOffsetX, + blockOffsetY + height + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading bottom strip to Atlas Failed!.\n"); + } + } + + // Blit right strip + if ( blockOffsetX + width + DOUBLE_PIXEL_PADDING <= mAtlasList[ atlas ].mSize.mWidth ) + { + if ( !mAtlasList[ atlas ].mAtlas.Upload( mAtlasList[ atlas ].mVerticalStrip, + blockOffsetX + width + SINGLE_PIXEL_PADDING, + blockOffsetY + SINGLE_PIXEL_PADDING ) ) + { + DALI_LOG_ERROR("Uploading right strip to Atlas Failed!.\n"); + } + } +} + +void AtlasManager::GenerateMeshData( ImageId id, + const Vector2& position, + MeshData& meshData ) +{ + // Read the atlas Id to use for this image + SizeType imageId = id - 1u; + SizeType atlas = mImageList[ imageId ].mAtlasId - 1u; + SizeType width = mImageList[ imageId ].mImageWidth; + SizeType height = mImageList[ imageId ].mImageHeight; + + SizeType widthInBlocks = width / mAtlasList[ atlas ].mSize.mBlockWidth; + if ( width % mAtlasList[ atlas ].mSize.mBlockWidth ) + { + widthInBlocks++; + } + SizeType heightInBlocks = height / mAtlasList[ atlas ].mSize.mBlockHeight; + if ( height % mAtlasList[ atlas ].mSize.mBlockHeight ) + { + heightInBlocks++; + } + + CreateMesh( atlas, width, height, position, widthInBlocks, heightInBlocks, meshData, mImageList[ imageId ] ); + + // Mesh created so increase the reference count + mImageList[ imageId ].mCount++; +} + +Dali::Atlas AtlasManager::GetAtlasContainer( AtlasId atlas ) const +{ + Dali::Atlas null; + if ( !atlas || atlas > mAtlasList.size( ) ) + { + + DALI_LOG_ERROR("Cannot get Atlas from AtlasID ( doesn't exist ).\n"); + return null; + } + return mAtlasList[ atlas -1u ].mAtlas; +} + +bool AtlasManager::Remove( ImageId id ) +{ + // Decrements the reference count of this image, and removes the blocks if zero. + SizeType imageId = id - 1u; + bool removed = false; + + if ( id > mImageList.size() ) + { + DALI_LOG_ERROR("Atlas was asked to free an invalid imageID: %i\n", id ); + return false; + } + + // If we attempt to free an image that is already freed then do nothing, other than log + if ( !mImageList[ imageId ].mCount ) + { + DALI_LOG_ERROR("Atlas was asked to free an imageID: %i, that has already been freed!\n", id ); + return false; + } + + if ( 2u > --mImageList[ imageId ].mCount ) + { + // 'Remove the blocks' from this image and add to the atlas' freelist + removed = true; + mImageList[ imageId ].mCount = 0; + SizeType atlas = mImageList[ imageId ].mAtlasId - 1u; + for ( uint32_t i = 0; i < mImageList[ imageId ].mBlocksList.Size(); ++i ) + { + mAtlasList[ atlas ].mFreeBlocksList.PushBack( mImageList[ imageId ].mBlocksList[ i ] ); + } + } + return removed; +} + +AtlasManager::AtlasId AtlasManager::GetAtlas( ImageId id ) const +{ + if ( id && id <= mImageList.size() ) + { + return mImageList[ id - 1u ].mAtlasId; + } + else + { + return 0; + } +} + +void AtlasManager::SetNewAtlasSize( const Toolkit::AtlasManager::AtlasSize& size ) +{ + mNewAtlasSize = size; + mNewAtlasSize.mBlockWidth += DOUBLE_PIXEL_PADDING; + mNewAtlasSize.mBlockHeight += DOUBLE_PIXEL_PADDING; +} + +const Toolkit::AtlasManager::AtlasSize& AtlasManager::GetAtlasSize( AtlasId atlas ) +{ + if ( atlas && atlas-- <= mAtlasList.size() ) + { + return mAtlasList[ atlas ].mSize; + } + return EMPTY_SIZE; +} + +AtlasManager::SizeType AtlasManager::GetFreeBlocks( AtlasId atlas ) const +{ + if ( atlas && atlas <= mAtlasList.size() ) + { + uint32_t index = atlas - 1u; + uint32_t width = mAtlasList[ index ].mSize.mWidth; + uint32_t height = mAtlasList[ index ].mSize.mHeight; + uint32_t blockWidth = mAtlasList[ index ].mSize.mBlockWidth; + uint32_t blockHeight = mAtlasList[ index ].mSize.mBlockHeight; + + SizeType widthInBlocks = width / blockWidth; + SizeType heightInBlocks = height / blockHeight; + uint32_t blockCount = widthInBlocks * heightInBlocks; + + // Check free previously unallocated blocks and any free blocks + if ( mAtlasList[ index ].mNextFreeBlock ) + { + blockCount -= mAtlasList[ index ].mNextFreeBlock -1u - mAtlasList[ index ].mFreeBlocksList.Size(); + } + else + { + blockCount = mAtlasList[ index ].mFreeBlocksList.Size(); + } + return blockCount; + } + else + { + return 0; + } +} + +AtlasManager::SizeType AtlasManager::GetAtlasCount() const +{ + return mAtlasList.size(); +} + +Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas ) +{ + if ( !atlas || atlas > mAtlasList.size( ) ) + { + + DALI_LOG_ERROR("Cannot get Atlas from AtlasID ( doesn't exist ).\n"); + return Pixel::L8; + } + return mAtlasList[ atlas -1u ].mPixelFormat; +} + +void AtlasManager::GetMetrics( Toolkit::AtlasManager::Metrics& metrics ) +{ + Toolkit::AtlasManager::AtlasMetricsEntry entry; + uint32_t textureMemoryUsed = 0; + uint32_t atlasCount = mAtlasList.size(); + metrics.mAtlasCount = atlasCount; + metrics.mAtlasMetrics.Resize(0); + + for ( uint32_t i = 0; i < atlasCount; ++i ) + { + entry.mSize = mAtlasList[ i ].mSize; + entry.mTotalBlocks = ( entry.mSize.mWidth / entry.mSize.mBlockWidth ) * ( entry.mSize.mHeight / entry.mSize.mBlockHeight ); + uint32_t reuseBlocks = mAtlasList[ i ].mFreeBlocksList.Size(); + entry.mBlocksUsed = mAtlasList[ i ].mNextFreeBlock ? mAtlasList[ i ].mNextFreeBlock - reuseBlocks - 1u: entry.mTotalBlocks - reuseBlocks; + entry.mPixelFormat = GetPixelFormat( i + 1 ); + + metrics.mAtlasMetrics.PushBack( entry ); + + uint32_t size = entry.mSize.mWidth * entry.mSize.mHeight; + if ( entry.mPixelFormat == Pixel::BGRA8888 ) + { + size <<= 2; + } + + textureMemoryUsed += size; + + } + metrics.mTextureMemoryUsed = textureMemoryUsed; +} + + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + + diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h new file mode 100644 index 0000000..ef078f8 --- /dev/null +++ b/dali-toolkit/internal/atlas-manager/atlas-manager-impl.h @@ -0,0 +1,240 @@ +#ifndef __DALI_TOOLKIT_ATLAS_MANAGER_IMPL_H__ +#define __DALI_TOOLKIT_ATLAS_MANAGER_IMPL_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 +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +class AtlasManager; + +} // namespace Toolkit + +namespace Toolkit +{ + +namespace Internal +{ + +typedef Dali::Vector< Toolkit::AtlasManager::AtlasSlot > slotContainer; + +class AtlasManager; +typedef IntrusivePtr AtlasManagerPtr; + +class AtlasManager : public Dali::BaseObject +{ +public: + + typedef uint32_t SizeType; + typedef SizeType AtlasId; + typedef SizeType ImageId; + + /** + * @brief Internal storage of atlas attributes and image upload results + */ + struct AtlasDescriptor + { + Dali::Atlas mAtlas; // atlas image + Toolkit::AtlasManager::AtlasSize mSize; // size of atlas + Pixel::Format mPixelFormat; // pixel format used by atlas + BufferImage mHorizontalStrip; // Image used to pad upload + BufferImage mVerticalStrip; // Image used to pad upload + BufferImage mFilledPixelImage; // Image used by atlas for operations such as underline + PixelBuffer* mStripBuffer; // Blank image buffer used to pad upload + Material mMaterial; // material used for atlas texture + SizeType mNextFreeBlock; // next free block will be placed here ( actually +1 ) + Dali::Vector< SizeType > mFreeBlocksList; // unless there are any previously freed blocks + }; + + struct AtlasSlotDescriptor + { + SizeType mCount; // Reference count for this slot + SizeType mImageWidth; // Width of image stored + SizeType mImageHeight; // Height of image stored + AtlasId mAtlasId; // Image is stored in this Atlas + Dali::Vector< SizeType > mBlocksList; // List of blocks within atlas used for image + }; + + AtlasManager(); + + /** + * Create a new AtlasManager + */ + static AtlasManagerPtr New(); + + virtual ~AtlasManager(); + + /** + * @copydoc: Toolkit::AtlasManager::CreateAtlas + */ + AtlasId CreateAtlas( const Toolkit::AtlasManager::AtlasSize& size, Pixel::Format pixelformat ); + + /** + * @copydoc Toolkit::AtlasManager::SetAddPolicy + */ + void SetAddPolicy( Toolkit::AtlasManager::AddFailPolicy policy ); + + /** + * @copydoc Toolkit::AtlasManager::Add + */ + void Add( const BufferImage& image, + Toolkit::AtlasManager::AtlasSlot& slot, + Toolkit::AtlasManager::AtlasId atlas ); + + /** + * @copydoc Toolkit::AtlasManager::GenerateMeshData + */ + void GenerateMeshData( ImageId id, + const Vector2& position, + MeshData& mesh ); + + /** + * @copydoc Toolkit::AtlasManager::StitchMesh + */ + void StitchMesh( MeshData& first, + const MeshData& second, + bool optimize ); + + /** + * @copydoc Toolkit::AtlasManager::StitchMesh + */ + void StitchMesh( const MeshData& first, + const MeshData& second, + MeshData& out, bool optimize ); + + /** + * @copydoc Toolkit::AtlasManager::Remove + */ + bool Remove( ImageId id ); + + /** + * @copydoc Toolkit::AtlasManager::GetAtlasContainer + */ + Dali::Atlas GetAtlasContainer( AtlasId atlas ) const; + + /** + * @copydoc Toolkit::AtlasManager::GetAtlas + */ + AtlasId GetAtlas( ImageId id ) const; + + /** + * @copydoc Toolkit::AtlasManager::SetNewAtlasSize + */ + void SetNewAtlasSize( const Toolkit::AtlasManager::AtlasSize& size ); + + /** + * @copydoc Toolkit::AtlasManager::GetAtlasSize + */ + const Toolkit::AtlasManager::AtlasSize& GetAtlasSize( AtlasId atlas ); + + /** + * @copydoc Toolkit::AtlasManager::GetBlockSize + */ + Vector2 GetBlockSize( AtlasId atlas ); + + /** + * @copydoc Toolkit::AtlasManager::GetFreeBlocks + */ + SizeType GetFreeBlocks( AtlasId atlas ) const; + + /* + * @copydoc Toolkit::AtlasManager::GetAtlasCount + */ + SizeType GetAtlasCount() const; + + /** + * @copydoc Toolkit::AtlasManager::GetPixelFormat + */ + Pixel::Format GetPixelFormat( AtlasId atlas ); + + /** + * @copydoc Toolkit::AtlasManager::GetMetrics + */ + void GetMetrics( Toolkit::AtlasManager::Metrics& metrics ); + +private: + + std::vector< AtlasDescriptor > mAtlasList; // List of atlases created + std::vector< AtlasSlotDescriptor > mImageList; // List of bitmaps store in atlases + + SizeType CheckAtlas( SizeType atlas, + SizeType width, + SizeType height, + Pixel::Format pixelFormat, + SizeType& blockArea, + SizeType& totalBlocks ); + + void CreateMesh( SizeType atlas, + SizeType imageWidth, + SizeType imageHeight, + const Vector2& position, + SizeType widthInBlocks, + SizeType heightInBlocks, + Dali::MeshData& meshData, + AtlasSlotDescriptor& desc ); + + void OptimizeVertices( const MeshData::VertexContainer& in, + MeshData::FaceIndices& faces, + MeshData::VertexContainer& out ); + + void UploadImage( const BufferImage& image, + const AtlasSlotDescriptor& desc ); + + void PrintMeshData( const MeshData& meshData ); + + Toolkit::AtlasManager::AtlasSize mNewAtlasSize; + Toolkit::AtlasManager::AddFailPolicy mAddFailPolicy; + uint32_t mFilledPixel; +}; + +} // namespace Internal + +inline const Internal::AtlasManager& GetImplementation(const Toolkit::AtlasManager& manager) +{ + DALI_ASSERT_ALWAYS( manager && "AtlasManager handle is empty" ); + + const BaseObject& handle = manager.GetBaseObject(); + + return static_cast(handle); +} + +inline Internal::AtlasManager& GetImplementation(Toolkit::AtlasManager& manager) +{ + DALI_ASSERT_ALWAYS( manager && "AtlasManager handle is empty" ); + + BaseObject& handle = manager.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + + + #endif // __DALI_TOOLKIT_ATLAS_MANAGER_IMPL_H__ \ No newline at end of file diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager.cpp b/dali-toolkit/internal/atlas-manager/atlas-manager.cpp new file mode 100644 index 0000000..e46eb1d --- /dev/null +++ b/dali-toolkit/internal/atlas-manager/atlas-manager.cpp @@ -0,0 +1,136 @@ +/* + * 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. + */ + +// CLASS HEADER +#include + + // INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +AtlasManager::AtlasManager() +{ +} + +AtlasManager::~AtlasManager() +{ +} + +AtlasManager AtlasManager::New() +{ + Internal::AtlasManagerPtr internal = Internal::AtlasManager::New(); + return AtlasManager(internal.Get()); +} + +AtlasManager::AtlasManager(Internal::AtlasManager *impl) + : BaseHandle(impl) +{ +} + +AtlasManager::AtlasId AtlasManager::CreateAtlas( const AtlasManager::AtlasSize& size, Pixel::Format pixelformat ) +{ + return GetImplementation(*this).CreateAtlas( size, pixelformat ); +} + +void AtlasManager::SetAddPolicy( AddFailPolicy policy ) +{ + GetImplementation(*this).SetAddPolicy( policy ); +} + +void AtlasManager::Add( const BufferImage& image, + AtlasManager::AtlasSlot& slot, + AtlasManager::AtlasId atlas ) +{ + GetImplementation(*this).Add( image, slot, atlas ); +} + +bool AtlasManager::Remove( ImageId id ) +{ + return GetImplementation(*this).Remove( id ); +} + +void AtlasManager::GenerateMeshData( ImageId id, + const Vector2& position, + MeshData& meshData) +{ + GetImplementation(*this).GenerateMeshData( id, + position, + meshData ); +} + +void AtlasManager::StitchMesh( MeshData& first, + const MeshData& second, + bool optimize ) +{ + GetImplementation(*this).StitchMesh( first, second, optimize ); +} + +void AtlasManager::StitchMesh( const MeshData& first, + const MeshData& second, + MeshData& out, + bool optimize ) +{ + GetImplementation(*this).StitchMesh( first, second, out, optimize ); +} + +Dali::Atlas AtlasManager::GetAtlasContainer( AtlasId atlas ) const +{ + return GetImplementation(*this).GetAtlasContainer( atlas ); +} + +AtlasManager::AtlasId AtlasManager::GetAtlas( ImageId id ) +{ + return GetImplementation(*this).GetAtlas( id ); +} + +const AtlasManager::AtlasSize& AtlasManager::GetAtlasSize( AtlasId atlas ) +{ + return GetImplementation(*this).GetAtlasSize( atlas ); +} + +AtlasManager::SizeType AtlasManager::GetFreeBlocks( AtlasId atlas ) +{ + return GetImplementation(*this).GetFreeBlocks( atlas ); +} + +void AtlasManager::SetNewAtlasSize( const AtlasSize& size ) +{ + GetImplementation(*this).SetNewAtlasSize( size ); +} + +AtlasManager::SizeType AtlasManager::GetAtlasCount() const +{ + return GetImplementation(*this).GetAtlasCount(); +} + +Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas ) +{ + return GetImplementation(*this).GetPixelFormat( atlas ); +} + +void AtlasManager::GetMetrics( Metrics& metrics ) +{ + return GetImplementation(*this).GetMetrics( metrics ); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/atlas-manager/atlas-manager.h b/dali-toolkit/internal/atlas-manager/atlas-manager.h new file mode 100644 index 0000000..5fc10d0 --- /dev/null +++ b/dali-toolkit/internal/atlas-manager/atlas-manager.h @@ -0,0 +1,383 @@ +#ifndef __DALI_TOOLKIT_ATLAS_MANAGER_H__ +#define __DALI_TOOLKIT_ATLAS_MANAGER_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 +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal DALI_INTERNAL +{ + +class AtlasManager; + +} // namespace Internal + +/** + * AtlasManager + * ------------ + * + * Creates and manages additions and removals of images from Texture Atlases + * + * The AtlasManager will match pixeltype and optimal block use to determine + * the appropriate atlas to upload an image to. + * + * A policy can be specified to determine the action the AtlasManager will carry + * out, should it not be able to add an image. This can return an error, or create + * a new atlas of pre-determined dimensions to accomodate the new image. + * + * Images are referenced by an ImageId once they have been successfully uploaded. + * + * Once an image has been successfully uploaded, Geometry can be generated by passing + * the ImageId to the GenerateMeshData method and geometry can be consolidated via + * the StitchMesh method. + * + * Images are reference counted once mesh data has been generated. An image is removed + * from the Atlas via the Remove( ImageId ) method. This unreferences the image and only + * physically removes it from the atlas once all references have been freed. + * + * If the AddPolicy is set to generate and error if an image can't be uploaded, then it + * is the applications responsibility to deal with the situation. An error will be indicated + * with an ImageId of 0. + * + * Examples using the AtlasManager + * + * Create or obtain the AtlasManager + * @code + * + * AtlasManager manager = AtlasManager::Get(); + * + * @endcode + * + * Set the AtlasManager AddPolicy + * + * @code + * + * // Tell the atlas manager to create a new atlas, if it needs to + * manager.SetAddPolicy( FAIL_ON_ADD_CREATES ); + * + * // Tell the atlas manager to return an error, if it can't add an image + * manager.SetAddPolicy( FAIL_ON_ADD_FAILS ); + * + * @endcode + * + * Simple add and removal of BufferImage to and from an atlas + * + * @code + * + * // Structure returned by AtlasManager operations + * AtlasSlot slot; + * + * // Add image to an atlas ( will be created if none suitable exists ) + * manager.Add( bitmapImage, slot ); + * + * // slot.mImage returns the imageId for the bitmap, slot.mAtlas indicates the atlasId + * // that the image was added to. The imageId is used to communicate with the AtlasManager + * uint32_t imageId = slot.mImage; + * if ( !imageId ) + * { + * // Addition has failed..... + * } + * ... + * ... + * // Done with image, so remove from atlas, if not being used elsewhere + * manager.Remove( imageId ); + * + * @endcode + * + * Create a Specific Atlas for adding BufferImages to + * + * @code + * + * // Create an RGB888 atlas of 2048x2848, with a blocksize of 128x128 + * uint32_t atlas = manager.CreateAtlas( 2048u, 2048u, 128u, 128u, Pixel::RGB888 ); + * + * // Add an image to a preferred atlas ( note not specifying atlas may still result + * // in the bitmap being added to the atlas above ) + * manager.Add( bitmapImage, slot, atlas ); + * + * @endcode + * + * Create Geometry for a previously added image + * + * @code + * + * // Top left corner of geometry to be generated + * Vector2 position( 1.0f, 1.0f ); + * + * // Geometry will end up here! + * MeshData meshData; + * manager.GenerateMeshData( imageId, position, meshData ); + * + * @endcode + * + * Generating Geometry from multiple images in the same atlas + * + * @code + * + * MeshData firstMesh; + * MeshData secondMesh; + * manager.GenerateMeshData( imageid_1, position_1, firstMesh ); + * manager.GenerateMeshData( imageid_2, position_2, secondMesh ); + * + * // Combine the two meshes. Passing MESH_OPTIMIZE as an optional third parameter will remove duplicate vertices + * manager.StitchMesh( first, second ); + * + * @endcode + * + */ + +class AtlasManager : public BaseHandle +{ +public: + + typedef uint32_t SizeType; + typedef SizeType AtlasId; + typedef SizeType ImageId; + static const bool MESH_OPTIMIZE = true; + + struct AtlasSize + { + SizeType mWidth; // width of the atlas in pixels + SizeType mHeight; // height of the atlas in pixels + SizeType mBlockWidth; // width of a block in pixels + SizeType mBlockHeight; // height of a block in pixels + }; + + /** + * Metrics structures to describe Atlas Manager state + * + */ + struct AtlasMetricsEntry + { + AtlasSize mSize; // size of atlas and blocks + SizeType mBlocksUsed; // number of blocks used in the atlas + SizeType mTotalBlocks; // total blocks used by atlas + Pixel::Format mPixelFormat; // pixel format of the atlas + }; + + struct Metrics + { + SizeType mAtlasCount; // number of atlases + SizeType mTextureMemoryUsed; // texture memory used by atlases + Dali::Vector< AtlasMetricsEntry > mAtlasMetrics; // container of atlas information + }; + + /** + * Create an AtlasManager handle; this can be initialised with AtlasManager::New() + * Calling member functions with an uninitialised handle is not allowed. + */ + AtlasManager(); + + /** + * @brief Get new instance of AtlasManager object. + * + * @return A handle to the AtlasManager control. + */ + static AtlasManager New(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~AtlasManager(); + + /** + * Policy on failing to add an image + */ + enum AddFailPolicy + { + FAIL_ON_ADD_FAILS, + FAIL_ON_ADD_CREATES + }; + + /** + * @brief Container to hold result of placing texture into atlas + */ + struct AtlasSlot + { + ImageId mImageId; // Id of stored Image + AtlasId mAtlasId; // Id of Atlas containing this slot + }; + + typedef Dali::Vector< AtlasManager::AtlasSlot > slotContainer; + + /** + * @brief Create a blank atlas of specific dimensions and pixel format with a certain block size + * + * @param[in] size desired atlas dimensions + * @param[in] pixelformat format of a pixel in atlas + * + * @return atlas Id + */ + AtlasId CreateAtlas( const AtlasSize& size, Pixel::Format pixelformat = Pixel::RGBA8888 ); + + /** + * @brief Set the policy on failure to add an image to an atlas + * + * @param policy policy to carry out if add fails + */ + void SetAddPolicy( AddFailPolicy policy ); + + /** + * @brief Attempts to add an image to the most suitable atlas + * + * @details Add Policy may dictate that a new atlas is created if it can't presently be placed. + * If an add is made before an atlas is created under this policy, + * then a default size atlas will be created + * + * @param[in] image reference to a bitmapimage + * @param[out] slot result of add operation + * @param[in] atlas optional preferred atlas + */ + void Add( const BufferImage& image, + AtlasSlot& slot, + AtlasId atlas = 0 ); + + /** + * @brief Remove previously added bitmapimage from atlas + * + * @param[in] id ImageId returned in the AtlasSlot from the add operation + * + * @return if true then image has been removed from the atlas + */ + bool Remove( ImageId id ); + + /** + * @brief Generate mesh data for a previously added image + * + * @param[in] id Image Id returned in the AtlasSlot from the add operation + * @param[in] position position of the resulting mesh in model space + * @param[out] mesh Mesh Data Object to populate with mesh data + */ + void GenerateMeshData( ImageId id, + const Vector2& position, + MeshData& mesh ); + + /** + * @brief Append second mesh to the first mesh + * + * @param[in] first First mesh + * @param[in] second Second mesh + * @param[in] optimize should we optimize vertex data + */ + void StitchMesh( MeshData& first, + const MeshData& second, + bool optimize = false ); + + /** + * @brief Combine two meshes, outputting the result into a new mesh + * + * @param[in] first First mesh + * @param[in] second Second mesh + * @param[in] optimize should we optimize vertex data + * @param[out] out resulting mesh + */ + void StitchMesh( const MeshData& first, + const MeshData& second, + MeshData& out, + bool optimize = false ); + + /** + * @brief Get the BufferImage containing an atlas + * + * @param[in] atlas AtlasId returned when atlas was created + * + * @return Atlas Handle + */ + Dali::Atlas GetAtlasContainer( AtlasId atlas ) const; + + /** + * @brief Get the Id of the atlas containing an image + * + * @param[in] id ImageId + * + * @return Atlas Id + */ + AtlasId GetAtlas( ImageId id ); + /** + * @brief Get the current size of an atlas + * + * @param[in] atlas AtlasId + * + * @return AtlasSize structure for the atlas + */ + const AtlasSize& GetAtlasSize( AtlasId atlas ); + + /** + * @brief Get the number of blocks available in an atlas + * + * @param[in] atlas AtlasId + * + * @return Number of blocks free in this atlas + */ + SizeType GetFreeBlocks( AtlasId atlas ); + + /** + * @brief Sets the pixel area of any new atlas and also the individual block size + * + * @param[in] size Atlas size structure + * + * @param blockSize pixel area in atlas for a block + */ + void SetNewAtlasSize( const AtlasSize& size ); + + /** + * @brief Get the number of atlases created + * + * @return number of atlases + */ + SizeType GetAtlasCount() const; + + /** + * @brief Get the pixel format used by an atlas + * + * @param[in] atlas AtlasId + * + * @return Pixel format used by this atlas + */ + Pixel::Format GetPixelFormat( AtlasId atlas ); + + /** + * @brief Fill in a metrics structure showing current status of this Atlas Manager + * + * @param[in] metrics metrics structure to be filled + */ + void GetMetrics( Metrics& metrics ); + +private: + + explicit DALI_INTERNAL AtlasManager(Internal::AtlasManager *impl); + +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_ATLAS_MANAGER_H__ \ No newline at end of file diff --git a/dali-toolkit/internal/builder/builder-animations.cpp b/dali-toolkit/internal/builder/builder-animations.cpp index 794b62a..bea8368 100644 --- a/dali-toolkit/internal/builder/builder-animations.cpp +++ b/dali-toolkit/internal/builder/builder-animations.cpp @@ -16,6 +16,8 @@ */ // EXTERNAL INCLUDES +#include +#include #include // INTERNAL INCLUDES @@ -241,13 +243,13 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D // to allow animating shader uniforms if( propIndex == Property::INVALID_INDEX ) { - ImageActor imageActor = ImageActor::DownCast( targetHandle ); - if( imageActor ) + RenderableActor renderable = RenderableActor::DownCast( targetHandle ); + if( renderable ) { // A limitation here is that its possible that between creation of animation // and running it the ShaderEffect of the actor has been changed. // However this is a unlikely use case especially when using scripts. - if( ShaderEffect effect = imageActor.GetShaderEffect() ) + if( ShaderEffect effect = renderable.GetShaderEffect() ) { propIndex = effect.GetPropertyIndex( *property ); if(propIndex != Property::INVALID_INDEX) @@ -438,3 +440,4 @@ Animation CreateAnimation( const TreeNode& child, Builder* const builder ) } // namespace Toolkit } // namespace Dali + diff --git a/dali-toolkit/internal/builder/builder-declarations.h b/dali-toolkit/internal/builder/builder-declarations.h index 766e1bf..21c49a1 100644 --- a/dali-toolkit/internal/builder/builder-declarations.h +++ b/dali-toolkit/internal/builder/builder-declarations.h @@ -19,7 +19,12 @@ */ // EXTERNAL INCLUDES -#include +#include +#include +#include +#include +#include +#include // INTERNAL INCLUDES #include diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index 5386db9..be1993c 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -22,11 +22,16 @@ #include #include #include - +#include +#include +#include +#include +#include +#include +#include #include // INTERNAL INCLUDES - #include #include @@ -273,7 +278,7 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace // special field 'effect' references the shader effect instances if(key == "effect") { - ImageActor actor = ImageActor::DownCast(handle); + RenderableActor actor = RenderableActor::DownCast(handle); if( actor ) { OptionalString str = constant.IsString( keyChild.second ); @@ -297,7 +302,7 @@ void Builder::SetProperties( const TreeNode& node, Handle& handle, const Replace if( Property::INVALID_INDEX == index ) { - ImageActor actor = ImageActor::DownCast(handle); + RenderableActor actor = RenderableActor::DownCast(handle); if( actor ) { if( ShaderEffect effect = actor.GetShaderEffect() ) @@ -529,9 +534,6 @@ BaseHandle Builder::DoCreate( const TreeNode& root, const TreeNode& node, if( actor ) { - // TEMP: Assume all script created actors are not using size negotiation for now - actor.SetRelayoutEnabled( false ); - // add children of all the styles if( OptionalChild actors = IsChild( node, KEYNAME_ACTORS ) ) { diff --git a/dali-toolkit/internal/builder/builder-impl.h b/dali-toolkit/internal/builder/builder-impl.h index aeb3ff1..4fb7aba 100644 --- a/dali-toolkit/internal/builder/builder-impl.h +++ b/dali-toolkit/internal/builder/builder-impl.h @@ -22,8 +22,11 @@ #include #include #include +#include #include #include +#include +#include #include // INTERNAL INCLUDES diff --git a/dali-toolkit/internal/builder/builder-set-property.cpp b/dali-toolkit/internal/builder/builder-set-property.cpp index 00d6ec6..184d253 100644 --- a/dali-toolkit/internal/builder/builder-set-property.cpp +++ b/dali-toolkit/internal/builder/builder-set-property.cpp @@ -17,6 +17,7 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include diff --git a/dali-toolkit/internal/builder/builder-signals.cpp b/dali-toolkit/internal/builder/builder-signals.cpp index 0efd85b..f832721 100644 --- a/dali-toolkit/internal/builder/builder-signals.cpp +++ b/dali-toolkit/internal/builder/builder-signals.cpp @@ -16,8 +16,11 @@ */ // EXTERNAL INCLUDES -#include #include +#include +#include +#include +#include // INTERNAL INCLUDES #include diff --git a/dali-toolkit/internal/controls/bloom-view/bloom-view-impl.cpp b/dali-toolkit/internal/controls/bloom-view/bloom-view-impl.cpp index 0221785..df9b6ed 100644 --- a/dali-toolkit/internal/controls/bloom-view/bloom-view-impl.cpp +++ b/dali-toolkit/internal/controls/bloom-view/bloom-view-impl.cpp @@ -21,7 +21,6 @@ // EXTERNAL INCLUDES #include #include -#include #include #include #include @@ -459,18 +458,6 @@ void BloomView::Deactivate() } /** - * EqualToConstraintFloat - * - * f(current, property) = property - */ -struct EqualToConstraintFloat -{ - EqualToConstraintFloat(){} - - float operator()(const float current, const PropertyInput& property) {return property.GetFloat();} -}; - -/** * RecipOneMinusConstraint * * f(current, property) = property @@ -479,9 +466,9 @@ struct RecipOneMinusConstraint { RecipOneMinusConstraint(){} - float operator()(const float current, const PropertyInput& property) + void operator()( float& current, const PropertyInputContainer& inputs ) { - return 1.0f / (1.0f - property.GetFloat()); + current = 1.0f / ( 1.0f - inputs[0]->GetFloat() ); } }; @@ -502,13 +489,15 @@ void BloomView::SetupProperties() // Register a property that the user can control to change the bloom threshold mBloomThresholdPropertyIndex = self.RegisterProperty(BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT); Property::Index shaderBloomThresholdPropertyIndex = mBloomExtractShader.GetPropertyIndex(BLOOM_THRESHOLD_PROPERTY_NAME); - Constraint bloomThresholdConstraint = Constraint::New(shaderBloomThresholdPropertyIndex, Source(self, mBloomThresholdPropertyIndex), EqualToConstraintFloat()); - mBloomExtractShader.ApplyConstraint(bloomThresholdConstraint); + Constraint bloomThresholdConstraint = Constraint::New( mBloomExtractShader, shaderBloomThresholdPropertyIndex, EqualToConstraint()); + bloomThresholdConstraint.AddSource( Source(self, mBloomThresholdPropertyIndex) ); + bloomThresholdConstraint.Apply(); // precalc 1.0 / (1.0 - threshold) on CPU to save shader insns, using constraint to tie to the normal threshold property Property::Index shaderRecipOneMinusBloomThresholdPropertyIndex = mBloomExtractShader.GetPropertyIndex(RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME); - Constraint thresholdConstraint = Constraint::New( shaderRecipOneMinusBloomThresholdPropertyIndex, LocalSource(shaderBloomThresholdPropertyIndex), RecipOneMinusConstraint()); - mBloomExtractShader.ApplyConstraint(thresholdConstraint); + Constraint thresholdConstraint = Constraint::New( mBloomExtractShader, shaderRecipOneMinusBloomThresholdPropertyIndex, RecipOneMinusConstraint()); + thresholdConstraint.AddSource( LocalSource(shaderBloomThresholdPropertyIndex) ); + thresholdConstraint.Apply(); //////////////////////////////////////////// @@ -516,8 +505,9 @@ void BloomView::SetupProperties() // Register a property that the user can control to fade the blur in / out via internal GaussianBlurView object mBlurStrengthPropertyIndex = self.RegisterProperty(BLOOM_BLUR_STRENGTH_PROPERTY_NAME, BLOOM_BLUR_STRENGTH_DEFAULT); - Constraint blurStrengthConstraint = Constraint::New( mGaussianBlurView.GetBlurStrengthPropertyIndex(), Source(self, mBlurStrengthPropertyIndex), EqualToConstraintFloat()); - mGaussianBlurView.ApplyConstraint(blurStrengthConstraint); + Constraint blurStrengthConstraint = Constraint::New( mGaussianBlurView, mGaussianBlurView.GetBlurStrengthPropertyIndex(), EqualToConstraint()); + blurStrengthConstraint.AddSource( Source(self, mBlurStrengthPropertyIndex) ); + blurStrengthConstraint.Apply(); //////////////////////////////////////////// @@ -527,8 +517,9 @@ void BloomView::SetupProperties() mBloomIntensityPropertyIndex = self.RegisterProperty(BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT); mCompositeShader.SetUniform( BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT ); Property::Index shaderBloomIntensityPropertyIndex = mCompositeShader.GetPropertyIndex(BLOOM_INTENSITY_PROPERTY_NAME); - Constraint bloomIntensityConstraint = Constraint::New( shaderBloomIntensityPropertyIndex, Source(self, mBloomIntensityPropertyIndex), EqualToConstraintFloat()); - mCompositeShader.ApplyConstraint(bloomIntensityConstraint); + Constraint bloomIntensityConstraint = Constraint::New( mCompositeShader, shaderBloomIntensityPropertyIndex, EqualToConstraint()); + bloomIntensityConstraint.AddSource( Source(self, mBloomIntensityPropertyIndex) ); + bloomIntensityConstraint.Apply(); //////////////////////////////////////////// @@ -538,8 +529,9 @@ void BloomView::SetupProperties() mBloomSaturationPropertyIndex = self.RegisterProperty(BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT); mCompositeShader.SetUniform( BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT ); Property::Index shaderBloomSaturationPropertyIndex = mCompositeShader.GetPropertyIndex(BLOOM_SATURATION_PROPERTY_NAME); - Constraint bloomSaturationConstraint = Constraint::New( shaderBloomSaturationPropertyIndex, Source(self, mBloomSaturationPropertyIndex), EqualToConstraintFloat()); - mCompositeShader.ApplyConstraint(bloomSaturationConstraint); + Constraint bloomSaturationConstraint = Constraint::New( mCompositeShader, shaderBloomSaturationPropertyIndex, EqualToConstraint()); + bloomSaturationConstraint.AddSource( Source(self, mBloomSaturationPropertyIndex) ); + bloomSaturationConstraint.Apply(); //////////////////////////////////////////// @@ -549,8 +541,9 @@ void BloomView::SetupProperties() mImageIntensityPropertyIndex = self.RegisterProperty(IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT); mCompositeShader.SetUniform( IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT ); Property::Index shaderImageIntensityPropertyIndex = mCompositeShader.GetPropertyIndex(IMAGE_INTENSITY_PROPERTY_NAME); - Constraint imageIntensityConstraint = Constraint::New( shaderImageIntensityPropertyIndex, Source(self, mImageIntensityPropertyIndex), EqualToConstraintFloat()); - mCompositeShader.ApplyConstraint(imageIntensityConstraint); + Constraint imageIntensityConstraint = Constraint::New( mCompositeShader, shaderImageIntensityPropertyIndex, EqualToConstraint()); + imageIntensityConstraint.AddSource( Source(self, mImageIntensityPropertyIndex) ); + imageIntensityConstraint.Apply(); //////////////////////////////////////////// @@ -560,8 +553,9 @@ void BloomView::SetupProperties() mImageSaturationPropertyIndex = self.RegisterProperty(IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT); mCompositeShader.SetUniform( IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT ); Property::Index shaderImageSaturationPropertyIndex = mCompositeShader.GetPropertyIndex(IMAGE_SATURATION_PROPERTY_NAME); - Constraint imageSaturationConstraint = Constraint::New( shaderImageSaturationPropertyIndex, Source(self, mImageSaturationPropertyIndex), EqualToConstraintFloat()); - mCompositeShader.ApplyConstraint(imageSaturationConstraint); + Constraint imageSaturationConstraint = Constraint::New( mCompositeShader, shaderImageSaturationPropertyIndex, EqualToConstraint()); + imageSaturationConstraint.AddSource( Source(self, mImageSaturationPropertyIndex) ); + imageSaturationConstraint.Apply(); } } // namespace Internal diff --git a/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp new file mode 100644 index 0000000..1306475 --- /dev/null +++ b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2014 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. + * + */ + +// CLASS HEADER +#include "bubble-emitter-impl.h" + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ +BubbleEmitter::BubbleEmitter( const Vector2& movementArea, + Image shapeImage, + unsigned int maximumNumberOfBubble, + const Vector2& bubbleSizeRange ) +: Control( REQUIRES_TOUCH_EVENTS ), + mMovementArea( movementArea ), + mShapeImage( shapeImage ), + mTotalNumOfBubble( maximumNumberOfBubble ), + mRenderTaskRunning(false), + mBubbleSizeRange( bubbleSizeRange ), + mCurrentUniform( 0 ), + mDensity( 5 ) +{ + // Calculate how many BubbleEffect shaders are required + if( mTotalNumOfBubble>100 ) + { + mNumBubblePerShader = 100; + mNumShader = mTotalNumOfBubble / 100; + } + else + { + mNumBubblePerShader = mTotalNumOfBubble; + mNumShader = 1; + } +} + +BubbleEmitter::~BubbleEmitter() +{ +} + +Toolkit::BubbleEmitter BubbleEmitter::New( const Vector2& winSize, + Image shapeImage, + unsigned int maximumNumberOfBubble, + const Vector2& bubbleSizeRange ) +{ + // Create the implementation + IntrusivePtr internalBubbleEmitter ( new BubbleEmitter( winSize, shapeImage, + maximumNumberOfBubble,bubbleSizeRange ) ); + + // Pass ownership to Toolkit::BubbleEmitter handle + Toolkit::BubbleEmitter bubbleEmitter( *internalBubbleEmitter ); + + //Second phase of implementeation : Initialization + internalBubbleEmitter->OnInitialize(); + + return bubbleEmitter; +} + +void BubbleEmitter::OnInitialize() +{ + // Create the root actor, all the meshActor should be its children + mBubbleRoot = Actor::New(); + mBubbleRoot.SetSize(mMovementArea); + + // Prepare the frame buffer to store the color adjusted background image + mEffectImage = FrameBufferImage::New( mMovementArea.width/4.f, mMovementArea.height/4.f, Pixel::RGBA8888, Dali::Image::UNUSED ); + + // Generate the material object, which is used by all meshActors + GenMaterial(); + + mMesh.resize( mNumShader ); + mMeshActor.resize( mNumShader ); + mEffect.resize( mNumShader ); + + // Create the meshActor group and bubbleEffect group to emit bubbles following the given track, such as finger touch track. + MeshData meshData; + ConstructBubbleMesh( meshData, mNumBubblePerShader*mDensity); + for(unsigned int i=0; i < mNumShader; i++ ) + { + mMesh[i] = Mesh::New( meshData ); + mMeshActor[i] = MeshActor::New( mMesh[i] ); + mMeshActor[i].SetParentOrigin(ParentOrigin::TOP_LEFT); + mEffect[i] = BubbleEffect::New( mNumBubblePerShader ); + mEffect[i].SetEffectImage( mEffectImage ); + mEffect[i].SetMovementArea( mMovementArea ); + mMeshActor[i].SetShaderEffect( mEffect[i] ); + mBubbleRoot.Add( mMeshActor[i] ); + } + + // Create the extra meshActor and bubbleEffect to emit bubbles in totally random angle. + MeshData meshDataForNoise; + ConstructBubbleMesh( meshDataForNoise, mNumBubblePerShader); + mMeshActorForNoise = MeshActor::New( Mesh::New(meshDataForNoise) ); + mMeshActorForNoise.SetParentOrigin(ParentOrigin::TOP_LEFT); + mEffectForNoise = BubbleEffect::New( mNumBubblePerShader ); + mEffectForNoise.SetMovementArea( mMovementArea ); + mEffectForNoise.SetEffectImage( mEffectImage ); + mMeshActorForNoise.SetShaderEffect( mEffectForNoise ); + mBubbleRoot.Add( mMeshActorForNoise ); + + // Create a cameraActor for the off screen render task. + mCameraActor = CameraActor::New(mMovementArea); + mCameraActor.SetParentOrigin(ParentOrigin::CENTER); + + Stage stage = Stage::GetCurrent(); + + stage.Add(mCameraActor); + stage.ContextRegainedSignal().Connect(this, &BubbleEmitter::OnContextRegained); +} + +Actor BubbleEmitter::GetRootActor() +{ + return mBubbleRoot; +} + +void BubbleEmitter::SetBackground( Image bgImage, const Vector3& hsvDelta ) +{ + mBackgroundImage = bgImage; + mHSVDelta = hsvDelta; + + ImageActor sourceActor = ImageActor::New( bgImage ); + sourceActor.SetSize( mMovementArea ); + sourceActor.SetParentOrigin(ParentOrigin::CENTER); + Stage::GetCurrent().Add( sourceActor ); + + ColorAdjuster colorAdjuster = ColorAdjuster::New( hsvDelta, true /*ignore alpha to make bubble color always*/ ); + sourceActor.SetShaderEffect( colorAdjuster ); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.CreateTask(); + task.SetRefreshRate( RenderTask::REFRESH_ONCE ); + task.SetSourceActor( sourceActor ); + task.SetExclusive(true); + task.SetCameraActor(mCameraActor); + task.GetCameraActor().SetInvertYAxis(true); + task.SetTargetFrameBuffer( mEffectImage ); + task.FinishedSignal().Connect(this, &BubbleEmitter::OnRenderFinished); + mRenderTaskRunning = true; +} + +void BubbleEmitter::SetShapeImage( Image shapeImage ) +{ + mCustomMaterial.SetDiffuseTexture( shapeImage ); +} + +void BubbleEmitter::SetBubbleScale( float scale ) +{ + for(unsigned int i=0; i < mNumShader; i++ ) + { + mEffect[i].SetDynamicScale( scale ); + } + mEffectForNoise.SetDynamicScale( scale ); +} + +void BubbleEmitter::SetBubbleDensity( unsigned int density ) +{ + DALI_ASSERT_ALWAYS( density>0 && density<=9 && " Only densities between 1 to 9 are valid " ); + + if( density == mDensity ) + { + return; + } + else + { + mDensity = density; + MeshData meshData; + ConstructBubbleMesh( meshData, mNumBubblePerShader*mDensity); + for(unsigned int i=0; i < mNumShader; i++ ) + { + mMesh[i].UpdateMeshData(meshData); + } + } +} + +// clear the resources created for the off screen rendering +void BubbleEmitter::OnRenderFinished(RenderTask& source) +{ + mRenderTaskRunning = false; + Actor sourceActor = source.GetSourceActor(); + if( sourceActor ) + { + RenderableActor renderable = RenderableActor::DownCast( sourceActor ); + if( renderable ) + { + renderable.RemoveShaderEffect(); + } + } + + Stage stage = Stage::GetCurrent(); + stage.Remove(sourceActor); + stage.GetRenderTaskList().RemoveTask(source); +} + +void BubbleEmitter::OnContextRegained() +{ + // Context was lost, so the framebuffer has been destroyed. Re-create render task + // and trigger re-draw if not already running + if( ! mRenderTaskRunning ) + { + SetBackground( mBackgroundImage, mHSVDelta ); + } +} + +void BubbleEmitter::SetBlendMode( bool enable ) +{ + if(enable) + { + for(unsigned int i=0; i < mNumShader; i++ ) + { + // linear overlay + // TODO: if BlendColor would be public api from renderable actor, then can optimize the constant color + mMeshActor[i].SetBlendFunc(BlendingFactor::SRC_ALPHA, BlendingFactor::ONE, + BlendingFactor::ZERO, BlendingFactor::ONE); + } + mMeshActorForNoise.SetBlendFunc(BlendingFactor::SRC_ALPHA, BlendingFactor::ONE, + BlendingFactor::ZERO, BlendingFactor::ONE); + } + else + { + for(unsigned int i=0; i < mNumShader; i++ ) + { + // using default blend func + mMeshActor[i].SetBlendFunc( BlendingFactor::SRC_ALPHA, BlendingFactor::ONE_MINUS_SRC_ALPHA, + BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA ); + } + mMeshActorForNoise.SetBlendFunc( BlendingFactor::SRC_ALPHA, BlendingFactor::ONE_MINUS_SRC_ALPHA, + BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA ); + } +} + +void BubbleEmitter::EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ) +{ + unsigned int curUniform = mCurrentUniform % mNumBubblePerShader; + unsigned int groupIdx = mCurrentUniform / mNumBubblePerShader; + SetBubbleParameter( mEffect[groupIdx], curUniform, emitPosition, direction, displacement); + animation.AnimateTo( Property( mEffect[groupIdx], mEffect[groupIdx].GetPercentagePropertyName(curUniform) ), + 1.f, AlphaFunctions::Linear ); + + if( mCurrentUniform % mNumShader == 0 ) + { + unsigned int uniform = mCurrentUniform / mNumShader; + SetBubbleParameter(mEffectForNoise, uniform, emitPosition, displacement); + animation.AnimateTo( Property( mEffectForNoise, mEffectForNoise.GetPercentagePropertyName(uniform) ), + 1.f, AlphaFunctions::Linear ); + } + + mCurrentUniform = (mCurrentUniform + 1) % mTotalNumOfBubble; +} + +void BubbleEmitter::StartExplosion( float duration, float multiple ) +{ + Animation animation = Animation::New( duration ); + for(unsigned int i=0; i < mNumShader; i++ ) + { + animation.AnimateTo( Property( mEffect[i], mEffect[i].GetMagnificationPropertyName() ), + multiple, AlphaFunctions::EaseOut); + } + animation.AnimateTo( Property( mEffectForNoise, mEffectForNoise.GetMagnificationPropertyName() ), + multiple, AlphaFunctions::EaseOut); + animation.Play(); + + animation.FinishedSignal().Connect(this, &BubbleEmitter::OnExplosionFinished); +} + +void BubbleEmitter::Restore() +{ + for(unsigned int i=0; i < mNumShader; i++ ) + { + mEffect[i].ResetParameters(); + } + mEffectForNoise.ResetParameters(); +} + +void BubbleEmitter::GenMaterial() +{ + mCustomMaterial = Material::New("CustomMaterial"); + mCustomMaterial.SetOpacity(1.0f); + mCustomMaterial.SetDiffuseColor(Color::WHITE); + mCustomMaterial.SetAmbientColor(Vector4(0.0, 0.1, 0.1, 1.0)); + mCustomMaterial.SetMapU( Material::MAPPING_MODE_WRAP ); + mCustomMaterial.SetMapV( Material::MAPPING_MODE_WRAP ); + mCustomMaterial.SetDiffuseTexture( mShapeImage ); +} + +void BubbleEmitter::AddVertex(MeshData::VertexContainer& vertices, Vector3 XYZ, Vector2 UV) +{ + MeshData::Vertex meshVertex; + meshVertex.x = XYZ.x; + meshVertex.y = XYZ.y; + meshVertex.z = XYZ.z; + meshVertex.u = UV.x; + meshVertex.v = UV.y; + vertices.push_back(meshVertex); +} + +void BubbleEmitter::AddTriangle(MeshData::FaceIndices& faces, +size_t v0, size_t v1, size_t v2) +{ + faces.push_back(v0); + faces.push_back(v1); + faces.push_back(v2); +} + +void BubbleEmitter::ConstructBubbleMesh( MeshData& meshData, unsigned int numOfBubble) +{ + MeshData::VertexContainer vertices; + MeshData::FaceIndices faces; + BoneContainer bones(0); + + for(unsigned int index = 0; index < numOfBubble; index ++) + { + float curSize = RandomRange(mBubbleSizeRange.x, mBubbleSizeRange.y); + if(rand()%100 < 1) + { + curSize *= 2.f; + } + float depth = static_cast( index ); + AddVertex( vertices, Vector3(0.f,0.f,depth), Vector2(0.f,0.f) ); + AddVertex( vertices, Vector3(0.f,curSize,depth), Vector2( 0.f,1.f )); + AddVertex( vertices, Vector3(curSize,curSize,depth), Vector2(1.f,1.f) ); + AddVertex( vertices, Vector3(curSize,0.f,depth), Vector2(1.f,0.f) ); + + unsigned int idx = index * 4; + AddTriangle( faces, idx, idx+1, idx+2); + AddTriangle( faces, idx, idx+2, idx+3); + } + + meshData.SetData(vertices, faces, bones, mCustomMaterial); + meshData.SetHasColor(false); + meshData.SetHasTextureCoords(true); +} + +void BubbleEmitter::SetBubbleParameter( BubbleEffect& effect, unsigned int curUniform, + const Vector2& emitPosition, const Vector2& displacement ) +{ + int halfRange = displacement.x / 2; + Vector2 randomVec(rand()%static_cast(displacement.x) - halfRange, rand()%static_cast(displacement.y) - halfRange); + if(randomVec.y > 0.0f) + { + randomVec.y *= 0.33f; + } + + Vector4 startAndEndPos( emitPosition.x, emitPosition.y, emitPosition.x+randomVec.x, emitPosition.y+randomVec.y ); + effect.SetStartAndEndPosition( curUniform, startAndEndPos ); + + effect.SetPercentage( curUniform, 0.f); +} + +void BubbleEmitter::SetBubbleParameter( BubbleEffect& effect, unsigned int curUniform, + const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ) +{ + Vector2 dir(direction); + + int halfRange = displacement.x / 2; + // for the y coordinate, always negative, so bubbles always go upwards + Vector2 randomVec(rand()%static_cast(displacement.x) - halfRange, -rand()%static_cast(displacement.y)); + dir.Normalize(); + randomVec.x -= dir.x*halfRange; + randomVec.y *= 1.0f - fabsf(dir.x)*0.33f; + + if(randomVec.y > 0.0f) + { + randomVec.y *= 0.33f; + } + Vector4 startAndEndPos( emitPosition.x, emitPosition.y, emitPosition.x+randomVec.x, emitPosition.y+randomVec.y ); + effect.SetStartAndEndPosition( curUniform, startAndEndPos ); + + effect.SetPercentage( curUniform, 0.f); +} + +void BubbleEmitter::OnExplosionFinished( Animation& source ) +{ + Restore(); +} + +float BubbleEmitter::RandomRange(float f0, float f1) +{ + return f0 + (rand() & 0xfff) * (f1-f0) * (1.0f/4095.0f); +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.h b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.h new file mode 100644 index 0000000..3ae36a1 --- /dev/null +++ b/dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.h @@ -0,0 +1,257 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_BUBBLE_EMITTER_IMPL_H__ +#define __DALI_TOOLKIT_INTERNAL_BUBBLE_EMITTER_IMPL_H__ + +/* + * Copyright (c) 2014 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 +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * BubbleEmitter implementation class. + */ +class BubbleEmitter : public Control +{ +public: + + /** + * Destructor + */ + ~BubbleEmitter(); + + /** + * @copydoc Toolkit::BubbleEmitter::New + */ + static Toolkit::BubbleEmitter New( const Vector2& winSize, + Image shapeImage, + unsigned int maximumNumberOfBubble, + const Vector2& bubbleSizeRange ); + + /** + * @copydoc Toolkit::BubbleEmitter::GetRootActor + */ + Actor GetRootActor(); + + /** + * @copydoc Toolkit::BubbleEmitter::SetBackground + */ + void SetBackground( Image bgImage, const Vector3& hsvDelta ); + + /** + * @copydoc Toolkit::BubbleEmitter::SetShapeImage + */ + void SetShapeImage( Image shapeImage ); + + /** + * @copydoc Toolkit::BubbleEmiter::SetBubbleScale + */ + void SetBubbleScale( float scale ); + + /** + * @copydoc Toolkit::BubbleEmitter::SetBubbleDensity + */ + void SetBubbleDensity( unsigned int density ); + + /** + * @copydoc Toolkit::BubbleEmitter::SetBlendMode + */ + void SetBlendMode( bool enable ); + + /** + * @copydoc Toolkit::BubbleEmitter::EmitBubble + */ + void EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ); + + /** + * @copydoc Toolkit::BubbleEmitter::StartExplosion + */ + void StartExplosion( float duration, float multiple ); + + /** + * @copydoc Toolkit::BubbleEmitter::Restore + */ + void Restore(); + +private: + + /** + * Construct a new BubbleEmitter object. + * @param[in] movementArea The size of the bubble moving area + * @param[in] shapeImage The alpha channnel of this texture defines the bubble shape. + * @param[in] maximumNumberOfBubble The maximum number of bubble needed. + * @param[in] bubbleSizeRange The size range of the bubbles; x component is the minimal size, and y component is the maximum size. + */ + BubbleEmitter( const Vector2& movementArea, + Image shapeImage, + unsigned int maximumNumberOfBubble, + const Vector2& bubbleSizeRange ); + + /** + * This method is called after the CubeTransitionEffect has been initialized. + * The meshActors and BubbleEffects are created here. + */ + void OnInitialize(); + + /** + * Callback function of the finished signal of off-screen render task. + * @param[in] source The render task used to create the color adjusted background image. + */ + void OnRenderFinished(RenderTask& source); + + /** + * Callback function from Stage to tell us if the context has been regained. + */ + void OnContextRegained(); + + /** + * Generate the material object which is attached to the meshActor to describe its color, texture, texture mapping mode etc. + */ + void GenMaterial(); + + /** + * Add a vertex to the mesh data. + * @param[in] vertices The collection of vertices. + * @param[in] XYZ The vertex position coordinates. + * @param[in] UV The vertex texture coordinate. + */ + void AddVertex(MeshData::VertexContainer& vertices, Vector3 XYZ, Vector2 UV); + + /** + * Add a triangle to the mesh data. + * @param[in] faces The collection od FaceIndex items. + * @param[in] v0 The index of the first point of the triangle. + * @param[in] v1 The index of the second point of the triangle. + * @param[in] v3 The index of the first point of the triangle. + */ + void AddTriangle(MeshData::FaceIndices& faces,size_t v0, size_t v1, size_t v2); + + /** + * Create a new mesh. + * @param[in] meshData The MeshData object which encompasses all the data required to describe and render the 3D mesh. + * @param[in] numberOfBubble The triangle number in the meshData is 2*numOfBubble; two triangles for each bubble + */ + void ConstructBubbleMesh( MeshData& meshData, unsigned int numOfBubble); + + /** + * Set the uniform values to the shader effect to emit a bubble + * @param[in] effect The BubbleEffect to render the current bubble + * @param[in] curUniform The index of the uniform array in the shader + * @param[in] emitPosition The start position of the bubble movement. + * @param[in] displacement The displacement used to bound the moving distance of the bubble. + */ + void SetBubbleParameter( BubbleEffect& effect, unsigned int curUniform, + const Vector2& emitPosition, const Vector2& displacement ); + + /** + * Set the uniform values to the shader effect to emit a bubble + * @param[in] effect The BubbleEffect to render the current bubble + * @param[in] curUniform The index of the uniform array in the shader + * @param[in] emitPosition The start position of the bubble movement. + * @param[in] direction The direction used to constrain the bubble to move in an adjacent direction around it. + * @param[in] displacement The displacement used to bound the moving distance of the bubble. + */ + void SetBubbleParameter( BubbleEffect& effect, unsigned int curUniform, + const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ); + + /** + * Callback function of the explosion animation finished signal to reset the shader parameters + * @param[in] source The explosion animation. + */ + void OnExplosionFinished( Animation& source ); + + /** + * Return a random value between the given interval. + * @param[in] f0 The low bound + * @param[in] f1 The up bound + * @return A random value between the given interval + */ + float RandomRange(float f0, float f1); + +private: + + Vector2 mMovementArea; ///< The size of the bubble moving area, usually the same size as the background image actor. + Image mShapeImage; ///< The alpha channnel of this texture defines the bubble shape. + Actor mBubbleRoot; /// mMesh; ///< The mesh vector, each mesh is used to create a meshActor which applies a BubbleEffect. + std::vector mMeshActor; ///< The meshActor vector, its size is mNumShader. + MeshActor mMeshActorForNoise; ///< An Extra mesh data to emit bubbles which emit bubble in totally random angle. + Material mCustomMaterial; ///< The material object which is attached to the meshActor to describe its color, texture, texture mapping mode etc. + + std::vector mEffect; ///< The bubbleEffect vector, corresponding to the mMeshActoe vector. + BubbleEffect mEffectForNoise; ///< The extra bubbleEffect, corresponding to the mMeshActorForNoise. + + unsigned int mCurrentUniform; ///< Keep track of the uniform index for the newly emitted bubble + + Vector3 mHSVDelta; ///< The HSV difference used to adjust the background image color. + Image mBackgroundImage; ///< The original background image + FrameBufferImage mEffectImage; ///< The image stores the adjusted color of the background image.The bubbles pick color from this image. + CameraActor mCameraActor; ///< The render task views the scene from the perspective of this actor. + + unsigned int mDensity; ///< How many bubbles will emit at each time, they are controlled by same uniforms in the shader. + +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods +inline Internal::BubbleEmitter& GetImpl(Dali::Toolkit::BubbleEmitter& obj) +{ + DALI_ASSERT_ALWAYS(obj && "BubbleEmitter handle is empty"); + Dali::RefObject& handle = obj.GetImplementation(); + return static_cast(handle); +} + +inline const Internal::BubbleEmitter& GetImpl(const Dali::Toolkit::BubbleEmitter& obj) +{ + DALI_ASSERT_ALWAYS(obj && "BubbleEmitter handle is empty"); + const Dali::RefObject& handle = obj.GetImplementation(); + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif /* __DALI_TOOLKIT_INTERNAL_BUBBLE_EMITTER_IMPL_H__ */ diff --git a/dali-toolkit/internal/controls/buttons/button-impl.cpp b/dali-toolkit/internal/controls/buttons/button-impl.cpp index acf3a5a..d1f30bc 100644 --- a/dali-toolkit/internal/controls/buttons/button-impl.cpp +++ b/dali-toolkit/internal/controls/buttons/button-impl.cpp @@ -19,6 +19,7 @@ #include "button-impl.h" // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -26,7 +27,31 @@ #include // INTERNAL INCLUDES -#include +#include + +/** + * Button states and contents + * (3) mSelectedContent + * (2) mButtonContent (2) mSelectedBackgroundContent + * (1) mBackgroundContent (1) mBackgroundContent + * < unselected > ----------------------- < selected > + * | OnSelect() | + * | OnDisabled() | OnDisabled() + * | | + * < disabled > < disabled-selected > + * (2) mDisabledContent (2) mDisabledSelectedContent + * (1) mDisabledBackgroundContent (1) mDisabledBackgroundContent + * + * The drawing order of child actors is as follows. + * + * Top mLabel + * | mButtonContent / mSelectedContent / mDisabledContent / mDisabledSelectedContent + * | mSelectedBackgroundContent + * Bottom mBackgroundContent / mDisabledBackgroundContent + * + * Some of contents may be missed. + * And 2 images - fade-in image and fade-out image - in the same layer can be shown during the transition animation. Fade-in image should be above fade-out image. + */ namespace Dali { @@ -85,7 +110,8 @@ Button::Button() mNextAutoRepeatingDelay( NEXT_AUTOREPEATING_DELAY ), mAnimationTime( 0.0f ), mClickActionPerforming( false ), - mState( ButtonUp ) + mState( ButtonUp ), + mPaintState( UnselectedState ) { } @@ -101,9 +127,241 @@ void Button::SetDisabled( bool disabled ) { if( disabled != mDisabled ) { + unsigned int backgroundIndex; + unsigned int buttonIndex; + + bool animationStarted = false; + mDisabled = disabled; - OnDisabled( mDisabled ); + switch( mPaintState ) + { + case UnselectedState: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mDisabledContent ); + + if( mBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mDisabledBackgroundContent ); + + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = UnselectedDisabledTransition; + } + else + { + mPaintState = DisabledUnselectedState; + } + break; + } + case SelectedState: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mDisabledSelectedContent ); + + if( mBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mDisabledBackgroundContent ); + + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = SelectedDisabledTransition; + } + else + { + mPaintState = DisabledSelectedState; + } + break; + } + case DisabledUnselectedState: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mButtonContent ); + + if( mDisabledBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mBackgroundContent ); + + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = DisabledUnselectedTransition; + } + else + { + mPaintState = UnselectedState; + } + break; + } + case DisabledSelectedState: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mSelectedContent ); + + if( mDisabledBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mSelectedBackgroundContent ); + InsertChild( backgroundIndex, mBackgroundContent ); + + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = DisabledSelectedTransition; + } + else + { + mPaintState = SelectedState; + } + break; + } + case UnselectedSelectedTransition: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mDisabledSelectedContent ); + + if( mBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mDisabledBackgroundContent ); + + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = SelectedDisabledTransition; + } + else + { + mPaintState = DisabledSelectedState; + } + break; + } + case SelectedUnselectedTransition: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mDisabledContent ); + + if( mBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mDisabledBackgroundContent ); + + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = UnselectedDisabledTransition; + } + else + { + mPaintState = DisabledUnselectedState; + } + break; + } + case UnselectedDisabledTransition: + { + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = DisabledUnselectedTransition; + } + else + { + mPaintState = UnselectedState; + } + break; + } + case DisabledUnselectedTransition: + { + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = UnselectedDisabledTransition; + } + else + { + mPaintState = DisabledUnselectedState; + } + break; + } + case SelectedDisabledTransition: + { + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = DisabledSelectedTransition; + } + else + { + mPaintState = SelectedState; + } + break; + } + case DisabledSelectedTransition: + { + animationStarted = OnDisabled(); + + if( animationStarted ) + { + mPaintState = SelectedDisabledTransition; + } + else + { + mPaintState = DisabledSelectedState; + } + break; + } + } } } @@ -124,11 +382,7 @@ void Button::SetAutoRepeating( bool autoRepeating ) if( mSelected ) { // Emit a signal is not wanted, only change the appearance. - OnSelected( false ); - - mSelected = false; - - RelayoutRequest(); + SetSelected( false, false ); } } } @@ -180,18 +434,169 @@ void Button::SetSelected( bool selected ) { if( !mDisabled && mTogglableButton && ( selected != mSelected ) ) { - // Notifies the derived class the button has been selected. - OnSelected( selected ); + SetSelected( selected, true ); + } +} + +void Button::SetSelected( bool selected, bool emitSignal ) +{ + unsigned int buttonIndex, backgroundIndex; + bool animationStarted = false; + + mSelected = selected; + + switch( mPaintState ) + { + case UnselectedState: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mSelectedContent ); + + if( mBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mSelectedBackgroundContent ); + + // Notifies the derived class the button has been selected. + animationStarted = OnSelected(); + + if( animationStarted ) + { + mPaintState = UnselectedSelectedTransition; + } + else + { + mPaintState = SelectedState; + } + break; + } + case SelectedState: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mButtonContent ); + + // Notifies the derived class the button has been selected. + animationStarted = OnSelected(); + + if( animationStarted ) + { + mPaintState = SelectedUnselectedTransition; + } + else + { + mPaintState = UnselectedState; + } + break; + } + case UnselectedSelectedTransition: + { + // Notifies the derived class the button has been selected. + animationStarted = OnSelected(); + + if( animationStarted ) + { + mPaintState = SelectedUnselectedTransition; + } + else + { + mPaintState = UnselectedState; + } + break; + } + case SelectedUnselectedTransition: + { + // Notifies the derived class the button has been selected. + animationStarted = OnSelected(); + + if( animationStarted ) + { + mPaintState = UnselectedSelectedTransition; + } + else + { + mPaintState = SelectedState; + } + break; + } + case DisabledUnselectedTransition: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mSelectedContent ); + + if( mDisabledBackgroundContent ) + { + if( mBackgroundContent ) + { + backgroundIndex = 2; + } + else + { + backgroundIndex = 1; + } + } + else if( mBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mSelectedBackgroundContent ); + + // Notifies the derived class the button has been selected. + animationStarted = OnSelected(); + + if( animationStarted ) + { + mPaintState = UnselectedSelectedTransition; + } + else + { + mPaintState = SelectedState; + } + break; + } + case DisabledSelectedTransition: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mButtonContent ); - mSelected = selected; + // Notifies the derived class the button has been selected. + animationStarted = OnSelected(); + if( animationStarted ) + { + mPaintState = SelectedUnselectedTransition; + } + else + { + mPaintState = UnselectedState; + } + break; + } + default: + { + break; + } + } + + if( emitSignal ) + { Toolkit::Button handle( GetOwner() ); // Emit signal. mStateChangedSignal.Emit( handle ); - - RelayoutRequest(); } + + RelayoutRequest(); } bool Button::IsSelected() const @@ -211,9 +616,8 @@ float Button::GetAnimationTime() const void Button::SetLabel( const std::string& label ) { - Toolkit::TextView textView = Toolkit::TextView::New( label ); - textView.SetWidthExceedPolicy( Toolkit::TextView::ShrinkToFit ); // Make sure our text always fits inside the button - SetLabel( textView ); + Toolkit::TextLabel textLabel = Toolkit::TextLabel::New( label ); + SetLabel( textLabel ); } void Button::SetLabel( Actor label ) @@ -226,6 +630,10 @@ void Button::SetLabel( Actor label ) } mLabel = label; + mLabel.SetPosition( 0.f, 0.f ); + + // label should be the top of the button + Self().Add( mLabel ); OnLabelSet(); @@ -243,6 +651,31 @@ Actor& Button::GetLabel() return mLabel; } +void Button::SetButtonImage( Actor image ) +{ + StopAllAnimations(); + + if( mButtonContent && mButtonContent.GetParent() ) + { + Self().Remove( mButtonContent ); + } + + mButtonContent = image; + + mButtonContent.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mButtonContent.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mButtonContent.SetPosition( 0.f, 0.f ); + + if( mPaintState == UnselectedState ) + { + unsigned int index = FindChildIndex( mLabel ); + + Self().Insert( index, mButtonContent ); + } + + OnButtonImageSet(); +} + Actor Button::GetButtonImage() const { return mButtonContent; @@ -253,6 +686,31 @@ Actor& Button::GetButtonImage() return mButtonContent; } +void Button::SetSelectedImage( Actor image ) +{ + StopAllAnimations(); + + if( mSelectedContent && mSelectedContent.GetParent() ) + { + Self().Remove( mSelectedContent ); + } + + mSelectedContent = image; + + mSelectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mSelectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mSelectedContent.SetPosition( 0.f, 0.f ); + + if( mPaintState == SelectedState ) + { + unsigned int index = FindChildIndex( mLabel ); + + Self().Insert( index, mSelectedContent ); + } + + OnSelectedImageSet(); +} + Actor Button::GetSelectedImage() const { return mSelectedContent; @@ -263,6 +721,29 @@ Actor& Button::GetSelectedImage() return mSelectedContent; } +void Button::SetBackgroundImage( Actor image ) +{ + StopAllAnimations(); + + if( mBackgroundContent && mBackgroundContent.GetParent() ) + { + Self().Remove( mBackgroundContent ); + } + + mBackgroundContent = image; + + mBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mBackgroundContent.SetPosition( 0.f, 0.f ); + + if( mPaintState == UnselectedState || mPaintState == SelectedState ) + { + Self().Insert( 0, mBackgroundContent ); + } + + OnBackgroundImageSet(); +} + Actor Button::GetBackgroundImage() const { return mBackgroundContent; @@ -273,6 +754,71 @@ Actor& Button::GetBackgroundImage() return mBackgroundContent; } +void Button::SetSelectedBackgroundImage( Actor image ) +{ + StopAllAnimations(); + + if( mSelectedBackgroundContent && mSelectedBackgroundContent.GetParent() ) + { + Self().Remove( mSelectedBackgroundContent ); + } + + mSelectedBackgroundContent = image; + + mSelectedBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mSelectedBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mSelectedBackgroundContent.SetPosition( 0.f, 0.f ); + + if( mPaintState == SelectedState ) + { + if( mBackgroundContent ) + { + Self().Insert( 1, mSelectedBackgroundContent ); + } + else + { + Self().Insert( 0, mSelectedBackgroundContent ); + } + } + + OnSelectedBackgroundImageSet(); +} + +Actor Button::GetSelectedBackgroundImage() const +{ + return mSelectedBackgroundContent; +} + +Actor& Button::GetSelectedBackgroundImage() +{ + return mSelectedBackgroundContent; +} + +void Button::SetDisabledImage( Actor image ) +{ + StopAllAnimations(); + + if( mDisabledContent && mDisabledContent.GetParent() ) + { + Self().Remove( mDisabledContent ); + } + + mDisabledContent = image; + + mDisabledContent.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mDisabledContent.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mDisabledContent.SetPosition( 0.f, 0.f ); + + if( mPaintState == DisabledUnselectedState || mPaintState == DisabledSelectedState ) + { + unsigned int index = FindChildIndex( mLabel ); + + Self().Insert( index, mDisabledContent ); + } + + OnDisabledImageSet(); +} + Actor Button::GetDisabledImage() const { return mDisabledContent; @@ -283,6 +829,31 @@ Actor& Button::GetDisabledImage() return mDisabledContent; } +void Button::SetDisabledSelectedImage( Actor image ) +{ + StopAllAnimations(); + + if( mDisabledSelectedContent && mDisabledSelectedContent.GetParent() ) + { + Self().Remove( mDisabledSelectedContent ); + } + + mDisabledSelectedContent = image; + + mDisabledSelectedContent.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mDisabledSelectedContent.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mDisabledSelectedContent.SetPosition( 0.f, 0.f ); + + if( mPaintState == DisabledSelectedState ) + { + unsigned int index = FindChildIndex( mLabel ); + + Self().Insert( index, mDisabledSelectedContent ); + } + + OnDisabledSelectedImageSet(); +} + Actor Button::GetDisabledSelectedImage() const { return mDisabledSelectedContent; @@ -293,6 +864,29 @@ Actor& Button::GetDisabledSelectedImage() return mDisabledSelectedContent; } +void Button::SetDisabledBackgroundImage( Actor image ) +{ + StopAllAnimations(); + + if( mDisabledBackgroundContent && mDisabledBackgroundContent.GetParent() ) + { + Self().Remove( mDisabledBackgroundContent ); + } + + mDisabledBackgroundContent = image; + + mDisabledBackgroundContent.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mDisabledBackgroundContent.SetParentOrigin( ParentOrigin::TOP_LEFT ); + mDisabledBackgroundContent.SetPosition( 0.f, 0.f ); + + if( mPaintState == DisabledUnselectedState || mPaintState == DisabledSelectedState ) + { + Self().Insert( 0, mDisabledBackgroundContent ); + } + + OnDisabledBackgroundImageSet(); +} + Actor Button::GetDisabledBackgroundImage() const { return mDisabledBackgroundContent; @@ -336,16 +930,66 @@ void Button::DoClickAction( const PropertyValueContainer& attributes ) } } +void Button::UpdatePaintTransitionState() +{ + switch( mPaintState ) + { + case UnselectedSelectedTransition: + { + RemoveChild( mButtonContent ); + mPaintState = SelectedState; + break; + } + case SelectedUnselectedTransition: + { + RemoveChild( mSelectedBackgroundContent ); + RemoveChild( mSelectedContent ); + mPaintState = UnselectedState; + break; + } + case UnselectedDisabledTransition: + { + RemoveChild( mBackgroundContent ); + RemoveChild( mButtonContent ); + mPaintState = DisabledUnselectedState; + break; + } + case DisabledUnselectedTransition: + { + RemoveChild( mDisabledBackgroundContent ); + RemoveChild( mDisabledContent ); + mPaintState = UnselectedState; + break; + } + case SelectedDisabledTransition: + { + RemoveChild( mBackgroundContent ); + RemoveChild( mSelectedBackgroundContent ); + RemoveChild( mSelectedContent ); + mPaintState = DisabledSelectedState; + break; + } + case DisabledSelectedTransition: + { + RemoveChild( mDisabledBackgroundContent ); + RemoveChild( mDisabledSelectedContent ); + mPaintState = SelectedState; + break; + } + default: + { + break; + } + } +} + void Button::OnButtonStageDisconnection() { if( ButtonDown == mState ) { if( !mTogglableButton ) { - Toolkit::Button handle( GetOwner() ); - - // Notifies the derived class the button has been released. - OnReleased(); + Released(); if( mAutoRepeating ) { @@ -361,8 +1005,7 @@ void Button::OnButtonDown() { Toolkit::Button handle( GetOwner() ); - // Notifies the derived class the button has been pressed. - OnPressed(); + Pressed(); if( mAutoRepeating ) { @@ -384,9 +1027,7 @@ void Button::OnButtonUp() } else { - // Notifies the derived class the button has been clicked. - OnReleased(); - OnClicked(); + Released(); if( mAutoRepeating ) { @@ -410,8 +1051,7 @@ void Button::OnTouchPointLeave() { Toolkit::Button handle( GetOwner() ); - // Notifies the derived class the button has been released. - OnReleased(); + Released(); if( mAutoRepeating ) { @@ -555,6 +1195,7 @@ void Button::OnInitialize() OnButtonInitialize(); + self.SetDrawMode( DrawMode::OVERLAY ); self.SetKeyboardFocusable( true ); } @@ -565,6 +1206,12 @@ void Button::OnActivated() DoClickAction( attributes ); } +void Button::OnControlStageDisconnection() +{ + OnButtonStageDisconnection(); // Notification for derived classes. + mState = ButtonUp; +} + void Button::OnTap(Actor actor, const TapGesture& tap) { // Do nothing. @@ -585,10 +1232,9 @@ bool Button::AutoRepeatingSlot() // Restart the autorepeat timer. SetUpTimer( mNextAutoRepeatingDelay ); - Toolkit::Button handle( GetOwner() ); + Pressed(); - // Notifies the derived class the button has been pressed. - OnPressed(); + Toolkit::Button handle( GetOwner() ); //Emit signal. consumed = mReleasedSignal.Emit( handle ); @@ -599,10 +1245,165 @@ bool Button::AutoRepeatingSlot() return consumed; } -void Button::OnControlStageDisconnection() +void Button::Pressed() { - OnButtonStageDisconnection(); // Notification for derived classes. - mState = ButtonUp; + unsigned int buttonIndex, backgroundIndex; + bool animationStarted = false; + + switch( mPaintState ) + { + case UnselectedState: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mSelectedContent ); + + if( mBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mSelectedBackgroundContent ); + + // Notifies the derived class the button has been pressed. + animationStarted = OnPressed(); + + if( animationStarted ) + { + mPaintState = UnselectedSelectedTransition; + } + else + { + mPaintState = SelectedState; + } + break; + } + case SelectedUnselectedTransition: + { + // Notifies the derived class the button has been pressed. + animationStarted = OnPressed(); + + if( animationStarted ) + { + mPaintState = UnselectedSelectedTransition; + } + else + { + mPaintState = SelectedState; + } + break; + } + case DisabledUnselectedTransition: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mSelectedContent ); + + if( mDisabledBackgroundContent ) + { + if( mBackgroundContent ) + { + backgroundIndex = 2; + } + else + { + backgroundIndex = 1; + } + } + else if( mBackgroundContent ) + { + backgroundIndex = 1; + } + else + { + backgroundIndex = 0; + } + + InsertChild( backgroundIndex, mSelectedBackgroundContent ); + + // Notifies the derived class the button has been pressed. + animationStarted = OnPressed(); + + if( animationStarted ) + { + mPaintState = UnselectedSelectedTransition; + } + else + { + mPaintState = SelectedState; + } + break; + } + default: + break; + } +} + +void Button::Released() +{ + unsigned int buttonIndex; + bool animationStarted = false; + + switch( mPaintState ) + { + case SelectedState: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mButtonContent ); + + // Notifies the derived class the button has been released. + animationStarted = OnReleased(); + + if( animationStarted ) + { + mPaintState = SelectedUnselectedTransition; + } + else + { + mPaintState = UnselectedState; + } + break; + } + case UnselectedSelectedTransition: + { + // Notifies the derived class the button has been released. + animationStarted = OnReleased(); + + if( animationStarted ) + { + mPaintState = SelectedUnselectedTransition; + } + else + { + mPaintState = UnselectedState; + } + break; + } + case DisabledSelectedTransition: + { + buttonIndex = FindChildIndex( mLabel ); + InsertChild( buttonIndex, mButtonContent ); + + // Notifies the derived class the button has been released. + animationStarted = OnReleased(); + + if( animationStarted ) + { + mPaintState = SelectedUnselectedTransition; + } + else + { + mPaintState = UnselectedState; + } + break; + } + default: + { + break; + } + } } Button::ButtonState Button::GetState() @@ -610,6 +1411,44 @@ Button::ButtonState Button::GetState() return mState; } +Button::PaintState Button::GetPaintState() +{ + return mPaintState; +} + +void Button::InsertChild( unsigned int index, Actor& actor ) +{ + if( actor ) + { + Self().Insert( index, actor); + } +} + +void Button::RemoveChild( Actor& actor ) +{ + if( actor && actor.GetParent() ) + { + Self().Remove( actor ); + } +} + +unsigned int Button::FindChildIndex( Actor& actor ) +{ + Actor self = Self(); + unsigned int childrenNum = self.GetChildCount(); + + for( unsigned int i = 0; i < childrenNum; i++ ) + { + Actor child = self.GetChildAt( i ); + if( child == actor ) + { + return i; + } + } + + return childrenNum; +} + void Button::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) { Toolkit::Button button = Toolkit::Button::DownCast( Dali::BaseHandle( object ) ); diff --git a/dali-toolkit/internal/controls/buttons/button-impl.h b/dali-toolkit/internal/controls/buttons/button-impl.h index f9dee5a..5197aca 100644 --- a/dali-toolkit/internal/controls/buttons/button-impl.h +++ b/dali-toolkit/internal/controls/buttons/button-impl.h @@ -142,6 +142,11 @@ public: Actor GetLabel() const; /** + * @copydoc Dali::Toolkit::PushButton::SetButtonImage( Actor image ) + */ + void SetButtonImage( Actor image ); + + /** * @copydoc Dali::Toolkit::PushButton::GetButtonImage() */ Actor GetButtonImage() const; @@ -153,6 +158,11 @@ public: Actor& GetButtonImage(); /** + * @copydoc Dali::Toolkit::PushButton::SetSelectedImage( Actor image ) + */ + void SetSelectedImage( Actor image ); + + /** * @copydoc Dali::Toolkit::PushButton::GetSelectedImage() */ Actor GetSelectedImage() const; @@ -164,6 +174,11 @@ public: Actor& GetSelectedImage(); /** + * @copydoc Dali::Toolkit::PushButton::SetBackgroundImage( Actor image ) + */ + void SetBackgroundImage( Actor image ); + + /** * @copydoc Dali::Toolkit::PushButton::GetBackgroundImage() */ Actor GetBackgroundImage() const; @@ -175,6 +190,27 @@ public: Actor& GetBackgroundImage(); /** + * @copydoc Dali::Toolkit::PushButton::SetSelectedBackgroundImage( Actor image ) + */ + void SetSelectedBackgroundImage( Actor image ); + + /** + * @copydoc Dali::Toolkit::PushButton::GetSelectedBackgroundImage() + */ + Actor GetSelectedBackgroundImage() const; + + /** + * Internal use only. + * @return A reference to the selected background image. + */ + Actor& GetSelectedBackgroundImage(); + + /** + * @copydoc Dali::Toolkit::PushButton::SetDisabledImage( Actor image ) + */ + void SetDisabledImage( Actor image ); + + /** * @copydoc Dali::Toolkit::PushButton::GetDisabledImage() */ Actor GetDisabledImage() const; @@ -186,6 +222,11 @@ public: Actor& GetDisabledImage(); /** + * @copydoc Dali::Toolkit::CheckBoxButton::SetDisabledSelectedImage( Actor image ) + */ + void SetDisabledSelectedImage( Actor image ); + + /** * @copydoc Dali::Toolkit::CheckBoxButton::GetDisabledSelectedImage() */ Actor GetDisabledSelectedImage() const; @@ -197,6 +238,11 @@ public: Actor& GetDisabledSelectedImage(); /** + * @copydoc Dali::Toolkit::PushButton::SetDisabledBackgroundImage( Actor image ) + */ + void SetDisabledBackgroundImage( Actor image ); + + /** * @copydoc Dali::Toolkit::PushButton::GetDisabledBackgroundImage() */ Actor GetDisabledBackgroundImage() const; @@ -216,57 +262,71 @@ public: */ static bool DoAction( BaseObject* object, const std::string& actionName, const PropertyValueContainer& attributes ); +protected: + /** - * @copydoc Dali::Toolkit::PushButton::SetButtonImage( Actor image ) + * @return A reference to the label actor. */ - virtual void SetButtonImage( Actor image ) {} + Actor& GetLabel(); /** - * @copydoc Dali::Toolkit::PushButton::SetSelectedImage( Actor image ) + * It changes the transition state of the push button. */ - virtual void SetSelectedImage( Actor image ) {} + void UpdatePaintTransitionState(); + +private: /** - * @copydoc Dali::Toolkit::PushButton::SetBackgroundImage( Actor image ) + * Perform the click action to click the button. + * @param[in] attributes The attributes to perfrom this action. */ - virtual void SetBackgroundImage( Actor image ) {} + void DoClickAction( const PropertyValueContainer& attributes ); /** - * @copydoc Dali::Toolkit::PushButton::SetDisabledImage( Actor image ) + * This method is called after the button initialization. + * Could be reimplemented in subclasses to provide specific behaviour. */ - virtual void SetDisabledImage( Actor image ) {} + virtual void OnButtonInitialize() { } /** - * @copydoc Dali::Toolkit::CheckBoxButton::SetDisabledSelectedImage( Actor image ) + * This method is called when the label is set. */ - virtual void SetDisabledSelectedImage( Actor image ) {} + virtual void OnLabelSet() {} /** - * @copydoc Dali::Toolkit::PushButton::SetDisabledBackgroundImage( Actor image ) + * This method is called when the button image is set */ - virtual void SetDisabledBackgroundImage( Actor image ) {} + virtual void OnButtonImageSet() {} -protected: + /** + * This method is called when the selected image is set + */ + virtual void OnSelectedImageSet() {} /** - * Internal use only. - * @return A reference to the label actor. + * This method is called when the background image is set */ - Actor& GetLabel(); + virtual void OnBackgroundImageSet() {} -private: + /** + * This method is called when the selected background image is set + */ + virtual void OnSelectedBackgroundImageSet() {} /** - * Perform the click action to click the button. - * @param[in] attributes The attributes to perfrom this action. + * This method is called when the disabled button image is set */ - void DoClickAction( const PropertyValueContainer& attributes ); + virtual void OnDisabledImageSet() {} /** - * This method is called after the button initialization. - * Could be reimplemented in subclasses to provide specific behaviour. + * This method is called when the disabled selected image is set */ - virtual void OnButtonInitialize() { } + virtual void OnDisabledSelectedImageSet() {} + + /** + * This method is called when the disabled background image is set + */ + virtual void OnDisabledBackgroundImageSet() {} /** * This method is called from the OnTouchEvent method when the button is down. @@ -300,34 +360,33 @@ private: virtual void OnButtonStageDisconnection(); /** - * This method is called when the label is set. - */ - virtual void OnLabelSet() {} - - /** * This method is called when the \e selected property is changed. + * @return true if the transition animation is started. */ - virtual void OnSelected( bool selected ) {} + virtual bool OnSelected() { return false; } /** * This method is called when the \e disabled property is changed. + * @return true if the transition animation is started. */ - virtual void OnDisabled( bool disabled ) {} + virtual bool OnDisabled() { return false; } /** * This method is called when the button is pressed. + * @return true if the transition animation is started. */ - virtual void OnPressed() {} + virtual bool OnPressed() { return false; } /** * This method is called when the button is released. + * @return true if the transition animation is started. */ - virtual void OnReleased() {} + virtual bool OnReleased() { return false; } /** - * This method is called when the button is clicked + * This method stops all animations */ - virtual void OnClicked() {} + virtual void StopAllAnimations() {} public: @@ -428,6 +487,23 @@ private: */ bool AutoRepeatingSlot(); + /** + * Sets the button as selected or unselected. + * @param[in] selected \e selected property value. + * @param[in] emitSignal Emit a signal if this value is \e true. + */ + void SetSelected( bool selected, bool emitSignal ); + + /** + * This method is called when the button is pressed. + */ + void Pressed(); + + /** + * This method is called when the button is released. + */ + void Released(); + protected: enum ButtonState @@ -446,7 +522,7 @@ protected: DisabledUnselectedState, ///< The button is disabled and unselected. DisabledSelectedState, ///< The button is disabled and selected. UnselectedSelectedTransition, ///< The button is in transition from unselected to selected. - SelectedUnselectedTransition, ///< The push button is in transition from selected to unselected. + SelectedUnselectedTransition, ///< The button is in transition from selected to unselected. UnselectedDisabledTransition, ///< The button is in transition from unselected to disabled. DisabledUnselectedTransition, ///< The button is in transition from disabled to unselected. SelectedDisabledTransition, ///< The button is in transition from selected to disabled. @@ -454,6 +530,23 @@ protected: }; ButtonState GetState(); + PaintState GetPaintState(); + + /** + * Inserts the actor to the button. + */ + void InsertChild( unsigned int index, Actor& actor ); + + /** + * Removes the actor from the button. + */ + void RemoveChild( Actor& actor ); + + /** + * Finds the index of the actor. + * If the actor doesn't exist, return the last index + 1. + */ + unsigned int FindChildIndex( Actor& actor ); private: @@ -478,6 +571,7 @@ private: Actor mButtonContent; ///< Stores the unselected content. Actor mSelectedContent; ///< Stores the selected content. Actor mBackgroundContent; ///< Stores the background content. + Actor mSelectedBackgroundContent; ///< Stores the selected background content. Actor mDisabledContent; ///< Stores the disabled content. Actor mDisabledSelectedContent; ///< Stores the disabled selected content. Actor mDisabledBackgroundContent; ///< Stores the disabled background content. @@ -496,6 +590,7 @@ private: bool mClickActionPerforming; ButtonState mState; ///< Stores the button state. + PaintState mPaintState; ///< Stores the paint state. }; } // namespace Internal diff --git a/dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp b/dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp index 0da7949..88e5364 100644 --- a/dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp +++ b/dali-toolkit/internal/controls/buttons/check-box-button-impl.cpp @@ -34,13 +34,9 @@ namespace Internal namespace { -const float FOREGROUND_DEPTH( 0.5f ); -const float BACKGROUND_DEPTH( 0.25f ); - +const float DISTANCE_BETWEEN_IMAGE_AND_LABEL( 5.0f ); const float ANIMATION_TIME( 0.26f ); // EFL checkbox tick time -const Vector3 DISTANCE_BETWEEN_IMAGE_AND_LABEL(5.0f, 0.0f, 0.0f); - BaseHandle Create() { return Toolkit::CheckBoxButton::New(); @@ -66,8 +62,7 @@ Dali::Toolkit::CheckBoxButton CheckBoxButton::New() } CheckBoxButton::CheckBoxButton() -: Button(), - mPaintState( UnselectedState ) +: Button() { SetTogglableButton( true ); @@ -76,162 +71,16 @@ CheckBoxButton::CheckBoxButton() CheckBoxButton::~CheckBoxButton() { - if( mCheckInAnimation ) + if( mTransitionAnimation ) { - mCheckInAnimation.Clear(); + mTransitionAnimation.Clear(); } } void CheckBoxButton::OnButtonInitialize() { // Wrap around all children - Self().SetResizePolicy( FIT_TO_CHILDREN, ALL_DIMENSIONS ); -} - -void CheckBoxButton::SetSelectedImage( Actor image ) -{ - Actor& selectedImage = GetSelectedImage(); - - switch( mPaintState ) - { - case SelectedState: - { - if( selectedImage && selectedImage.GetParent() ) - { - Self().Remove( selectedImage ); - } - - selectedImage = image; - Self().Add( selectedImage ); - break; - } - case UnselectedSelectedTransition: - { - StopCheckInAnimation(); - Self().Remove( selectedImage ); - - selectedImage = image; - Self().Add( selectedImage ); - - mPaintState = SelectedState; - break; - } - default: - { - selectedImage = image; - break; - } - } - - selectedImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - selectedImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - selectedImage.SetZ( FOREGROUND_DEPTH ); -} - -void CheckBoxButton::SetBackgroundImage( Actor image ) -{ - Actor& backgroundImage = GetBackgroundImage(); - - switch( mPaintState ) - { - case UnselectedState: // FALLTHROUGH - case SelectedState: - case UnselectedSelectedTransition: - { - if( backgroundImage && backgroundImage.GetParent() ) - { - Self().Remove( backgroundImage ); - - Actor& label = GetLabel(); - - if( label ) - { - backgroundImage.Remove( label ); - image.Add( label ); - } - } - - backgroundImage = image; - Self().Add( backgroundImage ); - break; - } - default: - { - backgroundImage = image; - break; - } - } - - backgroundImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - backgroundImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - backgroundImage.SetZ( BACKGROUND_DEPTH ); -} - -void CheckBoxButton::SetDisabledSelectedImage( Actor image ) -{ - Actor& disabledSelectedImage = GetDisabledSelectedImage(); - - switch( mPaintState ) - { - case DisabledSelectedState: - { - if( disabledSelectedImage && disabledSelectedImage.GetParent() ) - { - Self().Remove( disabledSelectedImage ); - } - - disabledSelectedImage = image; - Self().Add( disabledSelectedImage ); - break; - } - default: - { - disabledSelectedImage = image; - break; - } - } - - disabledSelectedImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - disabledSelectedImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - disabledSelectedImage.SetZ( FOREGROUND_DEPTH ); -} - -void CheckBoxButton::SetDisabledBackgroundImage( Actor image ) -{ - Actor& disabledBackgroundImage = GetDisabledBackgroundImage(); - - switch( mPaintState ) - { - case DisabledSelectedState: - case DisabledUnselectedState: - { - if( disabledBackgroundImage && disabledBackgroundImage.GetParent() ) - { - Self().Remove( disabledBackgroundImage ); - - Actor& label = GetLabel(); - - if( label ) - { - disabledBackgroundImage.Remove( label ); - image.Add( label ); - } - } - - disabledBackgroundImage = image; - Self().Add( disabledBackgroundImage ); - break; - } - default: - { - disabledBackgroundImage = image; - break; - } - } - - disabledBackgroundImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - disabledBackgroundImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - disabledBackgroundImage.SetZ( BACKGROUND_DEPTH ); + Self().SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); } void CheckBoxButton::OnLabelSet() @@ -240,171 +89,141 @@ void CheckBoxButton::OnLabelSet() if( label ) { - label.SetParentOrigin( ParentOrigin::CENTER_RIGHT ); + label.SetParentOrigin( ParentOrigin::CENTER_LEFT ); label.SetAnchorPoint( AnchorPoint::CENTER_LEFT ); - label.TranslateBy( DISTANCE_BETWEEN_IMAGE_AND_LABEL ); if( IsDisabled() && GetDisabledBackgroundImage() ) { - GetDisabledBackgroundImage().Add( label ); + label.SetX( GetDisabledBackgroundImage().GetNaturalSize().width + DISTANCE_BETWEEN_IMAGE_AND_LABEL ); } else if ( GetBackgroundImage() ) { - GetBackgroundImage().Add( label ); + label.SetX( GetBackgroundImage().GetNaturalSize().width + DISTANCE_BETWEEN_IMAGE_AND_LABEL ); } else { - Self().Add( label ); + label.SetX( DISTANCE_BETWEEN_IMAGE_AND_LABEL ); } } } -void CheckBoxButton::OnSelected( bool selected ) +bool CheckBoxButton::OnSelected() { Actor& selectedImage = GetSelectedImage(); - switch( mPaintState ) + PaintState paintState = GetPaintState(); + + switch( paintState ) { case UnselectedState: { - AddChild( selectedImage ); - StartCheckInAnimation( selectedImage ); // Animate in the check actor - - mPaintState = UnselectedSelectedTransition; + StartTransitionAnimation( selectedImage ); break; } case SelectedState: { RemoveChild( selectedImage ); - - mPaintState = UnselectedState; break; } case UnselectedSelectedTransition: { - StopCheckInAnimation(); + StopTransitionAnimation( false ); RemoveChild( selectedImage ); - - mPaintState = UnselectedState; break; } default: + { break; + } } + + if( mTransitionAnimation ) + { + return true; + } + + return false; } -void CheckBoxButton::OnDisabled( bool disabled ) +bool CheckBoxButton::OnDisabled() { Actor& backgroundImage = GetBackgroundImage(); Actor& selectedImage = GetSelectedImage(); Actor& disabledBackgroundImage = GetDisabledBackgroundImage(); Actor& disabledSelectedImage = GetDisabledSelectedImage(); - switch( mPaintState ) + PaintState paintState = GetPaintState(); + + switch( paintState ) { case UnselectedState: { - if( disabled ) - { - RemoveChild( backgroundImage ); - AddChild( disabledBackgroundImage ); - mPaintState = DisabledUnselectedState; - } + RemoveChild( backgroundImage ); break; } case SelectedState: { - if( disabled ) - { - RemoveChild( backgroundImage ); - RemoveChild( selectedImage ); - AddChild( disabledBackgroundImage ); - AddChild( disabledSelectedImage ); - - mPaintState = DisabledSelectedState; - } + RemoveChild( backgroundImage ); + RemoveChild( selectedImage ); break; } case DisabledUnselectedState: { - if( !disabled ) - { - RemoveChild( disabledBackgroundImage ); - AddChild( backgroundImage ); - - mPaintState = UnselectedState; - } + RemoveChild( disabledBackgroundImage ); break; } case DisabledSelectedState: { - if( !disabled ) - { - RemoveChild( disabledBackgroundImage ); - RemoveChild( disabledSelectedImage ); - AddChild( backgroundImage ); - AddChild( selectedImage ); - - mPaintState = SelectedState; - } + RemoveChild( disabledBackgroundImage ); + RemoveChild( disabledSelectedImage ); break; } case UnselectedSelectedTransition: { - if( disabled ) - { - StopCheckInAnimation(); - - RemoveChild( backgroundImage ); - RemoveChild( selectedImage ); - AddChild( disabledBackgroundImage ); - AddChild( disabledSelectedImage ); + StopTransitionAnimation(); - mPaintState = DisabledSelectedState; - } + RemoveChild( backgroundImage ); + RemoveChild( selectedImage ); break; } default: + { break; + } } Actor& label = GetLabel(); if( label ) { - if( label.GetParent() ) + if( IsDisabled() && disabledBackgroundImage) { - label.GetParent().Remove( label ); + label.SetX( disabledBackgroundImage.GetNaturalSize().width + DISTANCE_BETWEEN_IMAGE_AND_LABEL ); } - - if( disabled && disabledBackgroundImage) + else if( backgroundImage ) { - disabledBackgroundImage.Add( label ); + label.SetX( backgroundImage.GetNaturalSize().width + DISTANCE_BETWEEN_IMAGE_AND_LABEL ); } - else if( backgroundImage ) + else { - backgroundImage.Add( label ); + label.SetX( DISTANCE_BETWEEN_IMAGE_AND_LABEL ); } } -} -void CheckBoxButton::AddChild( Actor& actor ) -{ - if( actor ) + if( mTransitionAnimation ) { - Self().Add( actor); + return true; } + + return false; } -void CheckBoxButton::RemoveChild( Actor& actor ) +void CheckBoxButton::StopAllAnimations() { - if( actor ) - { - Self().Remove( actor ); - } + StopTransitionAnimation(); } -void CheckBoxButton::StartCheckInAnimation( Actor& actor ) +void CheckBoxButton::StartTransitionAnimation( Actor& actor ) { if( actor ) { @@ -419,47 +238,39 @@ void CheckBoxButton::StartCheckInAnimation( Actor& actor ) mTickUVEffect.SetBottomRight( Vector2( 0.0f, 1.0f ) ); - if( !mCheckInAnimation ) + if( !mTransitionAnimation ) { - mCheckInAnimation = Dali::Animation::New( GetAnimationTime() ); + mTransitionAnimation = Dali::Animation::New( GetAnimationTime() ); } // UV anim - mCheckInAnimation.AnimateTo( Property( mTickUVEffect, mTickUVEffect.GetBottomRightPropertyName() ), Vector2( 1.0f, 1.0f ) ); + mTransitionAnimation.AnimateTo( Property( mTickUVEffect, mTickUVEffect.GetBottomRightPropertyName() ), Vector2( 1.0f, 1.0f ) ); // Actor size anim - mCheckInAnimation.AnimateTo( Property( actor, Actor::Property::SCALE_X ), 1.0f ); + mTransitionAnimation.AnimateTo( Property( actor, Actor::Property::SCALE_X ), 1.0f ); - mCheckInAnimation.FinishedSignal().Connect( this, &CheckBoxButton::CheckInAnimationFinished ); - mCheckInAnimation.Play(); + mTransitionAnimation.FinishedSignal().Connect( this, &CheckBoxButton::TransitionAnimationFinished ); + mTransitionAnimation.Play(); } } -void CheckBoxButton::StopCheckInAnimation() +void CheckBoxButton::StopTransitionAnimation( bool remove ) { - if( mCheckInAnimation ) + if( mTransitionAnimation ) { - mCheckInAnimation.Clear(); - mCheckInAnimation.Reset(); + mTransitionAnimation.Clear(); + mTransitionAnimation.Reset(); } -} -void CheckBoxButton::CheckInAnimationFinished( Dali::Animation& source ) -{ - switch( mPaintState ) + if( remove ) { - case UnselectedSelectedTransition: - { - mPaintState = SelectedState; - break; - } - default: - { - break; - } + UpdatePaintTransitionState(); } +} - StopCheckInAnimation(); +void CheckBoxButton::TransitionAnimationFinished( Dali::Animation& source ) +{ + StopTransitionAnimation(); } } // namespace Internal diff --git a/dali-toolkit/internal/controls/buttons/check-box-button-impl.h b/dali-toolkit/internal/controls/buttons/check-box-button-impl.h index 47b91ae..7f55610 100644 --- a/dali-toolkit/internal/controls/buttons/check-box-button-impl.h +++ b/dali-toolkit/internal/controls/buttons/check-box-button-impl.h @@ -52,27 +52,17 @@ public: */ static Dali::Toolkit::CheckBoxButton New(); -public: // From Button - - /** - * @copydoc Toolkit::Internal::Button::SetSelectedImage( Actor image ) - */ - virtual void SetSelectedImage( Actor image ); - - /** - * @copydoc Toolkit::Internal::Button::SetBackgroundImage( Actor image ) - */ - virtual void SetBackgroundImage( Actor image ); +private: /** - * @copydoc Toolkit::Internal::Button::SetDisabledSelectedImage( Actor image ) + * Construct a new CheckBoxButton. */ - virtual void SetDisabledSelectedImage( Actor image ); + CheckBoxButton(); /** - * @copydoc Toolkit::Internal::Button::SetDisabledBackgroundImage( Actor image ) + * A reference counted object may only be deleted by calling Unreference() */ - virtual void SetDisabledBackgroundImage( Actor image ); + virtual ~CheckBoxButton(); private: // From Button @@ -90,56 +80,39 @@ private: // From Button /** * @copydoc Toolkit::Internal::Button::OnSelected() */ - virtual void OnSelected( bool selected ); + virtual bool OnSelected(); /** - * @copydoc Toolkit::Internal::Button::OnDisabled( bool disabled ) + * @copydoc Toolkit::Internal::Button::OnDisabled() */ - virtual void OnDisabled( bool disabled ); - -private: + virtual bool OnDisabled(); /** - * Construct a new CheckBoxButton. + * @copydoc Toolkit::Internal::Button::StopAllAnimations() */ - CheckBoxButton(); - - /** - * A reference counted object may only be deleted by calling Unreference() - */ - virtual ~CheckBoxButton(); + virtual void StopAllAnimations(); private: /** - * Adds the actor to the button. - */ - void AddChild( Actor& actor ); - - /** - * Removes the actor from the button. - */ - void RemoveChild( Actor& actor ); - - /** - * Adds the actor to the check in animation. - * It creates a check in animation if needed and starts the check in animation. + * Adds the actor to the transition animation. + * It creates a transition animation if needed and starts the animation. * @param[in] actor The actor. */ - void StartCheckInAnimation( Actor& actor ); + void StartTransitionAnimation( Actor& actor ); /** - * Stops the check in animation. + * Stops the transition animation. + * @param[in] remove If true, removes the fadeout actor from root. */ - void StopCheckInAnimation(); + void StopTransitionAnimation( bool remove = true ); // slots /** - * Called when the check in animation finishes. - * It changes the check button paint state. + * Called when the transition animation finishes. */ - void CheckInAnimationFinished( Dali::Animation& source ); + void TransitionAnimationFinished( Dali::Animation& source ); private: @@ -150,10 +123,8 @@ private: CheckBoxButton& operator=( const CheckBoxButton& ); private: - Animation mCheckInAnimation; ///< Animation used in the state transitions. - ImageRegionEffect mTickUVEffect; ///< ImageRegionEffect to expand the tick across - - PaintState mPaintState; ///< The paint state. + Animation mTransitionAnimation; ///< Animation used in the state transitions. + ImageRegionEffect mTickUVEffect; ///< ImageRegionEffect to expand the tick across }; } // namespace Internal diff --git a/dali-toolkit/internal/controls/buttons/push-button-impl.cpp b/dali-toolkit/internal/controls/buttons/push-button-impl.cpp index c96d56d..cf34f85 100644 --- a/dali-toolkit/internal/controls/buttons/push-button-impl.cpp +++ b/dali-toolkit/internal/controls/buttons/push-button-impl.cpp @@ -23,7 +23,7 @@ #include // INTERNAL INCLUDES -#include +#include namespace Dali { @@ -38,11 +38,6 @@ namespace { const float TEXT_PADDING = 12.0f; - -const float LABEL_DEPTH( 0.75f ); -const float FOREGROUND_DEPTH( 0.5f ); -const float BACKGROUND_DEPTH( 0.25f ); - const float ANIMATION_TIME( 0.2f ); BaseHandle Create() @@ -58,24 +53,18 @@ namespace { /** - * Find the first image actor in the actor hierarchy + * Get size of Actor if larger than given size + * @param[in] root the actor to get the size of + * @param[out] size the greater of the given size or the size of the Actor */ -ImageActor FindImageActor( Actor root ) +void SizeOfActorIfLarger( Actor root, Vector3& size ) { - ImageActor imageActor = ImageActor::DownCast( root ); - if( !imageActor && root ) + if ( root ) { - for( unsigned int i = 0, numChildren = root.GetChildCount(); i < numChildren; ++i ) - { - ImageActor childImageActor = FindImageActor( root.GetChildAt( i ) ); - if( childImageActor ) - { - return childImageActor; - } - } + // RelayoutSize retreived for Actor to use any padding set to it. + size.width = std::max( root.GetRelayoutSize( Dimension::WIDTH ), size.width ); + size.height = std::max( root.GetRelayoutSize( Dimension::HEIGHT ), size.height ); } - - return imageActor; } } // unnamed namespace @@ -97,8 +86,7 @@ Dali::Toolkit::PushButton PushButton::New() PushButton::PushButton() : Button(), - mSize(), - mPaintState( UnselectedState ) + mSize() { SetAnimationTime( ANIMATION_TIME ); } @@ -107,481 +95,170 @@ PushButton::~PushButton() { } -void PushButton::SetButtonImage( Actor image ) +void PushButton::OnButtonInitialize() { - Actor& buttonImage = GetButtonImage(); - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); - - switch( mPaintState ) - { - case UnselectedState: - { - if( buttonImage && buttonImage.GetParent() ) - { - StopFadeOutAnimation(); - FadeOutImage( Foreground, buttonImage ); - - buttonImage = image; - - FadeInImage( buttonImage, 0.0f, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - } - else - { - buttonImage = image; - Self().Insert( 0, buttonImage ); - } - break; - } - case UnselectedSelectedTransition: // FALLTHROUGH - case UnselectedDisabledTransition: - { - float opacity = 1.f; - if( fadeOutButtonImage ) - { - opacity = fadeOutButtonImage.GetCurrentOpacity(); - } - StopFadeOutAnimation(); - - // Replaces the button image. - buttonImage = image; - - Self().Insert( 0, buttonImage ); - FadeOutImage( Foreground, buttonImage, opacity ); - - StartFadeOutAnimation(); - break; - } - case SelectedUnselectedTransition: // FALLTHROUGH - case DisabledUnselectedTransition: - { - StopFadeInAnimation(); - Self().Remove( buttonImage ); - - buttonImage = image; - - FadeInImage( buttonImage, 0.0f, 0 ); - StartFadeInAnimation(); - break; - } - default: - buttonImage = image; - break; - } + // Push button requires the Leave event. + Actor self = Self(); + self.SetLeaveRequired( true ); - buttonImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - buttonImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - buttonImage.SetPosition( 0.f, 0.f, FOREGROUND_DEPTH ); - buttonImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - buttonImage.SetName( "BUTTON_IMAGE" ); + // Set resize policy to natural size so that buttons will resize to background images + self.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); } -void PushButton::SetSelectedImage( Actor image ) +void PushButton::OnLabelSet() { - Actor& selectedImage = GetSelectedImage(); - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); + Actor& label = GetLabel(); - switch( mPaintState ) + if( label ) { - case SelectedState: - { - if( selectedImage && selectedImage.GetParent() ) - { - StopFadeOutAnimation(); - FadeOutImage( Foreground, selectedImage ); - - selectedImage = image; - - FadeInImage( selectedImage, 0.0f, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - } - else - { - selectedImage = image; - Self().Insert( 0, selectedImage ); - } - break; - } - case SelectedUnselectedTransition: // FALLTHROUGH - case SelectedDisabledTransition: - { - float opacity = 1.f; - if( fadeOutButtonImage ) - { - opacity = fadeOutButtonImage.GetCurrentOpacity(); - } - StopFadeOutAnimation(); - - // Replaces the button image. - selectedImage = image; - - Self().Insert( 0, selectedImage ); - FadeOutImage( Foreground, selectedImage, opacity ); + label.SetAnchorPoint( AnchorPoint::CENTER ); + label.SetParentOrigin( ParentOrigin::CENTER ); + label.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); - StartFadeOutAnimation(); - break; - } - case UnselectedSelectedTransition: // FALLTHROUGH - case DisabledSelectedTransition: + Toolkit::TextLabel textLabel = Toolkit::TextLabel::DownCast( label ); + if( textLabel ) { - StopFadeInAnimation(); - Self().Remove( selectedImage ); - - selectedImage = image; - - FadeInImage( selectedImage, 0.0f, 0 ); - StartFadeInAnimation(); - break; + textLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + textLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + textLabel.SetProperty( Toolkit::TextLabel::Property::MULTI_LINE, true ); } - default: - selectedImage = image; - break; } - - selectedImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - selectedImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - selectedImage.SetPosition( 0.f, 0.f, FOREGROUND_DEPTH ); - selectedImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); } -void PushButton::SetBackgroundImage( Actor image ) +void PushButton::OnButtonImageSet() { - Actor& backgroundImage = GetBackgroundImage(); - Actor& fadeOutBackgroundImage = GetFadeOutBackgroundImage(); - - switch( mPaintState ) - { - case UnselectedState: // FALLTHROUGH - case SelectedState: - case UnselectedSelectedTransition: - case SelectedUnselectedTransition: - { - if( backgroundImage && backgroundImage.GetParent() ) - { - StopFadeOutAnimation(); - FadeOutImage( Background, backgroundImage ); - - backgroundImage = image; - - FadeInImage( backgroundImage, 0.0f, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - } - else - { - backgroundImage = image; - Self().Insert( 0, backgroundImage ); - } - break; - } - case UnselectedDisabledTransition: // FALLTHROUGH - case SelectedDisabledTransition: - { - float opacity = 1.f; - if( fadeOutBackgroundImage ) - { - opacity = fadeOutBackgroundImage.GetCurrentOpacity(); - } - StopFadeOutAnimation(); - - // Replaces the button image. - backgroundImage = image; - - Self().Insert( 0, backgroundImage ); - FadeOutImage( Background, backgroundImage, opacity ); - - StartFadeOutAnimation(); - break; - } - case DisabledUnselectedTransition: // FALLTHROUGH - case DisabledSelectedTransition: - { - StopFadeInAnimation(); - Self().Remove( backgroundImage ); + Actor& buttonImage = GetButtonImage(); - backgroundImage = image; + buttonImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); - FadeInImage( backgroundImage, 0.0f, 0 ); - StartFadeInAnimation(); - break; - } - default: - backgroundImage = image; - break; - } + buttonImage.RelayoutRequestTree(); - backgroundImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - backgroundImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - backgroundImage.SetPosition( 0.f, 0.f, BACKGROUND_DEPTH ); - backgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + RelayoutRequest(); } -void PushButton::SetDisabledImage( Actor image ) +void PushButton::OnSelectedImageSet() { - Actor& disabledImage = GetDisabledImage(); - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); - - switch( mPaintState ) - { - case DisabledUnselectedState: // FALLTHROUGH - case DisabledSelectedState: - { - if( disabledImage && disabledImage.GetParent() ) - { - StopFadeOutAnimation(); - FadeOutImage( Foreground, disabledImage ); - - disabledImage = image; - - FadeInImage( disabledImage, 0.0f, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - } - else - { - disabledImage = image; - Self().Add( disabledImage ); - } - break; - } - case UnselectedDisabledTransition: // FALLTHROUGH - case SelectedDisabledTransition: - { - StopFadeInAnimation(); - Self().Remove( disabledImage ); - - disabledImage = image; - - FadeInImage( disabledImage, 0.0f, 0 ); - StartFadeInAnimation(); - break; - } - case DisabledUnselectedTransition: // FALLTHROUGH - case DisabledSelectedTransition: - { - float opacity = 1.f; - if( fadeOutButtonImage ) - { - opacity = fadeOutButtonImage.GetCurrentOpacity(); - } - StopFadeOutAnimation(); - - // Replaces the button image. - disabledImage = image; + Actor& selectedImage = GetSelectedImage(); - Self().Add( disabledImage ); - FadeOutImage( Foreground, disabledImage, opacity ); + selectedImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); - StartFadeOutAnimation(); - break; - } - default: - disabledImage = image; - break; - } + selectedImage.RelayoutRequestTree(); - disabledImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - disabledImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - disabledImage.SetPosition( 0.f, 0.f, FOREGROUND_DEPTH ); - disabledImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + RelayoutRequest(); } -void PushButton::SetDisabledBackgroundImage( Actor image ) +void PushButton::OnBackgroundImageSet() { - Actor& disabledBackgroundImage = GetDisabledBackgroundImage(); - Actor& fadeOutBackgroundImage = GetFadeOutBackgroundImage(); - - switch( mPaintState ) - { - case DisabledUnselectedState: // FALLTHROUGH - case DisabledSelectedState: - { - if( disabledBackgroundImage && disabledBackgroundImage.GetParent() ) - { - StopFadeOutAnimation(); - FadeOutImage( Background, disabledBackgroundImage ); + Actor& backgroundImage = GetBackgroundImage(); - disabledBackgroundImage = image; + backgroundImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); - FadeInImage( disabledBackgroundImage, 0.0f, 0 ); + backgroundImage.RelayoutRequestTree(); - StartFadeOutAnimation(); - StartFadeInAnimation(); - } - else - { - disabledBackgroundImage = image; - Self().Add( disabledBackgroundImage ); - } - break; - } - case UnselectedDisabledTransition: // FALLTHROUGH - case SelectedDisabledTransition: - { - StopFadeInAnimation(); - Self().Remove( disabledBackgroundImage ); + RelayoutRequest(); +} - disabledBackgroundImage = image; +void PushButton::OnSelectedBackgroundImageSet() +{ + Actor& selectedBackgroundImage = GetSelectedBackgroundImage(); - FadeInImage( disabledBackgroundImage, 0.0f, 0 ); - StartFadeInAnimation(); - break; - } - case DisabledUnselectedTransition: // FALLTHROUGH - case DisabledSelectedTransition: - { - float opacity = 1.f; - if( fadeOutBackgroundImage ) - { - opacity = fadeOutBackgroundImage.GetCurrentOpacity(); - } - StopFadeOutAnimation(); + selectedBackgroundImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); +} - // Replaces the button image. - disabledBackgroundImage = image; +void PushButton::OnDisabledImageSet() +{ + Actor& disabledImage = GetDisabledImage(); - Self().Add( disabledBackgroundImage ); - FadeOutImage( Background, disabledBackgroundImage, opacity ); + disabledImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); - StartFadeOutAnimation(); - break; - } - default: - disabledBackgroundImage = image; - break; - } + disabledImage.RelayoutRequestTree(); - disabledBackgroundImage.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - disabledBackgroundImage.SetParentOrigin( ParentOrigin::TOP_LEFT ); - disabledBackgroundImage.SetPosition( 0.f, 0.f, BACKGROUND_DEPTH ); - disabledBackgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + RelayoutRequest(); } -void PushButton::OnButtonInitialize() +void PushButton::OnDisabledBackgroundImageSet() { - // Push button requires the Leave event. - Actor root = Self(); - root.SetLeaveRequired( true ); + Actor& disabledBackgroundImage = GetDisabledBackgroundImage(); - // Set resize policy to natural size so that buttons will resize to background images - root.SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS ); -} + disabledBackgroundImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); -void PushButton::OnLabelSet() -{ - Actor& label = GetLabel(); + disabledBackgroundImage.RelayoutRequestTree(); - if( label ) - { - label.SetAnchorPoint( AnchorPoint::CENTER ); - label.SetParentOrigin( ParentOrigin::CENTER ); - label.SetPosition( 0.f, 0.f, LABEL_DEPTH ); - label.SetSize( mSize ); - - Self().Add( label ); - } + RelayoutRequest(); } -void PushButton::OnSelected( bool selected ) +bool PushButton::OnSelected() { - Actor& selectedImage = GetSelectedImage(); Actor& buttonImage = GetButtonImage(); - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); + Actor& selectedImage = GetSelectedImage(); + Actor& selectedBackgroundImage = GetSelectedBackgroundImage(); + + PaintState paintState = GetPaintState(); - switch( mPaintState ) + switch( paintState ) { case UnselectedState: { - StopFadeOutAnimation(); - FadeOutImage( Foreground, buttonImage ); - FadeInImage( selectedImage, 0.0f, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || selectedImage ) - { - mPaintState = UnselectedSelectedTransition; - } - else - { - mPaintState = SelectedState; - } + FadeOutImage( buttonImage ); + FadeInImage( selectedBackgroundImage ); + FadeInImage( selectedImage ); + StartTransitionAnimation(); break; } case SelectedState: { - StopFadeOutAnimation(); - FadeOutImage( Foreground, selectedImage ); - FadeInImage( buttonImage, 0.0f, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || selectedImage ) - { - mPaintState = SelectedUnselectedTransition; - } - else - { - mPaintState = UnselectedState; - } + FadeOutImage( selectedBackgroundImage ); + FadeOutImage( selectedImage ); + FadeInImage( buttonImage ); + StartTransitionAnimation(); break; } case UnselectedSelectedTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( selectedImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = selectedImage.GetCurrentOpacity(); } - StopFadeOutAnimation( false ); - StopFadeInAnimation(); - FadeOutImage( Foreground, selectedImage, 1.f - opacity ); - FadeInImage( buttonImage, opacity, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || selectedImage ) - { - mPaintState = SelectedUnselectedTransition; - } - else - { - mPaintState = UnselectedState; - } + StopTransitionAnimation( false ); + FadeOutImage( selectedBackgroundImage, opacity ); + FadeOutImage( selectedImage, opacity ); + FadeInImage( buttonImage, 1.f - opacity ); + StartTransitionAnimation(); break; } case SelectedUnselectedTransition: { float opacity = 0.f; - if( fadeOutButtonImage ) + if( selectedImage ) { - opacity = 1.f - fadeOutButtonImage.GetCurrentOpacity(); + opacity = selectedImage.GetCurrentOpacity(); } - StopFadeOutAnimation( false ); - StopFadeInAnimation(); - - FadeOutImage( Foreground, buttonImage, 1.f - opacity ); - FadeInImage( selectedImage, opacity, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - if( buttonImage || selectedImage ) - { - mPaintState = UnselectedSelectedTransition; - } - else - { - mPaintState = SelectedState; - } + StopTransitionAnimation( false ); + FadeOutImage( buttonImage, 1.f - opacity ); + FadeInImage( selectedBackgroundImage, opacity ); + FadeInImage( selectedImage, opacity ); + StartTransitionAnimation(); + break; + } + case DisabledUnselectedTransition: + { + StopTransitionAnimation(); + FadeOutImage( buttonImage ); + FadeInImage( selectedBackgroundImage ); + FadeInImage( selectedImage ); + StartTransitionAnimation(); + break; + } + case DisabledSelectedTransition: + { + StopTransitionAnimation(); + FadeOutImage( selectedBackgroundImage ); + FadeOutImage( selectedImage ); + FadeInImage( buttonImage ); + StartTransitionAnimation(); break; } default: @@ -589,419 +266,282 @@ void PushButton::OnSelected( bool selected ) break; } } + + if( mTransitionAnimation ) + { + return true; + } + + return false; } -void PushButton::OnDisabled( bool disabled ) +bool PushButton::OnDisabled() { Actor& buttonImage = GetButtonImage(); Actor& selectedImage = GetSelectedImage(); + Actor& selectedBackgroundImage = GetSelectedBackgroundImage(); Actor& backgroundImage = GetBackgroundImage(); Actor& disabledImage = GetDisabledImage(); + Actor& disabledSelectedImage = GetDisabledSelectedImage(); Actor& disabledBackgroundImage = GetDisabledBackgroundImage(); - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); - switch( mPaintState ) - { - case UnselectedState: + PaintState paintState = GetPaintState(); + + switch( paintState ) { - if( disabled ) + case UnselectedState: { - StopFadeOutAnimation(); - FadeOutImage( Background, backgroundImage ); - FadeOutImage( Foreground, buttonImage ); - FadeInImage( disabledBackgroundImage, 0.0f, 0 ); - FadeInImage( disabledImage, 0.0f, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = UnselectedDisabledTransition; - } - else - { - mPaintState = DisabledUnselectedState; - } + FadeOutImage( backgroundImage ); + FadeOutImage( buttonImage ); + FadeInImage( disabledBackgroundImage ); + FadeInImage( disabledImage ); + StartTransitionAnimation(); + break; } - break; - } - case SelectedState: - { - if( disabled ) + case SelectedState: { - StopFadeOutAnimation(); - FadeOutImage( Background, backgroundImage ); - FadeOutImage( Foreground, selectedImage ); - FadeInImage( disabledBackgroundImage, 0.0f, 0 ); - FadeInImage( disabledImage, 0.0f, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( selectedImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = SelectedDisabledTransition; - } - else - { - mPaintState = DisabledSelectedState; - } + FadeOutImage( backgroundImage ); + FadeOutImage( selectedBackgroundImage ); + FadeOutImage( selectedImage ); + FadeInImage( disabledBackgroundImage ); + FadeInImage( disabledSelectedImage ); + StartTransitionAnimation(); + break; } - break; - } - case DisabledUnselectedState: - { - if( !disabled ) + case DisabledUnselectedState: { - StopFadeOutAnimation(); - FadeOutImage( Background, disabledBackgroundImage ); - FadeOutImage( Foreground, disabledImage ); - FadeInImage( backgroundImage, 0.0f, 0 ); - FadeInImage( buttonImage, 0.0f, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = DisabledUnselectedTransition; - } - else - { - mPaintState = UnselectedState; - } + FadeOutImage( disabledBackgroundImage ); + FadeOutImage( disabledImage ); + FadeInImage( backgroundImage ); + FadeInImage( buttonImage ); + StartTransitionAnimation(); + break; } - break; - } - case DisabledSelectedState: - { - if( !disabled ) + case DisabledSelectedState: { - StopFadeOutAnimation(); - FadeOutImage( Background, disabledBackgroundImage ); - FadeOutImage( Foreground, disabledImage ); - FadeInImage( backgroundImage, 0.0f, 0 ); - FadeInImage( selectedImage, 0.0f, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( selectedImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = DisabledSelectedTransition; - } - else - { - mPaintState = SelectedState; - } + FadeOutImage( disabledBackgroundImage ); + FadeOutImage( disabledSelectedImage ); + FadeInImage( backgroundImage ); + FadeInImage( selectedBackgroundImage ); + FadeInImage( selectedImage ); + StartTransitionAnimation(); + break; } - break; - } - case UnselectedSelectedTransition: - { - if( disabled ) + case UnselectedSelectedTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( selectedImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = selectedImage.GetCurrentOpacity(); } - StopFadeOutAnimation(); - StopFadeInAnimation(); - FadeOutImage( Foreground, selectedImage, 1.f - opacity ); - FadeOutImage( Background, backgroundImage ); - - FadeInImage( disabledImage, 0.0f, 0 ); - FadeInImage( disabledBackgroundImage, 0.0f, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( selectedImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = SelectedDisabledTransition; - } - else - { - mPaintState = DisabledSelectedState; - } + StopTransitionAnimation(); + FadeOutImage( backgroundImage ); + FadeOutImage( selectedBackgroundImage, opacity ); + FadeOutImage( selectedImage, opacity ); + FadeInImage( disabledBackgroundImage ); + FadeInImage( disabledSelectedImage ); + StartTransitionAnimation(); + break; } - break; - } - case SelectedUnselectedTransition: - { - if( disabled ) + case SelectedUnselectedTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( buttonImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = buttonImage.GetCurrentOpacity(); } - StopFadeOutAnimation(); - StopFadeInAnimation(); - - FadeOutImage( Foreground, buttonImage, 1.f - opacity ); - FadeOutImage( Background, backgroundImage ); - FadeInImage( disabledImage, 0.0f, 0); - FadeInImage( disabledBackgroundImage, 0.0f, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = UnselectedDisabledTransition; - } - else - { - mPaintState = DisabledUnselectedState; - } + StopTransitionAnimation(); + FadeOutImage( backgroundImage ); + FadeOutImage( buttonImage, opacity ); + FadeInImage( disabledBackgroundImage ); + FadeInImage( disabledImage ); + StartTransitionAnimation(); + break; } - break; - } - case UnselectedDisabledTransition: - { - if( !disabled ) + case UnselectedDisabledTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( disabledImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = disabledImage.GetCurrentOpacity(); } - StopFadeOutAnimation( false ); - StopFadeInAnimation(); - - FadeOutImage( Foreground, disabledImage, 1.f - opacity ); - FadeOutImage( Background, disabledBackgroundImage, 1.f - opacity ); - FadeInImage( buttonImage, opacity, 0 ); - FadeInImage( backgroundImage, opacity, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - if( buttonImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = DisabledUnselectedTransition; - } - else - { - mPaintState = UnselectedState; - } + StopTransitionAnimation( false ); + FadeOutImage( disabledBackgroundImage, opacity ); + FadeOutImage( disabledImage, opacity ); + FadeInImage( backgroundImage, 1.f - opacity ); + FadeInImage( buttonImage, 1.f - opacity ); + StartTransitionAnimation(); + break; } - break; - } - case DisabledUnselectedTransition: - { - if( disabled ) + case DisabledUnselectedTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( buttonImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = buttonImage.GetCurrentOpacity(); } - StopFadeOutAnimation( false ); - StopFadeInAnimation(); - FadeOutImage( Foreground, buttonImage, 1.f - opacity ); - FadeOutImage( Background, backgroundImage, 1.f - opacity ); - FadeInImage( disabledImage, opacity, 0 ); - FadeInImage( disabledBackgroundImage, opacity, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = UnselectedDisabledTransition; - } - else - { - mPaintState = DisabledUnselectedState; - } + StopTransitionAnimation( false ); + FadeOutImage( backgroundImage, opacity ); + FadeOutImage( buttonImage, opacity ); + FadeInImage( disabledBackgroundImage, 1.f - opacity ); + FadeInImage( disabledImage, 1.f - opacity ); + StartTransitionAnimation(); + break; } - break; - } - case SelectedDisabledTransition: - { - if( !disabled ) + case SelectedDisabledTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( disabledSelectedImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = disabledSelectedImage.GetCurrentOpacity(); } - StopFadeOutAnimation( false ); - StopFadeInAnimation(); - - FadeOutImage( Foreground, disabledImage, 1.f - opacity ); - FadeOutImage( Background, disabledBackgroundImage, 1.f - opacity ); - FadeInImage( selectedImage, opacity, 0 ); - FadeInImage( backgroundImage, opacity, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - if( selectedImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = DisabledSelectedTransition; - } - else - { - mPaintState = SelectedState; - } + StopTransitionAnimation( false ); + FadeOutImage( disabledBackgroundImage, opacity ); + FadeOutImage( disabledSelectedImage, opacity ); + FadeInImage( backgroundImage, 1.f - opacity ); + FadeInImage( selectedBackgroundImage, 1.f - opacity ); + FadeInImage( selectedImage, 1.f - opacity ); + StartTransitionAnimation(); + break; } - break; - } - case DisabledSelectedTransition: - { - if( disabled ) + case DisabledSelectedTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( selectedImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = selectedImage.GetCurrentOpacity(); } - StopFadeOutAnimation( false ); - StopFadeInAnimation(); - FadeOutImage( Foreground, selectedImage, 1.f - opacity ); - FadeOutImage( Background, backgroundImage, 1.f - opacity ); - FadeInImage( disabledImage, opacity, 0 ); - FadeInImage( disabledBackgroundImage, opacity, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( selectedImage || disabledImage || backgroundImage || disabledBackgroundImage ) - { - mPaintState = SelectedDisabledTransition; - } - else - { - mPaintState = DisabledSelectedState; - } + StopTransitionAnimation( false ); + FadeOutImage( backgroundImage, opacity ); + FadeOutImage( selectedBackgroundImage, opacity ); + FadeOutImage( selectedImage, opacity ); + FadeInImage( disabledBackgroundImage, 1.f - opacity ); + FadeInImage( disabledSelectedImage, 1.f - opacity ); + StartTransitionAnimation(); + break; } - break; } - default: - break; + + if( mTransitionAnimation ) + { + return true; } + + return false; } -void PushButton::OnPressed() +bool PushButton::OnPressed() { - Actor& selectedImage = GetSelectedImage(); Actor& buttonImage = GetButtonImage(); - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); + Actor& selectedImage = GetSelectedImage(); + Actor& selectedBackgroundImage = GetSelectedBackgroundImage(); + + PaintState paintState = GetPaintState(); - switch( mPaintState ) + switch( paintState ) { case UnselectedState: { - StopFadeOutAnimation(); - FadeOutImage( Foreground, buttonImage ); - FadeInImage( selectedImage, 0.0f, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || selectedImage ) - { - mPaintState = UnselectedSelectedTransition; - } - else - { - mPaintState = SelectedState; - } + FadeOutImage( buttonImage ); + FadeInImage( selectedBackgroundImage ); + FadeInImage( selectedImage ); + StartTransitionAnimation(); break; } - case UnselectedSelectedTransition: + case SelectedUnselectedTransition: { - if( !IsAutoRepeating() ) + float opacity = 1.f; + if( buttonImage ) { - mPaintState = SelectedUnselectedTransition; + opacity = buttonImage.GetCurrentOpacity(); } + + StopTransitionAnimation( false ); + FadeOutImage( buttonImage, opacity ); + FadeInImage( selectedBackgroundImage, 1.f - opacity ); + FadeInImage( selectedImage, 1.f - opacity ); + StartTransitionAnimation(); break; } - case SelectedUnselectedTransition: + case DisabledUnselectedTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( buttonImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = buttonImage.GetCurrentOpacity(); } - StopFadeOutAnimation( false ); - StopFadeInAnimation(); - - FadeOutImage( Foreground, buttonImage, 1.f - opacity ); - FadeInImage( selectedImage, opacity, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || selectedImage ) - { - mPaintState = UnselectedSelectedTransition; - } - else - { - mPaintState = SelectedState; - } + StopTransitionAnimation(); + FadeOutImage( buttonImage, opacity ); + FadeInImage( selectedBackgroundImage ); + FadeInImage( selectedImage ); + StartTransitionAnimation(); break; } default: break; } + + if( mTransitionAnimation ) + { + return true; + } + + return false; } -void PushButton::OnReleased() +bool PushButton::OnReleased() { - Actor& selectedImage = GetSelectedImage(); Actor& buttonImage = GetButtonImage(); - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); + Actor& selectedImage = GetSelectedImage(); + Actor& selectedBackgroundImage = GetSelectedBackgroundImage(); - switch( mPaintState ) + PaintState paintState = GetPaintState(); + + switch( paintState ) { case SelectedState: { - StopFadeOutAnimation(); - FadeOutImage( Foreground, selectedImage ); - FadeInImage( buttonImage, 0.0f, 0 ); - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || selectedImage ) - { - mPaintState = SelectedUnselectedTransition; - } - else - { - mPaintState = UnselectedState; - } + FadeOutImage( selectedBackgroundImage ); + FadeOutImage( selectedImage ); + FadeInImage( buttonImage ); + StartTransitionAnimation(); break; } case UnselectedSelectedTransition: { float opacity = 1.f; - if( fadeOutButtonImage ) + if( selectedImage ) { - opacity = fadeOutButtonImage.GetCurrentOpacity(); + opacity = selectedImage.GetCurrentOpacity(); } - StopFadeOutAnimation( false ); - StopFadeInAnimation(); - FadeOutImage( Foreground, selectedImage, 1.f - opacity ); - FadeInImage( buttonImage, opacity, 0 ); - - StartFadeOutAnimation(); - StartFadeInAnimation(); - - if( buttonImage || selectedImage ) - { - mPaintState = SelectedUnselectedTransition; - } - else + StopTransitionAnimation( false ); + FadeOutImage( selectedBackgroundImage, opacity ); + FadeOutImage( selectedImage, opacity ); + FadeInImage( buttonImage, 1.f - opacity ); + StartTransitionAnimation(); + break; + } + case DisabledSelectedTransition: + { + float opacity = 1.f; + if( selectedImage ) { - mPaintState = UnselectedState; + opacity = selectedImage.GetCurrentOpacity(); } + + StopTransitionAnimation(); + FadeOutImage( selectedBackgroundImage, opacity ); + FadeOutImage( selectedImage, opacity ); + FadeInImage( buttonImage ); + StartTransitionAnimation(); break; } default: @@ -1009,11 +549,18 @@ void PushButton::OnReleased() break; } } + + if( mTransitionAnimation ) + { + return true; + } + + return false; } -void PushButton::OnClicked() +void PushButton::StopAllAnimations() { - OnReleased(); + StopTransitionAnimation(); } void PushButton::OnControlSizeSet( const Vector3& targetSize ) @@ -1033,273 +580,83 @@ void PushButton::OnControlSizeSet( const Vector3& targetSize ) Vector3 PushButton::GetNaturalSize() { - Vector3 size = Control::GetNaturalSize(); + Vector3 size; - const bool widthIsZero = EqualsZero( size.width ); - const bool heightIsZero = EqualsZero( size.height ); + // Check Image and Background image and use the largest size as the control's Natural size. + SizeOfActorIfLarger( GetButtonImage(), size ); + SizeOfActorIfLarger( GetBackgroundImage(), size ); - if( widthIsZero || heightIsZero ) + // If label, test against it's size + Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( GetLabel() ); + if( label ) { - // If background and background not scale9 try get size from that - ImageActor imageActor = FindImageActor( GetButtonImage() ); - if( imageActor && imageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH ) - { - Vector3 imageSize = imageActor.GetNaturalSize(); - - if( widthIsZero ) - { - size.width = imageSize.width; - } - - if( heightIsZero ) - { - size.height = imageSize.height; - } - } + Vector3 labelSize = label.GetNaturalSize(); - ImageActor backgroundImageActor = FindImageActor( GetBackgroundImage() ); - if( backgroundImageActor && backgroundImageActor.GetStyle() != ImageActor::STYLE_NINE_PATCH ) - { - Vector3 imageSize = backgroundImageActor.GetNaturalSize(); - - if( widthIsZero ) - { - size.width = std::max( size.width, imageSize.width ); - } - - if( heightIsZero ) - { - size.height = std::max( size.height, imageSize.height ); - } - } - - // If label, test against it's size - Toolkit::TextView textView = Toolkit::TextView::DownCast( GetLabel() ); - if( textView ) - { - Vector3 textViewSize = textView.GetNaturalSize(); - - if( widthIsZero ) - { - size.width = std::max( size.width, textViewSize.width + TEXT_PADDING * 2.0f ); - } - - if( heightIsZero ) - { - size.height = std::max( size.height, textViewSize.height + TEXT_PADDING * 2.0f ); - } - } + size.width = std::max( size.width, labelSize.width + TEXT_PADDING * 2.0f ); + size.height = std::max( size.height, labelSize.height + TEXT_PADDING * 2.0f ); } return size; } -Actor& PushButton::GetFadeOutButtonImage() -{ - return mFadeOutButtonContent; -} - -Actor& PushButton::GetFadeOutBackgroundImage() -{ - return mFadeOutBackgroundContent; -} - -void PushButton::AddToFadeInAnimation( const Actor& actor ) -{ - if( !mFadeInAnimation ) - { - mFadeInAnimation = Dali::Animation::New( GetAnimationTime() ); - } - - mFadeInAnimation.OpacityTo( actor, 1.f ); -} - -void PushButton::StartFadeInAnimation() -{ - if( mFadeInAnimation ) - { - mFadeInAnimation.FinishedSignal().Connect( this, &PushButton::FadeInAnimationFinished ); - mFadeInAnimation.Play(); - } -} - -void PushButton::StopFadeInAnimation() -{ - if( mFadeInAnimation ) - { - mFadeInAnimation.Clear(); - mFadeInAnimation.Reset(); - } -} - -void PushButton::AddToFadeOutAnimation( const Actor& actor ) +void PushButton::StartTransitionAnimation() { - if( !mFadeOutAnimation ) + if( mTransitionAnimation ) { - mFadeOutAnimation = Dali::Animation::New( GetAnimationTime() ); - } - - mFadeOutAnimation.OpacityTo( actor, 0.f ); -} - -void PushButton::StartFadeOutAnimation() -{ - if( mFadeOutAnimation ) - { - mFadeOutAnimation.FinishedSignal().Connect( this, &PushButton::FadeOutAnimationFinished ); - mFadeOutAnimation.Play(); + mTransitionAnimation.FinishedSignal().Connect( this, &PushButton::TransitionAnimationFinished ); + mTransitionAnimation.Play(); } } -void PushButton::StopFadeOutAnimation( bool remove ) +void PushButton::StopTransitionAnimation( bool remove ) { - if( mFadeOutAnimation ) + if( mTransitionAnimation ) { - mFadeOutAnimation.Clear(); - mFadeOutAnimation.Reset(); + mTransitionAnimation.Clear(); + mTransitionAnimation.Reset(); } if( remove ) { - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); - Actor& fadeOutBackgroundImage = GetFadeOutBackgroundImage(); - - if( fadeOutButtonImage && fadeOutButtonImage.GetParent() ) - { - fadeOutButtonImage.GetParent().Remove( fadeOutButtonImage ); - } - - if( fadeOutBackgroundImage && fadeOutBackgroundImage.GetParent() ) - { - fadeOutBackgroundImage.GetParent().Remove( fadeOutBackgroundImage ); - } - - fadeOutButtonImage.Reset(); - fadeOutBackgroundImage.Reset(); + UpdatePaintTransitionState(); } } -void PushButton::FadeInImage( Actor& image, float opacity, int priority ) +void PushButton::FadeInImage( Actor& image, float opacity, Vector3 scale ) { if( image ) { image.SetOpacity( opacity ); - if( !image.GetParent() ) + image.SetScale( scale ); + + if( !mTransitionAnimation ) { - if( priority > -1 ) - { - Self().Insert( priority, image ); - } - else - { - Self().Add( image ); - } + mTransitionAnimation = Dali::Animation::New( GetAnimationTime() ); } - AddToFadeInAnimation( image ); + mTransitionAnimation.AnimateTo( Property( image, Actor::Property::COLOR_ALPHA ), 1.f ); } } -void PushButton::FadeOutImage( ImageLayer layer, Actor& image, float opacity ) +void PushButton::FadeOutImage( Actor& image, float opacity, Vector3 scale ) { if( image ) { - Actor& fadeOutButtonImage = GetFadeOutButtonImage(); - Actor& fadeOutBackgroundImage = GetFadeOutBackgroundImage(); - - Actor& actorLayer = ( ( Background == layer ) ? fadeOutBackgroundImage : fadeOutButtonImage ); - - actorLayer = image; - actorLayer.SetOpacity( opacity ); - - AddToFadeOutAnimation( actorLayer ); - } -} + image.SetOpacity( opacity ); + image.SetScale( scale ); -void PushButton::FadeOutAnimationFinished( Dali::Animation& source ) -{ - switch( mPaintState ) - { - case UnselectedSelectedTransition: - { - mPaintState = SelectedState; - break; - } - case SelectedUnselectedTransition: + if( !mTransitionAnimation ) { - mPaintState = UnselectedState; - break; - } - case UnselectedDisabledTransition: - { - mPaintState = DisabledUnselectedState; - break; + mTransitionAnimation = Dali::Animation::New( GetAnimationTime() ); } - case DisabledUnselectedTransition: - { - mPaintState = UnselectedState; - break; - } - case SelectedDisabledTransition: - { - mPaintState = DisabledSelectedState; - break; - } - case DisabledSelectedTransition: - { - mPaintState = SelectedState; - break; - } - default: - { - break; - } - } - StopFadeOutAnimation(); + mTransitionAnimation.AnimateTo( Property( image, Actor::Property::COLOR_ALPHA ), 0.f ); + } } -void PushButton::FadeInAnimationFinished( Dali::Animation& source ) +void PushButton::TransitionAnimationFinished( Dali::Animation& source ) { - switch( mPaintState ) - { - case UnselectedSelectedTransition: - { - mPaintState = SelectedState; - break; - } - case SelectedUnselectedTransition: - { - mPaintState = UnselectedState; - break; - } - case UnselectedDisabledTransition: - { - mPaintState = DisabledUnselectedState; - break; - } - case DisabledUnselectedTransition: - { - mPaintState = UnselectedState; - break; - } - case SelectedDisabledTransition: - { - mPaintState = DisabledSelectedState; - break; - } - case DisabledSelectedTransition: - { - mPaintState = SelectedState; - break; - } - default: - { - break; - } - } - - StopFadeInAnimation(); + StopTransitionAnimation(); } } // namespace Internal diff --git a/dali-toolkit/internal/controls/buttons/push-button-impl.h b/dali-toolkit/internal/controls/buttons/push-button-impl.h index 89bce4b..3eddddc 100644 --- a/dali-toolkit/internal/controls/buttons/push-button-impl.h +++ b/dali-toolkit/internal/controls/buttons/push-button-impl.h @@ -62,69 +62,72 @@ protected: */ virtual ~PushButton(); -public: // From Button +private: // From Button /** - * @copydoc Toolkit::Internal::Button::SetButtonImage( Actor image ) + * @copydoc Toolkit::Internal::Button::OnButtonInitialize() */ - virtual void SetButtonImage( Actor image ); + virtual void OnButtonInitialize(); /** - * @copydoc Toolkit::Internal::Button::SetSelectedImage( Actor image ) + * @copydoc Toolkit::Internal::Button::OnLabelSet() */ - virtual void SetSelectedImage( Actor image ); + virtual void OnLabelSet(); /** - * @copydoc Toolkit::Internal::Button::SetBackgroundImage( Actor image ) + * @copydoc Toolkit::Internal::Button::OnButtonImageSet() */ - virtual void SetBackgroundImage( Actor image ); + virtual void OnButtonImageSet(); /** - * @copydoc Toolkit::Internal::Button::SetDisabledImage( Actor image ) + * @copydoc Toolkit::Internal::Button::OnSelectedImageSet() */ - virtual void SetDisabledImage( Actor image ); + virtual void OnSelectedImageSet(); /** - * @copydoc Toolkit::Internal::Button::SetDisabledBackgroundImage( Actor image ) + * @copydoc Toolkit::Internal::Button::OnBackgroundImage() */ - virtual void SetDisabledBackgroundImage( Actor image ); + virtual void OnBackgroundImageSet(); -private: // From Button + /** + * @copydoc Toolkit::Internal::Button::OnSelectedBackgroundImageSet() + */ + virtual void OnSelectedBackgroundImageSet(); /** - * @copydoc Toolkit::Internal::Button::OnButtonInitialize() + * @copydoc Toolkit::Internal::Button::OnDisabledImageSet() */ - virtual void OnButtonInitialize(); + virtual void OnDisabledImageSet(); /** - * @copydoc Toolkit::Internal::Button::OnLabelSet() + * @copydoc Toolkit::Internal::Button::OnDisabledBackgroundImageSet() */ - virtual void OnLabelSet(); + virtual void OnDisabledBackgroundImageSet(); /** * @copydoc Toolkit::Internal::Button::OnSelected() */ - virtual void OnSelected( bool selected ); + virtual bool OnSelected(); /** - * @copydoc Toolkit::Internal::Button::OnDisabled( bool disabled ) + * @copydoc Toolkit::Internal::Button::OnDisabled() */ - virtual void OnDisabled( bool disabled ); + virtual bool OnDisabled(); /** * @copydoc Toolkit::Internal::Button::OnPressed() */ - virtual void OnPressed(); + virtual bool OnPressed(); /** * @copydoc Toolkit::Internal::Button::OnReleased() */ - virtual void OnReleased(); + virtual bool OnReleased(); /** - * @copydoc Toolkit::Internal::Button::OnClicked() + * @copydoc Toolkit::Internal::Button::StopAllAnimations() */ - virtual void OnClicked(); + virtual void StopAllAnimations(); private: // From Control @@ -141,89 +144,40 @@ private: // From Control private: /** - * Used in the FadeOut functions. - */ - enum ImageLayer - { - Background, ///< Fade out the background. - Foreground ///< Fade out the foreground. - }; - - /** - * Gets the button image that is fading out. - * @return A reference to the button image that is fading out. + * Starts the transition animation. + * PushButton::TransitionAnimationFinished slot is called when the animation finishes. */ - Actor& GetFadeOutButtonImage(); + void StartTransitionAnimation(); /** - * Gets the background image that is fading out. - * @return A reference to the background image that is fading out. - */ - Actor& GetFadeOutBackgroundImage(); - - /** - * Adds the actor to the fade in animation. It creates a fade in animation if needed. - * @param[in] actor The actor. - */ - void AddToFadeInAnimation( const Actor& actor ); - - /** - * Starts the fade in animation. - * PushButton::FadeInAnimationFinished slot is called when the animation finishes. - */ - void StartFadeInAnimation(); - - /** - * Stops the fade in animation. - */ - void StopFadeInAnimation(); - - /** - * Adds the actor to the fade out animation. It creates a fade out animation if needed. - */ - void AddToFadeOutAnimation( const Actor& actor ); - - /** - * Starts the fade out animation. - * PushButton::FadeOutAnimationFinished slot is called when the animation finishes. - */ - void StartFadeOutAnimation(); - - /** - * Stops the fade out animation. - * It removes the actor stored in PushButton::mFadeOutBackgroundImage and PushButton::mFadeOutCheckedImage. + * Stops the transition animation. * @param[in] remove If true, removes the fadeout actor from root. */ - void StopFadeOutAnimation( bool remove = true ); + void StopTransitionAnimation( bool remove = true ); /** * It adds the actor to the root actor and to the fade in animation. * @param[inout] image The actor. * @param[in] opacity The initial opacity. + * @param[in] scale The initial scale. */ - void FadeInImage( Actor& image, float opacity = 0.f, int priority = -1 ); + void FadeInImage( Actor& image, float opacity = 0.f, Vector3 scale = Vector3( 1.f, 1.f, 1.f ) ); /** * It adds the actor fade out animation and stores it to be removed when the animation finishes. * @param[in] layer Defines if the actor is going to be stored in the mFadeOutBackgroundImage or mFadeOutCheckedImage member. * @param[inout] image The actor. * @param[in] opacity The initial opacity. + * @param[in] scale The initial scale. */ - void FadeOutImage( ImageLayer layer, Actor& image, float opacity = 1.f ); + void FadeOutImage( Actor& image, float opacity = 1.f, Vector3 scale = Vector3( 1.f, 1.f, 1.f ) ); // slots /** - * Called when the fade out animation finishes. - * It changes the check button paint state and removes actors from the root. + * Called when the transition animation finishes. */ - void FadeOutAnimationFinished( Dali::Animation& source ); - - /** - * Called when the fade in animation finishes. - * It changes the check button paint state. - */ - void FadeInAnimationFinished( Dali::Animation& source ); + void TransitionAnimationFinished( Dali::Animation& source ); private: @@ -235,15 +189,8 @@ private: private: - Animation mFadeInAnimation; ///< Animation used in the state transitions. - Animation mFadeOutAnimation; ///< Animation used in the state transitions. - - Actor mFadeOutButtonContent; ///< Stores a foreground content, which is in a fade out animation, to be removed when the animation finishes. - Actor mFadeOutBackgroundContent; ///< Stores a background content, which is in a fade out animation, to be removed when the animation finishes. - + Animation mTransitionAnimation; ///< Animation used in the state transitions. Vector3 mSize; ///< The button's size. - - PaintState mPaintState; ///< The paint state. }; } // namespace Internal diff --git a/dali-toolkit/internal/controls/buttons/radio-button-impl.cpp b/dali-toolkit/internal/controls/buttons/radio-button-impl.cpp index 05dba27..81b6a5d 100644 --- a/dali-toolkit/internal/controls/buttons/radio-button-impl.cpp +++ b/dali-toolkit/internal/controls/buttons/radio-button-impl.cpp @@ -45,7 +45,7 @@ TypeRegistration typeRegistration( typeid( Toolkit::RadioButton ), typeid( Toolk const char* const UNSELECTED_BUTTON_IMAGE_DIR = DALI_IMAGE_DIR "radio-button-unselected.png"; const char* const SELECTED_BUTTON_IMAGE_DIR = DALI_IMAGE_DIR "radio-button-selected.png"; -const float DISTANCE_BETWEEN_IMAGE_AND_LABEL = 5.0f; +const float DISTANCE_BETWEEN_IMAGE_AND_LABEL( 5.0f ); } Dali::Toolkit::RadioButton RadioButton::New() @@ -72,39 +72,12 @@ RadioButton::~RadioButton() { } -void RadioButton::SetImage( Actor image ) -{ - mLayoutContainer.RemoveChildAt( Toolkit::TableView::CellPosition( 0, 0 ) ); - mLayoutContainer.AddChild( image, Toolkit::TableView::CellPosition( 0, 0 ) ); - - RelayoutRequest(); -} - -void RadioButton::SetButtonImage( Actor image ) -{ - Actor& buttonImage = GetButtonImage(); - buttonImage = image; -} - -void RadioButton::SetSelectedImage( Actor image ) -{ - Actor& selectedImage = GetSelectedImage(); - selectedImage = image; -} - void RadioButton::OnButtonInitialize() { Actor self = Self(); // Wrap size of radio button around all its children - self.SetResizePolicy( FIT_TO_CHILDREN, ALL_DIMENSIONS ); - - // Create the layout container empty at first - mLayoutContainer = Toolkit::TableView::New( 0, 0 ); - mLayoutContainer.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - mLayoutContainer.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mLayoutContainer.SetResizePolicy( FIT_TO_CHILDREN, ALL_DIMENSIONS ); - self.Add( mLayoutContainer ); + self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); Image buttonImage = Dali::ResourceImage::New( UNSELECTED_BUTTON_IMAGE_DIR ); Image selectedImage = Dali::ResourceImage::New( SELECTED_BUTTON_IMAGE_DIR ); @@ -112,8 +85,6 @@ void RadioButton::OnButtonInitialize() SetButtonImage( ImageActor::New( buttonImage ) ); SetSelectedImage( ImageActor::New( selectedImage ) ); - SetImage( GetButtonImage() ); - RelayoutRequest(); } @@ -135,37 +106,77 @@ void RadioButton::OnLabelSet() if( label ) { - // Add padding to the left of the label to create distance from the image - label.SetPadding( Padding( DISTANCE_BETWEEN_IMAGE_AND_LABEL, 0.0f, 0.0f, 0.0f ) ); + label.SetParentOrigin( ParentOrigin::CENTER_LEFT ); + label.SetAnchorPoint( AnchorPoint::CENTER_LEFT ); - mLayoutContainer.RemoveChildAt( Toolkit::TableView::CellPosition( 0, 1 ) ); - mLayoutContainer.AddChild( label, Toolkit::TableView::CellPosition( 0, 1 ) ); + // Radio button width is FIT_TO_CHILDREN, so the label must have a sensible policy to fill out the space + if( label.GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FILL_TO_PARENT ) + { + label.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH ); + } + + if( IsSelected() ) + { + label.SetX( GetSelectedImage().GetNaturalSize().width + DISTANCE_BETWEEN_IMAGE_AND_LABEL ); + } + else + { + label.SetX( GetButtonImage().GetNaturalSize().width + DISTANCE_BETWEEN_IMAGE_AND_LABEL ); + } } } -void RadioButton::OnSelected( bool selected ) +bool RadioButton::OnSelected() { - if( selected ) + Actor& buttonImage = GetButtonImage(); + Actor& selectedImage = GetSelectedImage(); + Actor& label = GetLabel(); + + PaintState paintState = GetPaintState(); + + switch( paintState ) { - Actor parent = Self().GetParent(); - if( parent ) + case UnselectedState: { - for( unsigned int i = 0; i < parent.GetChildCount(); ++i ) + Actor parent = Self().GetParent(); + if( parent ) { - Dali::Toolkit::RadioButton radioButtonChild = Dali::Toolkit::RadioButton::DownCast( parent.GetChildAt( i ) ); - if( radioButtonChild ) + for( unsigned int i = 0; i < parent.GetChildCount(); ++i ) { - radioButtonChild.SetSelected( false ); + Dali::Toolkit::RadioButton radioButtonChild = Dali::Toolkit::RadioButton::DownCast( parent.GetChildAt( i ) ); + if( radioButtonChild && radioButtonChild != Self() ) + { + radioButtonChild.SetSelected( false ); + } } } + + RemoveChild( buttonImage ); + + if( label ) + { + label.SetX( selectedImage.GetNaturalSize().width + DISTANCE_BETWEEN_IMAGE_AND_LABEL ); + } + break; } + case SelectedState: + { + RemoveChild( selectedImage ); - SetImage( GetSelectedImage() ); - } - else - { - SetImage( GetButtonImage() ); + if( label ) + { + label.SetX( buttonImage.GetNaturalSize().width + DISTANCE_BETWEEN_IMAGE_AND_LABEL ); + } + break; + } + default: + { + break; + } } + + // there is no animation + return false; } } // namespace Internal diff --git a/dali-toolkit/internal/controls/buttons/radio-button-impl.h b/dali-toolkit/internal/controls/buttons/radio-button-impl.h index 917f9fe..d525a43 100644 --- a/dali-toolkit/internal/controls/buttons/radio-button-impl.h +++ b/dali-toolkit/internal/controls/buttons/radio-button-impl.h @@ -23,7 +23,6 @@ #include // INTERNAL INCLUDES -#include #include #include #include "button-impl.h" @@ -47,42 +46,22 @@ public: /** * Create a new RadioButton. * - * @return A smart-pointer to the newly allocated PushButton. + * @return A smart-pointer to the newly allocated RadioButton. */ static Dali::Toolkit::RadioButton New(); - /** - * Construct a new PushButton. - */ - RadioButton(); - - /** - * Construct a new PushButton with label. - */ - RadioButton( const std::string& label ); +private: /** - * Construct a new PushButton with label. + * Construct a new RadioButton. */ - RadioButton( Actor label ); + RadioButton(); /** * A reference counted object may only be deleted by calling Unreference() */ virtual ~RadioButton(); -public: // From Button - - /** - * @copydoc Toolkit::Internal::Button::SetButtonImage( Actor image ) - */ - virtual void SetButtonImage( Actor image ); - - /** - * @copydoc Toolkit::Internal::Button::SetSelectedImage( Actor image ) - */ - virtual void SetSelectedImage( Actor image ); - private: // From Button /** @@ -98,7 +77,7 @@ private: // From Button /** * @copydoc Toolkit::Internal::Button::OnSelected() */ - virtual void OnSelected( bool selected ); + virtual bool OnSelected(); /** * @copydoc Toolkit::Internal::Button::OnLabelSet() @@ -107,25 +86,11 @@ private: // From Button private: - /** - * @brief Set the image to display - * - * @param[in] image The image to set - */ - void SetImage( Actor image ); - -private: - // Undefined RadioButton( const RadioButton& origin ); // Undefined RadioButton& operator=( const RadioButton& origin ); - -private: - - Toolkit::TableView mLayoutContainer; ///< Container to position button images and labels - }; } // namespace Internal diff --git a/dali-toolkit/internal/controls/cluster/cluster-impl.cpp b/dali-toolkit/internal/controls/cluster/cluster-impl.cpp index d4daf3c..e2b4297 100644 --- a/dali-toolkit/internal/controls/cluster/cluster-impl.cpp +++ b/dali-toolkit/internal/controls/cluster/cluster-impl.cpp @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include // for strcmp #include #include #include @@ -284,7 +285,7 @@ void Cluster::ExpandChild( unsigned int index ) const float angle = (rand()%360) * Math::PI / 180.0f; Vector3 position(sin(angle) * length, -cos(angle) * length, zOffset); const float scale(1.2f); - const float rotate = ((rand()%30) - 15) * Math::PI / 180.0f; + const Radian rotate( Degree( (rand()%30) - 15 ) ); position += childInfo.mActor.GetCurrentPosition(); @@ -520,7 +521,7 @@ void Cluster::DoTransformAction(const PropertyValueContainer& attributes) unsigned int index = attributes[0].Get(); Vector3 position; Vector3 scale(Vector3::ONE); - Quaternion rotation(0.0f, Vector3::ZAXIS); + Quaternion rotation( Dali::ANGLE_0, Vector3::ZAXIS ); DALI_ASSERT_ALWAYS(attributes[1].GetType() == Property::VECTOR3); attributes[1].Get(position); diff --git a/dali-toolkit/internal/controls/cluster/cluster-style-impl.cpp b/dali-toolkit/internal/controls/cluster/cluster-style-impl.cpp index 1084302..16dd5ea 100644 --- a/dali-toolkit/internal/controls/cluster/cluster-style-impl.cpp +++ b/dali-toolkit/internal/controls/cluster/cluster-style-impl.cpp @@ -295,8 +295,8 @@ void ClusterStyle::Apply( Actor actor, if( animationDuration > 0.f ) { Animation animation = Animation::New(animationDuration); - animation.MoveTo( actor, position, alpha, durationSeconds.delaySeconds, durationSeconds.durationSeconds ); - animation.Resize( actor, size, alpha, durationSeconds.delaySeconds, durationSeconds.durationSeconds ); + animation.AnimateTo( Property( actor, Actor::Property::POSITION ), position, alpha, TimePeriod( durationSeconds.delaySeconds, durationSeconds.durationSeconds ) ); + animation.AnimateTo( Property( actor, Actor::Property::SIZE ), size, alpha, TimePeriod( durationSeconds.delaySeconds, durationSeconds.durationSeconds ) ); animation.Play(); } else @@ -318,10 +318,10 @@ void ClusterStyle::Apply( Actor actor, if( animationDuration > 0.f ) { Animation animation = Animation::New(animationDuration); - animation.MoveTo( actor, position, alpha, durationSeconds.delaySeconds, durationSeconds.durationSeconds ); - animation.Resize( actor, size, alpha, durationSeconds.delaySeconds, durationSeconds.durationSeconds ); - animation.RotateTo( actor, rotation, alpha, durationSeconds.delaySeconds, durationSeconds.durationSeconds ); - animation.ScaleTo( actor, scale, alpha, durationSeconds.delaySeconds, durationSeconds.durationSeconds ); + animation.AnimateTo( Property( actor, Actor::Property::POSITION ), position, alpha, TimePeriod( durationSeconds.delaySeconds, durationSeconds.durationSeconds ) ); + animation.AnimateTo( Property( actor, Actor::Property::SIZE ), size, alpha, TimePeriod( durationSeconds.delaySeconds, durationSeconds.durationSeconds ) ); + animation.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), rotation, alpha, TimePeriod( durationSeconds.delaySeconds, durationSeconds.durationSeconds ) ); + animation.AnimateTo( Property( actor, Actor::Property::SCALE ), scale, alpha, TimePeriod( durationSeconds.delaySeconds, durationSeconds.durationSeconds ) ); animation.Play(); } else @@ -473,7 +473,7 @@ void ClusterStyleRandom::ApplyStyle(Actor child, unsigned int index, AlphaFuncti Apply( child, FirstOrderEquation( GetClusterSize(), Vector3(position.x, position.y, 0.0f), Vector3(0.0f, 0.0f, depthPropertyValue) ), FirstOrderEquation( GetClusterSize(), Vector3::ONE * size), - Quaternion(rotation, Vector3::ZAXIS), + Quaternion( Radian( rotation ), Vector3::ZAXIS ), Vector3::ONE, alpha, durationSeconds); diff --git a/dali-toolkit/internal/controls/effects-view/effects-view-impl.cpp b/dali-toolkit/internal/controls/effects-view/effects-view-impl.cpp index d229ceb..21b6e23 100644 --- a/dali-toolkit/internal/controls/effects-view/effects-view-impl.cpp +++ b/dali-toolkit/internal/controls/effects-view/effects-view-impl.cpp @@ -19,7 +19,6 @@ #include "effects-view-impl.h" // EXTERNAL INCLUDES -#include #include #include #include @@ -271,8 +270,14 @@ void EffectsView::SetupProperties() mEffectStrengthPropertyIndex = self.RegisterProperty(EFFECT_STRENGTH_PROPERTY_NAME, EFFECT_STRENGTH_DEFAULT, Property::READ_WRITE); mEffectOffsetPropertyIndex = self.RegisterProperty(EFFECT_OFFSET_PROPERTY_NAME, EFFECT_OFFSET_DEFAULT); mEffectColorPropertyIndex = self.RegisterProperty(EFFECT_COLOR_PROPERTY_NAME, EFFECT_COLOR_DEFAULT); - mActorPostFilter.ApplyConstraint( Constraint::New( Actor::Property::POSITION, Source( self, mEffectOffsetPropertyIndex ), EqualToConstraint() ) ); - mActorPostFilter.ApplyConstraint( Constraint::New( Actor::Property::COLOR, Source( self, mEffectColorPropertyIndex ), EqualToConstraint() ) ); + + Constraint positionConstraint = Constraint::New( mActorPostFilter, Actor::Property::POSITION, EqualToConstraint() ); + positionConstraint.AddSource( Source( self, mEffectOffsetPropertyIndex ) ); + positionConstraint.Apply(); + + Constraint colorConstraint = Constraint::New( mActorPostFilter, Actor::Property::COLOR, EqualToConstraint() ); + colorConstraint.AddSource( Source( self, mEffectColorPropertyIndex ) ); + colorConstraint.Apply(); } void EffectsView::SetBackgroundColor( const Vector4& color ) diff --git a/dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp b/dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp index 5a5e501..8a38163 100644 --- a/dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp +++ b/dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp @@ -21,7 +21,6 @@ // EXTERNAL INCLUDES #include #include -#include #include #include #include @@ -139,7 +138,7 @@ GaussianBlurView::GaussianBlurView() GaussianBlurView::GaussianBlurView( const unsigned int numSamples, const float blurBellCurveWidth, const Pixel::Format renderTargetPixelFormat, const float downsampleWidthScale, const float downsampleHeightScale, bool blurUserImage) - : Control( CONTROL_BEHAVIOUR_NONE ) + : Control( NO_SIZE_NEGOTIATION ) , mNumSamples(numSamples) , mBlurBellCurveWidth( 0.001f ) , mPixelFormat(renderTargetPixelFormat) @@ -242,18 +241,6 @@ Vector4 GaussianBlurView::GetBackgroundColor() const // Private methods // -/** - * EqualToConstraintFloat - * - * f(current, property) = property - */ -struct EqualToConstraintFloat -{ - EqualToConstraintFloat(){} - - float operator()(const float current, const PropertyInput& property) {return property.GetFloat();} -}; - void GaussianBlurView::OnInitialize() { // root actor to parent all user added actors, needed to allow us to set that subtree as exclusive for our child render task @@ -279,12 +266,14 @@ void GaussianBlurView::OnInitialize() // Create an ImageActor for performing a horizontal blur on the texture mImageActorHorizBlur = ImageActor::New(); + mImageActorHorizBlur.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mImageActorHorizBlur.SetParentOrigin(ParentOrigin::CENTER); mImageActorHorizBlur.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME mImageActorHorizBlur.SetShaderEffect( mHorizBlurShader ); // Create an ImageActor for performing a vertical blur on the texture mImageActorVertBlur = ImageActor::New(); + mImageActorVertBlur.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mImageActorVertBlur.SetParentOrigin(ParentOrigin::CENTER); mImageActorVertBlur.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME mImageActorVertBlur.SetShaderEffect( mVertBlurShader ); @@ -296,15 +285,18 @@ void GaussianBlurView::OnInitialize() if(!mBlurUserImage) { mImageActorComposite = ImageActor::New(); + mImageActorComposite.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mImageActorComposite.SetParentOrigin(ParentOrigin::CENTER); mImageActorComposite.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME mImageActorComposite.SetOpacity(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH); // ensure alpha is enabled for this object and set default value - Constraint blurStrengthConstraint = Constraint::New( Actor::Property::COLOR_ALPHA, ParentSource(mBlurStrengthPropertyIndex), EqualToConstraintFloat()); - mImageActorComposite.ApplyConstraint(blurStrengthConstraint); + Constraint blurStrengthConstraint = Constraint::New( mImageActorComposite, Actor::Property::COLOR_ALPHA, EqualToConstraint()); + blurStrengthConstraint.AddSource( ParentSource(mBlurStrengthPropertyIndex) ); + blurStrengthConstraint.Apply(); // Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task mTargetActor = ImageActor::New(); + mTargetActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mTargetActor.SetParentOrigin(ParentOrigin::CENTER); mTargetActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME diff --git a/dali-toolkit/internal/controls/image-view/masked-image-view-impl.cpp b/dali-toolkit/internal/controls/image-view/masked-image-view-impl.cpp index 2dc796c..97c4053 100644 --- a/dali-toolkit/internal/controls/image-view/masked-image-view-impl.cpp +++ b/dali-toolkit/internal/controls/image-view/masked-image-view-impl.cpp @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include #include #include #include @@ -98,11 +97,6 @@ const char* const MASKED_IMAGE_VIEW_FRAGMENT_SOURCE = " gl_FragColor = texture2D(sTexture, vTexCoord) * vec4(1,1,1,mask.a); \n" "}"; -Vector2 EqualToConstraintVector2( const Vector2& current, const PropertyInput& property ) -{ - return property.GetVector2(); -} - Vector2 GetSizeForAspectRatio( const Vector2& targetSize, float aspectRatio ) { Vector2 sizeToKeepAspectRatio( targetSize ); @@ -545,9 +539,10 @@ void MaskedImageView::Initialize( unsigned int targetWidth, mRenderTask.SetInputEnabled( false ); mRenderTask.SetExclusive( true ); mRenderTask.SetClearEnabled( true ); - mRenderTask.ApplyConstraint( Constraint::New( RenderTask::Property::CLEAR_COLOR, - Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::BACKGROUND_COLOR ] ), - EqualToConstraint() ) ); + + Constraint clearColorConstraint = Constraint::New( mRenderTask, RenderTask::Property::CLEAR_COLOR, EqualToConstraint() ); + clearColorConstraint.AddSource( Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::BACKGROUND_COLOR ] ) ); + clearColorConstraint.Apply(); mRenderTask.FinishedSignal().Connect( this, &MaskedImageView::OnRenderTaskFinished ); // Edit mode initialization @@ -585,22 +580,26 @@ void MaskedImageView::ApplyMaskedImageShader( ImageRotation rotation ) ShaderEffect::GeometryHints( ShaderEffect::HINT_BLENDING ) ); shader.SetUniform( "uTargetSize", mTargetSize ); + shader.SetUniform( "uSourceSize", mTargetSize ); - shader.ApplyConstraint( Constraint::New( shader.GetPropertyIndex( "uSourceSize" ), - Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::SOURCE_SIZE ] ), - EqualToConstraintVector2 ) ); + Constraint sourceSizeConstraint = Constraint::New( shader, shader.GetPropertyIndex( "uSourceSize" ), EqualToConstraint() ); + sourceSizeConstraint.AddSource( Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::SOURCE_SIZE ] ) ); + sourceSizeConstraint.Apply(); + shader.SetUniform( "uSourceOffset", Vector2::ZERO ); - shader.ApplyConstraint( Constraint::New( shader.GetPropertyIndex( "uSourceOffset" ), - Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::SOURCE_OFFSET ] ), - EqualToConstraintVector2 ) ); + Constraint sourceOffsetConstraint = Constraint::New( shader, shader.GetPropertyIndex( "uSourceOffset" ), EqualToConstraint() ); + sourceOffsetConstraint.AddSource( Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::SOURCE_OFFSET ] ) ); + sourceOffsetConstraint.Apply(); + shader.SetUniform( "uMaskSize", mTargetSize ); - shader.ApplyConstraint( Constraint::New( shader.GetPropertyIndex( "uMaskSize" ), - Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::MASK_SIZE ] ), - EqualToConstraintVector2 ) ); + Constraint maskSizeConstraint = Constraint::New( shader, shader.GetPropertyIndex( "uMaskSize" ), EqualToConstraint() ); + maskSizeConstraint.AddSource( Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::MASK_SIZE ] ) ); + maskSizeConstraint.Apply(); + shader.SetUniform( "uMaskOffset", mTargetSize ); - shader.ApplyConstraint( Constraint::New( shader.GetPropertyIndex( "uMaskOffset" ), - Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::MASK_OFFSET ] ), - EqualToConstraintVector2 ) ); + Constraint maskOffsetConstraint = Constraint::New( shader, shader.GetPropertyIndex( "uMaskOffset" ), EqualToConstraint() ); + maskOffsetConstraint.AddSource( Source( self, mCustomProperties[ Dali::Toolkit::MaskedImageView::MASK_OFFSET ] ) ); + maskOffsetConstraint.Apply(); shader.SetEffectImage( mMaskImage ); mSourceImageActor.SetShaderEffect( shader ); diff --git a/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp b/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp index 37e5776..fc6f71a 100644 --- a/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp +++ b/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp @@ -19,7 +19,6 @@ #include // EXTERNAL INCLUDES -#include #include #include #include @@ -35,27 +34,6 @@ const char* DEFAULT_FRAME_IMAGE_PATH = DALI_IMAGE_DIR "magnifier-image-frame.png const float IMAGE_BORDER_INDENT = 14.0f; ///< Indent of border in pixels. -/** - * ImageBorderSizeConstraint - */ -struct ImageBorderSizeConstraint -{ - ImageBorderSizeConstraint() - : mSizeOffset(Vector3(IMAGE_BORDER_INDENT - 1, IMAGE_BORDER_INDENT - 1, 0.0f) * 2.0f) - { - } - - Vector3 operator()(const Vector3& current, - const PropertyInput& referenceSizeProperty) - { - const Vector3& referenceSize = referenceSizeProperty.GetVector3(); - - return referenceSize + mSizeOffset; - } - - Vector3 mSizeOffset; ///< The amount to offset the size from referenceSize -}; - struct CameraActorPositionConstraint { CameraActorPositionConstraint(const Vector2& stageSize, float defaultCameraDistance = 0.0f) @@ -64,14 +42,13 @@ struct CameraActorPositionConstraint { } - Vector3 operator()(const Vector3& current, - const PropertyInput& sourcePositionProperty) + void operator()( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& sourcePosition = sourcePositionProperty.GetVector3(); + const Vector3& sourcePosition = inputs[0]->GetVector3(); - return Vector3( sourcePosition.x + mStageSize.x * 0.5f, - sourcePosition.y + mStageSize.y * 0.5f, - sourcePosition.z + mDefaultCameraDistance); + current.x = sourcePosition.x + mStageSize.x * 0.5f; + current.y = sourcePosition.y + mStageSize.y * 0.5f; + current.z = sourcePosition.z + mDefaultCameraDistance; } Vector2 mStageSize; @@ -86,25 +63,18 @@ struct RenderTaskViewportPositionConstraint { } - Vector2 operator()(const Vector2& current, - const PropertyInput& positionProperty, - const PropertyInput& magnifierSizeProperty, - const PropertyInput& magnifierScaleProperty) + void operator()( Vector2& current, const PropertyInputContainer& inputs ) { - Vector2 position(positionProperty.GetVector3()); // World position? - - //position -= mStageSize * 0.5f; + current = inputs[0]->GetVector3(); // World position? // should be updated when: // Magnifier's world position/size/scale/parentorigin/anchorpoint changes. // or Magnifier camera's world position changes. - Vector3 size = magnifierSizeProperty.GetVector3() * magnifierScaleProperty.GetVector3(); + Vector3 size = inputs[1]->GetVector3() * inputs[2]->GetVector3(); /* magnifier-size * magnifier-scale */ // Reposition, and resize viewport to reflect the world bounds of this Magnifier actor. - position.x += (mStageSize.width - size.width) * 0.5f; - position.y += (mStageSize.height - size.height) * 0.5f; - - return position; + current.x += ( mStageSize.width - size.width ) * 0.5f; + current.y += ( mStageSize.height - size.height ) * 0.5f; } Vector2 mStageSize; @@ -116,11 +86,9 @@ struct RenderTaskViewportSizeConstraint { } - Vector2 operator()(const Vector2& current, - const PropertyInput& magnifierSizeProperty, - const PropertyInput& magnifierScaleProperty) + void operator()( Vector2& current, const PropertyInputContainer& inputs ) { - return Vector2(magnifierSizeProperty.GetVector3() * magnifierScaleProperty.GetVector3()); + current = inputs[0]->GetVector3() * inputs[1]->GetVector3(); /* magnifier-size * magnifier-scale */ } }; @@ -192,10 +160,9 @@ void Magnifier::Initialize() mSourceActor = Actor::New(); Stage().GetCurrent().Add(mSourceActor); mSourceActor.SetParentOrigin(ParentOrigin::CENTER); - Constraint constraint = Constraint::New( Actor::Property::POSITION, - Source( self, mPropertySourcePosition ), - EqualToConstraint() ); - mSourceActor.ApplyConstraint(constraint); + Constraint constraint = Constraint::New( mSourceActor, Actor::Property::POSITION, EqualToConstraint() ); + constraint.AddSource( Source( self, mPropertySourcePosition ) ); + constraint.Apply(); // create the render task this will render content on top of everything // based on camera source position. @@ -224,25 +191,22 @@ void Magnifier::Initialize() // at the end of the update cycle i.e. after constraints have been applied.) //Property::Index propertySourcePositionDelayed = mCameraActor.RegisterProperty("delayed-source-position", Vector3::ZERO); - constraint = Constraint::New( Actor::Property::POSITION, - Source( mSourceActor, Actor::Property::WORLD_POSITION ), - CameraActorPositionConstraint(stageSize, mDefaultCameraDistance) ); - mCameraActor.ApplyConstraint(constraint); + constraint = Constraint::New( mCameraActor, Actor::Property::POSITION, CameraActorPositionConstraint(stageSize, mDefaultCameraDistance) ); + constraint.AddSource( Source( mSourceActor, Actor::Property::WORLD_POSITION ) ); + constraint.Apply(); // Apply constraint to render-task viewport position - constraint = Constraint::New( RenderTask::Property::VIEWPORT_POSITION, - Source( self, Actor::Property::WORLD_POSITION ),//mPropertySourcePosition ), - Source( self, Actor::Property::SIZE ), - Source( self, Actor::Property::WORLD_SCALE ), - RenderTaskViewportPositionConstraint(stageSize) ); - mTask.ApplyConstraint(constraint); + constraint = Constraint::New( mTask, RenderTask::Property::VIEWPORT_POSITION, RenderTaskViewportPositionConstraint(stageSize) ); + constraint.AddSource( Source( self, Actor::Property::WORLD_POSITION ) ); + constraint.AddSource( Source( self, Actor::Property::SIZE ) ); + constraint.AddSource( Source( self, Actor::Property::WORLD_SCALE ) ); + constraint.Apply(); // Apply constraint to render-task viewport position - constraint = Constraint::New( RenderTask::Property::VIEWPORT_SIZE, - Source( self, Actor::Property::SIZE ), - Source( self, Actor::Property::WORLD_SCALE ), - RenderTaskViewportSizeConstraint() ); - mTask.ApplyConstraint(constraint); + constraint = Constraint::New( mTask, RenderTask::Property::VIEWPORT_SIZE, RenderTaskViewportSizeConstraint() ); + constraint.AddSource( Source( self, Actor::Property::SIZE ) ); + constraint.AddSource( Source( self, Actor::Property::WORLD_SCALE ) ); + constraint.Apply(); } Magnifier::~Magnifier() @@ -289,10 +253,9 @@ void Magnifier::SetFrameVisibility(bool visible) mFrame.SetPositionInheritanceMode(DONT_INHERIT_POSITION); mFrame.SetInheritScale(true); - Constraint constraint = Constraint::New( Actor::Property::POSITION, - ParentSource( Actor::Property::WORLD_POSITION ), - EqualToConstraint() ); - mFrame.ApplyConstraint( constraint ); + Constraint constraint = Constraint::New( mFrame, Actor::Property::POSITION, EqualToConstraint() ); + constraint.AddSource( ParentSource( Actor::Property::WORLD_POSITION ) ); + constraint.Apply(); mFrame.SetNinePatchBorder( Vector4::ONE * IMAGE_BORDER_INDENT ); self.Add(mFrame); diff --git a/dali-toolkit/internal/controls/navigation-frame/navigation-control-impl.cpp b/dali-toolkit/internal/controls/navigation-frame/navigation-control-impl.cpp index 91fb19f..26956dc 100644 --- a/dali-toolkit/internal/controls/navigation-frame/navigation-control-impl.cpp +++ b/dali-toolkit/internal/controls/navigation-frame/navigation-control-impl.cpp @@ -19,6 +19,7 @@ #include "navigation-control-impl.h" // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -264,11 +265,12 @@ void NavigationControl::OrientationChanged( int angle ) } } + Actor self = Self(); Animation animation = Animation::New( mOrientationAnimationDuration ); - animation.RotateTo( Self(), Degree( -angle ), Vector3::ZAXIS, mOrientationAnimationAlphaFunc ); + animation.AnimateTo( Property( self, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( -angle ) ), Vector3::ZAXIS ), mOrientationAnimationAlphaFunc ); animation.Play(); - Self().SetSize( targetSize ); + self.SetSize( targetSize ); RelayoutRequest(); } diff --git a/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.cpp b/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.cpp index 4e486ba..e8ce9e0 100644 --- a/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.cpp +++ b/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.cpp @@ -56,12 +56,8 @@ NavigationTitleBar::NavigationTitleBar(NavigationControl& naviControl, mTitleIconLayout= Toolkit::TableView::New( 3,2 ); SetFixedSizes(); - mTitle = Toolkit::TextView::New(); - mTitle.SetTextAlignment( Toolkit::Alignment::HorizontalLeft ); - mTitle.SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit); - mSubTitle = Toolkit::TextView::New(); - mSubTitle.SetTextAlignment( Toolkit::Alignment::HorizontalLeft ); - mSubTitle.SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit); + mTitle = Toolkit::TextLabel::New(); + mSubTitle = Toolkit::TextLabel::New(); } void NavigationTitleBar::Update( Toolkit::Page page ) @@ -113,8 +109,7 @@ void NavigationTitleBar::Update( Toolkit::Page page ) } // add title and subtitle(if exist) - mTitle.SetText( page.GetTitle() ); - mTitle.SetStyleToCurrentText(mCurrentStyle->titleTextStyle); + mTitle.SetProperty( Toolkit::TextLabel::Property::TEXT, page.GetTitle() ); if( page.GetSubTitle().empty() ) //display title { mTitleLayout.SetFixedHeight( 1,mCurrentStyle->titleHeightWithoutSubtitle - mCurrentStyle->subtitleHeight ); @@ -124,8 +119,7 @@ void NavigationTitleBar::Update( Toolkit::Page page ) { mTitleLayout.SetFixedHeight( 1, mCurrentStyle->titleHeightWithSubtitle ); mTitleLayout.AddChild( mTitle, Toolkit::TableView::CellPosition(1,0) ); - mSubTitle.SetText( page.GetSubTitle() ); - mSubTitle.SetStyleToCurrentText(mCurrentStyle->subtitleTextStyle); + mSubTitle.SetProperty( Toolkit::TextLabel::Property::TEXT, page.GetSubTitle() ); mTitleLayout.AddChild( mSubTitle, Toolkit::TableView::CellPosition(2,0) ); } diff --git a/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h b/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h index 0377a2e..c8200ed 100644 --- a/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h +++ b/dali-toolkit/internal/controls/navigation-frame/navigation-title-bar.h @@ -21,7 +21,7 @@ // INTERNAL INCLUDES #include #include -#include +#include #include #include @@ -81,8 +81,8 @@ private: Toolkit::TableView mTitleLayout; Toolkit::TableView mTitleIconLayout; - Toolkit::TextView mTitle; - Toolkit::TextView mSubTitle; + Toolkit::TextLabel mTitle; + Toolkit::TextLabel mSubTitle; }; diff --git a/dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h b/dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h index ecb3d3b..80603d8 100644 --- a/dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h +++ b/dali-toolkit/internal/controls/navigation-frame/navigation-tool-bar.h @@ -20,7 +20,6 @@ // INTERNAL INCLUDES #include -#include #include #include #include diff --git a/dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.cpp b/dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.cpp index 2f4ba6c..fc464ad 100644 --- a/dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.cpp +++ b/dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.cpp @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include #include #include #include @@ -80,17 +79,17 @@ struct OriginalCenterConstraint mDirection = offset / mDistance; } - Vector2 operator()(const Vector2& current, const PropertyInput& panDisplacement) + void operator()( Vector2& current, const PropertyInputContainer& inputs ) { - float displacement = panDisplacement.GetFloat(); + float displacement = inputs[0]->GetFloat(); if( displacement < mDistance ) { - return mOldCenter + mDirection * displacement; + current = mOldCenter + mDirection * displacement; } else { - return mNewCenter + Vector2(0.25f*(displacement-mDistance), 0.f); + current = mNewCenter + Vector2(0.25f*(displacement-mDistance), 0.f); } } @@ -114,22 +113,21 @@ struct RotationConstraint mStep = 1.f / pageWidth; mSign = isTurnBack ? -1.0f : 1.0f; mConst = isTurnBack ? -1.0f : 0.f; - mRotation = isTurnBack ? Quaternion( -Math::PI, Vector3::YAXIS ) : Quaternion( 0.f, Vector3::YAXIS ); + mRotation = isTurnBack ? Quaternion( Radian( -Math::PI ), Vector3::YAXIS ) : Quaternion( Radian(0.f), Vector3::YAXIS ); } - Quaternion operator()( const Quaternion& current, const PropertyInput& panDisplacement ) + void operator()( Quaternion& current, const PropertyInputContainer& inputs ) { - float displacement = panDisplacement.GetFloat(); - float angle; + float displacement = inputs[0]->GetFloat(); if( displacement < mDistance) { - return mRotation; + current = mRotation; } else { float coef = std::max(-1.0f, mStep*(mDistance-displacement)); - angle = Math::PI*( mConst + mSign*coef ); - return Quaternion( angle, Vector3::YAXIS ); + float angle = Math::PI * ( mConst + mSign * coef ); + current = Quaternion( Radian( angle ), Vector3::YAXIS ); } } @@ -148,22 +146,23 @@ struct RotationConstraint */ struct CurrentCenterConstraint { - CurrentCenterConstraint( float pageWidth) + CurrentCenterConstraint( float pageWidth ) : mPageWidth( pageWidth ) { mThres = pageWidth * PAGE_TURN_OVER_THRESHOLD_RATIO * 0.5f; } - Vector2 operator()( const Vector2& current, const PropertyInput& center, const PropertyInput& originalCenter ) + void operator()( Vector2& current, const PropertyInputContainer& inputs ) { - Vector2 centerPosition = center.GetVector2(); + const Vector2& centerPosition = inputs[0]->GetVector2(); if( centerPosition.x > 0.f ) { - return Vector2( mThres+centerPosition.x*0.5f , centerPosition.y); + current.x = mThres+centerPosition.x * 0.5f; + current.y = centerPosition.y; } else { - Vector2 centerOrigin = originalCenter.GetVector2(); + const Vector2& centerOrigin = inputs[1]->GetVector2(); Vector2 direction = centerOrigin - Vector2(mThres, centerPosition.y); float coef = 1.f+(centerPosition.x*2.f / mPageWidth); // Todo: when coef <= 0, the page is flat, slow down the last moment of the page stretch by 10 times to avoid a small bounce @@ -171,7 +170,7 @@ struct CurrentCenterConstraint { coef = (coef+0.225f)/10.0f; } - return centerOrigin - direction * coef; + current = centerOrigin - direction * coef; } } @@ -185,14 +184,13 @@ struct ShadowBlurStrengthConstraint : mThres( thres ) {} - float operator()( const float current, const PropertyInput& currentCenter, const PropertyInput& originalCenter, const PropertyInput& panDisplacement) + void operator()( float& blurStrength, const PropertyInputContainer& inputs ) { - float displacement = panDisplacement.GetFloat(); - float blurStrength; + float displacement = inputs[2]->GetFloat(); if( EqualsZero(displacement)) { - Vector2 cur = currentCenter.GetVector2(); - Vector2 ori = originalCenter.GetVector2(); + const Vector2& cur = inputs[0]->GetVector2(); + const Vector2& ori = inputs[1]->GetVector2(); blurStrength = 5.f*(ori-cur).Length() / mThres; } else @@ -201,7 +199,6 @@ struct ShadowBlurStrengthConstraint } blurStrength = blurStrength > 1.f ? 1.f : ( blurStrength < 0.f ? 0.f : blurStrength ); - return blurStrength; } float mThres; @@ -807,12 +804,12 @@ void PageTurnView::PanContinuing( const Vector2& gesturePosition ) mShadowView.RemoveConstraints(); Actor self = Self(); self.SetProperty( mPropertyPanDisplacement[mIndex], 0.f ); - Constraint shadowBlurStrengthConstraint = Constraint::New( mShadowView.GetBlurStrengthPropertyIndex(), - Source(mTurnEffect[mIndex], mTurnEffect[mIndex].GetPropertyIndex(mTurnEffect[mIndex].PageTurnEffect::GetCurrentCenterPropertyName())), - Source(mTurnEffect[mIndex], mTurnEffect[mIndex].GetPropertyIndex(mTurnEffect[mIndex].PageTurnEffect::GetOriginalCenterPropertyName())), - Source( self, mPropertyPanDisplacement[mIndex] ), - ShadowBlurStrengthConstraint( mPageSize.width*PAGE_TURN_OVER_THRESHOLD_RATIO ) ); - mShadowView.ApplyConstraint( shadowBlurStrengthConstraint ); + + Constraint shadowBlurStrengthConstraint = Constraint::New( mShadowView, mShadowView.GetBlurStrengthPropertyIndex(), ShadowBlurStrengthConstraint( mPageSize.width*PAGE_TURN_OVER_THRESHOLD_RATIO ) ); + shadowBlurStrengthConstraint.AddSource( Source(mTurnEffect[mIndex], mTurnEffect[mIndex].GetPropertyIndex(mTurnEffect[mIndex].PageTurnEffect::GetCurrentCenterPropertyName())) ); + shadowBlurStrengthConstraint.AddSource( Source(mTurnEffect[mIndex], mTurnEffect[mIndex].GetPropertyIndex(mTurnEffect[mIndex].PageTurnEffect::GetOriginalCenterPropertyName())) ); + shadowBlurStrengthConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) ); + shadowBlurStrengthConstraint.Apply(); } } else @@ -874,28 +871,24 @@ void PageTurnView::PanContinuing( const Vector2& gesturePosition ) /( offset.x*offset.x + offset.y*offset.y ); offset *= k; Actor self = Self(); - Source source(self, mPropertyPanDisplacement[mIndex]); Property::Index shaderOriginalCenterPropertyIndex = mTurnEffect[mIndex].GetPropertyIndex(mTurnEffect[mIndex].PageTurnEffect::GetOriginalCenterPropertyName()); - Constraint originalCenterConstraint = Constraint::New( shaderOriginalCenterPropertyIndex , - source, - OriginalCenterConstraint( mOriginalCenter, offset )); - mTurnEffect[mIndex].ApplyConstraint( originalCenterConstraint ); + Constraint originalCenterConstraint = Constraint::New( mTurnEffect[mIndex], shaderOriginalCenterPropertyIndex, OriginalCenterConstraint( mOriginalCenter, offset )); + originalCenterConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) ); + originalCenterConstraint.Apply(); Property::Index shaderCurrentCenterPropertyIndex = mTurnEffect[mIndex].GetPropertyIndex(mTurnEffect[mIndex].PageTurnEffect::GetCurrentCenterPropertyName()); - Constraint currentCenterConstraint = Constraint::New( shaderCurrentCenterPropertyIndex, - Source(self, mPropertyCurrentCenter[mIndex]), - Source(mTurnEffect[mIndex], shaderOriginalCenterPropertyIndex), - CurrentCenterConstraint(mPageSize.width)); - mTurnEffect[mIndex].ApplyConstraint( currentCenterConstraint ); + Constraint currentCenterConstraint = Constraint::New( mTurnEffect[mIndex], shaderCurrentCenterPropertyIndex, CurrentCenterConstraint(mPageSize.width)); + currentCenterConstraint.AddSource( Source(self, mPropertyCurrentCenter[mIndex]) ); + currentCenterConstraint.AddSource( Source(mTurnEffect[mIndex], shaderOriginalCenterPropertyIndex) ); + currentCenterConstraint.Apply(); GetImpl( mTurnEffect[mIndex] ).ApplyInternalConstraint(); float distance = offset.Length(); - Constraint rotationConstraint = Constraint::New( Actor::Property::ORIENTATION, - Source( self, mPropertyPanDisplacement[mIndex] ), - RotationConstraint(distance, mPageSize.width, mIsTurnBack[mPanActor])); - mPanActor.ApplyConstraint( rotationConstraint ); + Constraint rotationConstraint = Constraint::New( mPanActor, Actor::Property::ORIENTATION, RotationConstraint(distance, mPageSize.width, mIsTurnBack[mPanActor])); + rotationConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) ); + rotationConstraint.Apply(); mConstraints = false; } diff --git a/dali-toolkit/internal/controls/popup/popup-impl.cpp b/dali-toolkit/internal/controls/popup/popup-impl.cpp index 7b8e420..a5aed9b 100755 --- a/dali-toolkit/internal/controls/popup/popup-impl.cpp +++ b/dali-toolkit/internal/controls/popup/popup-impl.cpp @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -121,14 +122,14 @@ void Popup::OnInitialize() Actor self = Self(); self.SetSensitive(false); // Reisize to fit the height of children - self.SetResizePolicy( FIT_TO_CHILDREN, HEIGHT ); + self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::HEIGHT ); // Create Layer mLayer = Layer::New(); mLayer.SetName( "POPUP_LAYER" ); mLayer.SetParentOrigin(ParentOrigin::CENTER); mLayer.SetAnchorPoint(AnchorPoint::CENTER); - mLayer.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mLayer.SetDrawMode( DrawMode::OVERLAY ); // Any content after this point which is added to Self() will be reparented to @@ -147,8 +148,8 @@ void Popup::OnInitialize() mPopupLayout.SetName( "POPUP_LAYOUT_TABLE" ); mPopupLayout.SetParentOrigin(ParentOrigin::CENTER); mPopupLayout.SetAnchorPoint(AnchorPoint::CENTER); - mPopupLayout.SetResizePolicy( FILL_TO_PARENT, WIDTH ); - mPopupLayout.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT ); + mPopupLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); + mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); mPopupLayout.SetFitHeight( 0 ); // Set row to fit mPopupLayout.SetFitHeight( 1 ); // Set row to fit self.Add( mPopupLayout ); @@ -223,11 +224,10 @@ void Popup::SetBackgroundImage( Actor image ) // OnDialogTouched only consume the event. It prevents the touch event to be caught by the backing. mBackgroundImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched ); - mBackgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mBackgroundImage.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS ); mBackgroundImage.SetAnchorPoint( AnchorPoint::CENTER ); mBackgroundImage.SetParentOrigin( ParentOrigin::CENTER ); - mBackgroundImage.SetSizeMode( SIZE_FIXED_OFFSET_FROM_PARENT ); Vector3 border( mPopupStyle->backgroundOuterBorder.x, mPopupStyle->backgroundOuterBorder.z, 0.0f ); mBackgroundImage.SetSizeModeFactor( border ); @@ -251,7 +251,7 @@ void Popup::SetButtonAreaImage( Actor image ) // OnDialogTouched only consume the event. It prevents the touch event to be caught by the backing. mButtonAreaImage.TouchedSignal().Connect( this, &Popup::OnDialogTouched ); - mButtonAreaImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mButtonAreaImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mButtonAreaImage.SetAnchorPoint( AnchorPoint::CENTER ); mButtonAreaImage.SetParentOrigin( ParentOrigin::CENTER ); @@ -263,41 +263,36 @@ void Popup::SetButtonAreaImage( Actor image ) void Popup::SetTitle( const std::string& text ) { - Toolkit::TextView titleActor = Toolkit::TextView::New(); - titleActor.SetName( "POPUP_TITLE" ); - titleActor.SetText( text ); - titleActor.SetColor( Color::BLACK ); - titleActor.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); - titleActor.SetWidthExceedPolicy( Toolkit::TextView::Split ); - titleActor.SetLineJustification( Toolkit::TextView::Center ); - - SetTitle( titleActor ); -} - -void Popup::SetTitle( Toolkit::TextView titleActor ) -{ // Replaces the current title actor. if( mPopupLayout ) { mPopupLayout.RemoveChildAt( Toolkit::TableView::CellPosition( 0, 0 ) ); } - mTitle = titleActor; + mTitle = Toolkit::TextLabel::New( text ); + mTitle.SetName( "POPUP_TITLE" ); + mTitle.SetProperty( Toolkit::TextLabel::Property::MULTI_LINE, true ); + mTitle.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); if( mPopupLayout ) { mTitle.SetPadding( Padding( 0.0f, 0.0f, mPopupStyle->margin, mPopupStyle->margin ) ); - mTitle.SetResizePolicy( FILL_TO_PARENT, WIDTH ); - mTitle.SetDimensionDependency( HEIGHT, WIDTH ); // HeightForWidth + mTitle.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); + mTitle.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); mPopupLayout.AddChild( mTitle, Toolkit::TableView::CellPosition( 0, 0 ) ); } RelayoutRequest(); } -Toolkit::TextView Popup::GetTitle() const +std::string Popup::GetTitle() const { - return mTitle; + if( mTitle ) + { + return mTitle.GetProperty( Toolkit::TextLabel::Property::TEXT ); + } + + return std::string(); } void Popup::CreateFooter() @@ -308,7 +303,7 @@ void Popup::CreateFooter() mBottomBg = Actor::New(); mBottomBg.SetName( "POPUP_BOTTOM_BG" ); mBottomBg.SetRelayoutEnabled( true ); - mBottomBg.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mBottomBg.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mPopupLayout.SetFixedHeight( 2, mPopupStyle->bottomSize.height ); // Buttons mPopupLayout.AddChild( mBottomBg, Toolkit::TableView::CellPosition( 2, 0 ) ); @@ -318,7 +313,7 @@ void Popup::CreateFooter() void Popup::AddButton( Toolkit::Button button ) { mButtons.push_back( button ); - button.SetResizePolicy( USE_ASSIGNED_SIZE, ALL_DIMENSIONS ); // Size will be assigned to it + button.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::ALL_DIMENSIONS ); // Size will be assigned to it // If this is the first button added if( mButtons.size() == 1 ) @@ -428,7 +423,7 @@ void Popup::CreateBacking() mBacking = Dali::Toolkit::CreateSolidColorActor( mPopupStyle->backingColor ); mBacking.SetName( "POPUP_BACKING" ); - mBacking.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mBacking.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mBacking.SetSensitive(true); mLayer.Add( mBacking ); @@ -693,23 +688,23 @@ void Popup::OnRelayout( const Vector2& size, RelayoutContainer& container ) } } -void Popup::OnSetResizePolicy( ResizePolicy policy, Dimension dimension ) +void Popup::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) { if( mPopupLayout ) { - if( policy == FIT_TO_CHILDREN ) + if( policy == ResizePolicy::FIT_TO_CHILDREN ) { - mPopupLayout.SetResizePolicy( USE_NATURAL_SIZE, dimension ); - if( dimension & HEIGHT ) + mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, dimension ); + if( dimension & Dimension::HEIGHT ) { mPopupLayout.SetFitHeight( 1 ); } } else { - mPopupLayout.SetResizePolicy( FILL_TO_PARENT, dimension ); + mPopupLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, dimension ); // Make the content cell fill the whole of the available space - if( dimension & HEIGHT ) + if( dimension & Dimension::HEIGHT ) { mPopupLayout.SetRelativeHeight( 1, 1.0f ); } @@ -748,7 +743,7 @@ Vector3 Popup::GetNaturalSize() const float titleBuffer = 0.5f; titleNaturalSize.width += titleBuffer; - // As TextView GetNaturalSize does not take wrapping into account, limit the width + // As TextLabel GetNaturalSize does not take wrapping into account, limit the width // to that of the stage if( titleNaturalSize.width >= maxWidth) { diff --git a/dali-toolkit/internal/controls/popup/popup-impl.h b/dali-toolkit/internal/controls/popup/popup-impl.h index ec85966..f695c74 100755 --- a/dali-toolkit/internal/controls/popup/popup-impl.h +++ b/dali-toolkit/internal/controls/popup/popup-impl.h @@ -28,6 +28,7 @@ #include #include #include +#include namespace Dali { @@ -84,14 +85,9 @@ public: void SetTitle( const std::string& text ); /** - * @copydoc Toolkit::Popup::SetTitle( TextView titleActor ) - */ - void SetTitle( Toolkit::TextView titleActor ); - - /** * @copydoc Toolkit::Popup::GetTitle */ - Toolkit::TextView GetTitle() const; + std::string GetTitle() const; /** * @copydoc Toolkit::Popup::AddButton @@ -263,7 +259,7 @@ private: /** * @copydoc Control::OnSetResizePolicy() */ - virtual void OnSetResizePolicy( ResizePolicy policy, Dimension dimension ); + virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ); /** * @copydoc Control::OnKeyEvent() @@ -325,7 +321,7 @@ private: Actor mBackgroundImage; ///< Stores the background image. Actor mButtonAreaImage; ///< Stores the button background image. - Toolkit::TextView mTitle; ///< Stores the text title. + Toolkit::TextLabel mTitle; ///< Stores the text title. Actor mContent; ///< Stores popup's content. Actor mBottomBg; ///< bottom button bar background. ImageActor is replaced with Actor due to hidden image. Actor mTailImage; ///< Stores the tail image diff --git a/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp b/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp index bae2b78..0d7b833 100755 --- a/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp +++ b/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.cpp @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -71,24 +72,21 @@ struct IndicatorPositionConstraint /** * Constraint operator - * @param[in] current The current indicator position - * @param[in] indicatorSizeProperty The size of indicator. - * @param[in] parentSizeProperty The parent size of indicator. - * @param[in] scrollPositionProperty The scroll position of the scrollable container // (from 0.0 -> 1.0 in each axis) + * @param[in,out] current The current indicator position + * @param[in] inputs Contains the size of indicator, the size of indicator's parent, and the scroll position of the scrollable container (from 0.0 -> 1.0 in each axis) * @return The new indicator position is returned. */ - Vector3 operator()(const Vector3& current, - const PropertyInput& indicatorSizeProperty, - const PropertyInput& parentSizeProperty, - const PropertyInput& scrollPositionProperty) + void operator()( Vector3& current, const PropertyInputContainer& inputs ) { - Vector3 indicatorSize = indicatorSizeProperty.GetVector3(); - Vector3 parentSize = parentSizeProperty.GetVector3(); - float scrollPosition = scrollPositionProperty.GetFloat(); + const Vector3& indicatorSize = inputs[0]->GetVector3(); + const Vector3& parentSize = inputs[1]->GetVector3(); + float scrollPosition = inputs[2]->GetFloat(); const float domainSize = fabs(mMaxPosition - mMinPosition); float relativePosition = (mMaxPosition - scrollPosition) / domainSize; - return Vector3(current.x, relativePosition * (parentSize.height - indicatorSize.height), DEFAULT_SLIDER_DEPTH); + + current.y = relativePosition * ( parentSize.height - indicatorSize.height ); + current.z = DEFAULT_SLIDER_DEPTH; } float mMinPosition; ///< The minimum scroll position @@ -198,13 +196,6 @@ void ScrollBar::ApplyConstraints() { if( mScrollConnector ) { - Constraint constraint; - - if(mIndicatorSizeConstraint) - { - mIndicator.RemoveConstraint(mIndicatorSizeConstraint); - } - // Set indicator height according to the indicator's height policy if(mIndicatorHeightPolicy == Toolkit::ScrollBar::Fixed) { @@ -217,15 +208,14 @@ void ScrollBar::ApplyConstraints() if(mIndicatorPositionConstraint) { - mIndicator.RemoveConstraint(mIndicatorPositionConstraint); + mIndicatorPositionConstraint.Remove(); } - constraint = Constraint::New( Actor::Property::POSITION, - LocalSource( Actor::Property::SIZE ), - ParentSource( Actor::Property::SIZE ), - Source( mScrollPositionObject, Toolkit::ScrollConnector::SCROLL_POSITION ), - IndicatorPositionConstraint( mScrollConnector.GetMinLimit(), mScrollConnector.GetMaxLimit() ) ); - mIndicatorPositionConstraint = mIndicator.ApplyConstraint( constraint ); + mIndicatorPositionConstraint = Constraint::New( mIndicator, Actor::Property::POSITION, IndicatorPositionConstraint( mScrollConnector.GetMinLimit(), mScrollConnector.GetMaxLimit() ) ); + mIndicatorPositionConstraint.AddSource( LocalSource( Actor::Property::SIZE ) ); + mIndicatorPositionConstraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + mIndicatorPositionConstraint.AddSource( Source( mScrollPositionObject, Toolkit::ScrollConnector::SCROLL_POSITION ) ); + mIndicatorPositionConstraint.Apply(); } } @@ -250,6 +240,8 @@ void ScrollBar::OnScrollPositionNotified(PropertyNotification& source) void ScrollBar::Show() { + Actor self = Self(); + // Cancel any animation if(mAnimation) { @@ -260,17 +252,19 @@ void ScrollBar::Show() if(mIndicatorShowDuration > 0.0f) { mAnimation = Animation::New( mIndicatorShowDuration ); - mAnimation.OpacityTo( Self(), 1.0f, AlphaFunctions::EaseIn ); + mAnimation.AnimateTo( Property( self, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunctions::EaseIn ); mAnimation.Play(); } else { - Self().SetOpacity(1.0f); + self.SetOpacity(1.0f); } } void ScrollBar::Hide() { + Actor self = Self(); + // Cancel any animation if(mAnimation) { @@ -281,12 +275,12 @@ void ScrollBar::Hide() if(mIndicatorHideDuration > 0.0f) { mAnimation = Animation::New( mIndicatorHideDuration ); - mAnimation.OpacityTo( Self(), 0.0f, AlphaFunctions::EaseIn ); + mAnimation.AnimateTo( Property( self, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunctions::EaseIn ); mAnimation.Play(); } else { - Self().SetOpacity(0.0f); + self.SetOpacity(0.0f); } } diff --git a/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.h b/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.h index 6826c0e..f6e85dd 100755 --- a/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.h +++ b/dali-toolkit/internal/controls/scroll-bar/scroll-bar-impl.h @@ -21,7 +21,7 @@ // EXTERNAL INCLUDES #include #include -#include +#include #include #include @@ -258,8 +258,7 @@ private: ScrollPositionNotifiedSignalType mScrollPositionNotifiedSignal; - ActiveConstraint mIndicatorSizeConstraint; - ActiveConstraint mIndicatorPositionConstraint; + Constraint mIndicatorPositionConstraint; }; } // namespace Internal diff --git a/dali-toolkit/internal/controls/scroll-component/scroll-bar-internal-impl.cpp b/dali-toolkit/internal/controls/scroll-component/scroll-bar-internal-impl.cpp index 1dfced0..4b7760e 100755 --- a/dali-toolkit/internal/controls/scroll-component/scroll-bar-internal-impl.cpp +++ b/dali-toolkit/internal/controls/scroll-component/scroll-bar-internal-impl.cpp @@ -19,7 +19,6 @@ #include // EXTERNAL INCLUDES -#include #include #include #include @@ -59,11 +58,9 @@ const int SECOND_UNIT(1000); * ScrollBarInternal Visibility Constraint * Returns whether scroll bar is visible */ -bool ScrollBarInternalVisibilityConstraint(const bool& current, - const PropertyInput& canScrollProperty) +void ScrollBarInternalVisibilityConstraint( bool& current, const PropertyInputContainer& inputs ) { - bool canScroll = canScrollProperty.GetBoolean(); - return canScroll; + current = inputs[0]->GetBoolean(); } /** @@ -83,35 +80,26 @@ struct ScrollBarInternalSizeConstraint /** * Constraint operator - * @param[in] current The current ScrollBarInternal size - * @param[in] scrollMinProperty The container's minimum position. - * @param[in] scrollMaxProperty The container's maximum position. - * @param[in] scrollDirectionProperty The container's scroll direction. - * @param[in] scrollSizeProperty The container's size of viewport. + * @param[in,out] current The current ScrollBarInternal size + * @param[in] inputs Contains the container's minimum position, its maximum position, its scroll direction & its size of viewport. * @return The new ScrollBarInternal position is returned. */ - Vector3 operator()(const Vector3& current, - const PropertyInput& scrollMinProperty, - const PropertyInput& scrollMaxProperty, - const PropertyInput& scrollDirectionProperty, - const PropertyInput& scrollSizeProperty) + void operator()( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& min = scrollMinProperty.GetVector3(); - const Vector3& max = scrollMaxProperty.GetVector3(); - const Vector3& scrollDirection = scrollDirectionProperty.GetVector3(); + const Vector3& min = inputs[0]->GetVector3(); + const Vector3& max = inputs[1]->GetVector3(); + const Vector3& scrollDirection = inputs[2]->GetVector3(); const Toolkit::ControlOrientation::Type& orientation = static_cast(scrollDirection.z); - const Vector3& size = scrollSizeProperty.GetVector3(); + const Vector3& size = inputs[3]->GetVector3(); const Vector3 domainSize = max - min; if (mVertical && Toolkit::IsVertical(orientation)) { - float mod = fabsf(domainSize.height) > size.height ? size.height * ( size.height / fabsf(domainSize.height) ) : size.height * ( (size.height - fabsf(domainSize.height * 0.5f)) / size.height); - return Vector3( current.width, mod, current.depth ); + current.height = fabsf(domainSize.height) > size.height ? size.height * ( size.height / fabsf(domainSize.height) ) : size.height * ( (size.height - fabsf(domainSize.height * 0.5f)) / size.height); } else { - float mod = fabsf(domainSize.height) > size.width ? size.width * ( size.width / fabsf(domainSize.height) ) : size.width * ( (size.width - fabsf(domainSize.height * 0.5f)) / size.width); - return Vector3( current.width, mod, current.depth ); + current.height = fabsf(domainSize.height) > size.width ? size.width * ( size.width / fabsf(domainSize.height) ) : size.width * ( (size.width - fabsf(domainSize.height * 0.5f)) / size.width); } } @@ -135,23 +123,22 @@ struct ScrollBarInternalRotationConstraint /** * Constraint operator - * @param[in] current The current ScrollBarInternal rotation + * @param[in,out] current The current ScrollBarInternal rotation * @param[in] scrollDirectionProperty The container's scroll direction. * @return The new ScrollBarInternal rotation is returned. */ - Quaternion operator()(const Quaternion& current, - const PropertyInput& scrollDirectionProperty) + void operator()( Quaternion& current, const PropertyInputContainer& inputs ) { - const Vector3& scrollDirection = scrollDirectionProperty.GetVector3(); + const Vector3& scrollDirection = inputs[0]->GetVector3(); const Toolkit::ControlOrientation::Type& orientation = static_cast(scrollDirection.z); if( (mVertical && Toolkit::IsVertical(orientation)) || (!mVertical && Toolkit::IsHorizontal(orientation)) ) { - return Quaternion(0.0f, Vector3::ZAXIS); + current = Quaternion( Radian( 0.0f ), Vector3::ZAXIS ); } else { - return Quaternion(0.5f * Math::PI, Vector3::ZAXIS); + current = Quaternion( Radian( 0.5f * Math::PI ), Vector3::ZAXIS); } } @@ -178,29 +165,24 @@ struct ScrollBarInternalPositionConstraint /** * Constraint operator - * @param[in] current The current ScrollBarInternal position - * @param[in] scrollBarSizeProperty ScrollBarInternal size - * @param[in] scrollRelativePositionProperty The container's relative position (from 0.0 -> 1.0 in each axis) - * @param[in] scrollMinProperty The container's minimum position. - * @param[in] scrollMaxProperty The container's maximum position. - * @param[in] scrollDirectionProperty The container's scroll direction. - * @param[in] scrollSizeProperty The container's size of viewport. + * @param[in] finalPosition The current ScrollBarInternal position + * @param[in] inputs Contains: + * The ScrollBarInternal size, + * The container's relative position (from 0.0 -> 1.0 in each axis), + * The container's minimum position, + * The container's maximum position, + * The container's scroll direction, + * The container's size of viewport. * @return The new ScrollBarInternal position is returned. */ - Vector3 operator()(const Vector3& current, - const PropertyInput& scrollBarSizeProperty, - const PropertyInput& scrollRelativePositionProperty, - const PropertyInput& scrollMinProperty, - const PropertyInput& scrollMaxProperty, - const PropertyInput& scrollDirectionProperty, - const PropertyInput& scrollSizeProperty) + void operator()( Vector3& finalPosition, const PropertyInputContainer& inputs ) { - Vector3 barSize = scrollBarSizeProperty.GetVector3(); - Vector3 relativePosition = scrollRelativePositionProperty.GetVector3(); - Vector3 size = scrollSizeProperty.GetVector3(); - const Vector3& min = scrollMinProperty.GetVector3(); - const Vector3& max = scrollMaxProperty.GetVector3(); - const Vector3& scrollDirection = scrollDirectionProperty.GetVector3(); + const Vector3& barSize = inputs[0]->GetVector3(); + const Vector3& relativePosition = inputs[1]->GetVector3(); + const Vector3& min = inputs[2]->GetVector3(); + const Vector3& max = inputs[3]->GetVector3(); + const Vector3& scrollDirection = inputs[4]->GetVector3(); + const Vector3& size = inputs[5]->GetVector3(); const Toolkit::ControlOrientation::Type& orientation = static_cast(scrollDirection.z); Vector3 domainSize = max - min; @@ -256,7 +238,7 @@ struct ScrollBarInternalPositionConstraint Vector3 maskedRelativePosition = Toolkit::IsVertical(orientation) ? Vector3(relativePosition.x * (size.x-barSize.y), relativePosition.y * (size.y-barSize.y), 0.0f) * mask : Vector3(relativePosition.y * (size.x-barSize.y), relativePosition.x * (size.y-barSize.y), 0.0f) * mask; - Vector3 finalPosition = relativeOffset * size + absoluteOffset + maskedRelativePosition; + finalPosition = relativeOffset * size + absoluteOffset + maskedRelativePosition; // If Wrapped Slider, then position 1 domain either before or after current slider. if(mWrap) @@ -279,8 +261,6 @@ struct ScrollBarInternalPositionConstraint finalPosition.y -= size.y; } } - - return finalPosition; } bool mVertical; ///< Whether vertical or horizontal. @@ -308,17 +288,14 @@ struct ScrollBarInternalHitSizeConstraint /** * Constraint operator * @param[in] current The current HitSize - * @param[in] scrollDirectionProperty The container's scroll direction. - * @param[in] scrollSizeProperty The container's size of viewport. + * @param[in] inputs Contains the container's scroll direction and size of its viewport. * @return The new ScrollBarInternal Hit Area size is returned. */ - Vector3 operator()(const Vector3& current, - const PropertyInput& scrollDirectionProperty, - const PropertyInput& scrollSizeProperty) + void operator()( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& scrollDirection = scrollDirectionProperty.GetVector3(); + const Vector3& scrollDirection = inputs[0]->GetVector3(); const Toolkit::ControlOrientation::Type& orientation = static_cast(scrollDirection.z); - Vector3 size = scrollSizeProperty.GetVector3(); + const Vector3& size = inputs[1]->GetVector3(); Vector3 mask; // Mask size aspect of hit area. Vector3 offset; // Add Offset size. @@ -334,7 +311,7 @@ struct ScrollBarInternalHitSizeConstraint offset = Vector3::YAXIS * mThickness; } - return size * mask + offset; + current = size * mask + offset; } bool mVertical; ///< Whether vertical or horizontal. @@ -392,47 +369,47 @@ ScrollBarInternal::ScrollBarInternal(Toolkit::Scrollable& container, bool vertic // target the container to observe for scrolling Actor target = mContainer.Self(); - Constraint constraint = Constraint::New( Actor::Property::VISIBLE, - Source( target, vertical ? target.GetPropertyIndex(Scrollable::SCROLLABLE_CAN_SCROLL_VERTICAL) : target.GetPropertyIndex(Scrollable::SCROLLABLE_CAN_SCROLL_HORIZONTAL)), - ScrollBarInternalVisibilityConstraint ); - mSlider.ApplyConstraint( constraint ); - mSliderWrap.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::SIZE, - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ), - Source( target, Actor::Property::SIZE ), - ScrollBarInternalSizeConstraint( vertical ) ); - mSlider.ApplyConstraint( constraint ); - mSliderWrap.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::ORIENTATION, - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ), - ScrollBarInternalRotationConstraint( vertical ) ); - mSlider.ApplyConstraint( constraint ); - mSliderWrap.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::POSITION, - Source( mSlider, Actor::Property::SIZE), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_RELATIVE_POSITION_PROPERTY_NAME ) ), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ), - Source( target, Actor::Property::SIZE ), - ScrollBarInternalPositionConstraint(vertical) ); - - mSlider.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::POSITION, - Source( mSlider, Actor::Property::SIZE), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_RELATIVE_POSITION_PROPERTY_NAME ) ), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ), - Source( target, Actor::Property::SIZE ), - ScrollBarInternalPositionConstraint(vertical, true) ); - mSliderWrap.ApplyConstraint( constraint ); + Constraint constraint = Constraint::New( mSlider, Actor::Property::VISIBLE, ScrollBarInternalVisibilityConstraint ); + constraint.AddSource( Source( target, vertical ? Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL : Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL ) ); + constraint.Apply(); + + constraint = constraint.Clone( mSliderWrap ); + constraint.Apply(); + + constraint = Constraint::New( mSlider, Actor::Property::SIZE, ScrollBarInternalSizeConstraint( vertical ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_DIRECTION ) ); + constraint.AddSource( Source( target, Actor::Property::SIZE ) ); + constraint.Apply(); + + constraint = constraint.Clone( mSliderWrap ); + constraint.Apply(); + + constraint = Constraint::New( mSlider, Actor::Property::ORIENTATION, ScrollBarInternalRotationConstraint( vertical ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_DIRECTION ) ); + constraint.Apply(); + + constraint = constraint.Clone( mSliderWrap ); + constraint.Apply(); + + constraint = Constraint::New( mSlider, Actor::Property::POSITION, ScrollBarInternalPositionConstraint(vertical) ); + constraint.AddSource( Source( mSlider, Actor::Property::SIZE) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_DIRECTION ) ); + constraint.AddSource( Source( target, Actor::Property::SIZE ) ); + constraint.Apply(); + + constraint = Constraint::New( mSliderWrap, Actor::Property::POSITION, ScrollBarInternalPositionConstraint(vertical, true) ); + constraint.AddSource( Source( mSlider, Actor::Property::SIZE) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_DIRECTION ) ); + constraint.AddSource( Source( target, Actor::Property::SIZE ) ); + constraint.Apply(); // Add Sliders to internal Actor, to avoid mixing up with regular // Actors added by user. @@ -446,11 +423,10 @@ ScrollBarInternal::ScrollBarInternal(Toolkit::Scrollable& container, bool vertic mHitArea.SetPosition(0.0f, 0.0f, 0.2f); mContainer.AddOverlay( mHitArea ); - constraint = Constraint::New( Actor::Property::SIZE, - Source( target, target.GetPropertyIndex( Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME ) ), - Source( target, Actor::Property::SIZE ), - ScrollBarInternalHitSizeConstraint(vertical, BAR_TAB_SIZE.width) ); - mHitArea.ApplyConstraint( constraint ); + constraint = Constraint::New( mHitArea, Actor::Property::SIZE, ScrollBarInternalHitSizeConstraint(vertical, BAR_TAB_SIZE.width) ); + constraint.AddSource( Source( target, Toolkit::Scrollable::Property::SCROLL_DIRECTION ) ); + constraint.AddSource( Source( target, Actor::Property::SIZE ) ); + constraint.Apply(); if(vertical) { @@ -558,8 +534,8 @@ void ScrollBarInternal::Show() } mAnimation = Animation::New( BAR_SHOW_TIME ); - mAnimation.OpacityTo( mSlider, 1.0f, AlphaFunctions::EaseIn ); - mAnimation.OpacityTo( mSliderWrap, 1.0f, AlphaFunctions::EaseIn ); + mAnimation.AnimateTo( Property( mSlider, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunctions::EaseIn ); + mAnimation.AnimateTo( Property( mSliderWrap, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunctions::EaseIn ); mAnimation.Play(); DestructTimer(); @@ -575,8 +551,8 @@ void ScrollBarInternal::Hide() } mAnimation = Animation::New( BAR_HIDE_TIME ); - mAnimation.OpacityTo( mSlider, 0.0f, AlphaFunctions::EaseIn ); - mAnimation.OpacityTo( mSliderWrap, 0.0f, AlphaFunctions::EaseIn ); + mAnimation.AnimateTo( Property( mSlider, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunctions::EaseIn ); + mAnimation.AnimateTo( Property( mSliderWrap, Actor::Property::COLOR_ALPHA ), 0.0f, AlphaFunctions::EaseIn ); mAnimation.Play(); } diff --git a/dali-toolkit/internal/controls/scrollable/bouncing-effect-actor.cpp b/dali-toolkit/internal/controls/scrollable/bouncing-effect-actor.cpp new file mode 100644 index 0000000..5ea5753 --- /dev/null +++ b/dali-toolkit/internal/controls/scrollable/bouncing-effect-actor.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2014 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ +// Bouncing effect is presented by stacked three layers with same color and opacity +const size_t NUM_LAYERS( 3 ); +const Vector3 LAYER_HEIGHTS( 1.f, 27.f/42.f, 13.f/42.f); + +// use the actor color to paint every layer +const char* MESH_FRAGMENT_SHADER = +"void main()\n" +"{\n" +" gl_FragColor = uColor;\n" +"}\n"; + +// Constraint to move the vertices vertically +struct VertexPositionConstraint +{ + VertexPositionConstraint( float initialY, float range ) + : mInitialY( initialY ), + mRange( range ) + { + } + + void operator()( Vector3& current, const PropertyInputContainer& inputs ) + { + current.y = mInitialY + mRange * fabsf( inputs[0]->GetFloat() ); + } + + float mInitialY; + float mRange; +}; + +} // namespace Anon + +Actor CreateBouncingEffectActor( Property::Index& bouncePropertyIndex ) +{ + Dali::AnimatableMesh mesh; + Dali::MeshActor meshActor; + + Dali::AnimatableMesh::Faces faces; + faces.reserve( NUM_LAYERS * 6 ); // 2 triangles per layer + for( size_t i=0; i( i ); // the interval between each layer is 0.01 + mesh[j ].SetPosition( Vector3( -0.5f, -0.5f, positionZ ) ); + mesh[j+1].SetPosition( Vector3( 0.5f, -0.5f, positionZ ) ); + mesh[j+2].SetPosition( Vector3( -0.5f, -0.5f, positionZ ) ); + mesh[j+3].SetPosition( Vector3( 0.5f, -0.5f, positionZ ) ); + } + + meshActor = Dali::MeshActor::New(mesh); + + Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( "", MESH_FRAGMENT_SHADER, + GEOMETRY_TYPE_UNTEXTURED_MESH, + Dali::ShaderEffect::HINT_BLENDING ); + meshActor.SetShaderEffect(shaderEffect); + + // To control the movement of all vertices with one custom property + bouncePropertyIndex = meshActor.RegisterProperty("BounceCoeffcient", 0.f); + for( size_t i=0;i( mesh, mesh.GetPropertyIndex(j+2, AnimatableVertex::Property::POSITION ), VertexPositionConstraint(-0.5f, LAYER_HEIGHTS[i]) ); + constraint.AddSource( Source(meshActor, bouncePropertyIndex) ); + constraint.Apply(); + + constraint = Constraint::New( mesh, mesh.GetPropertyIndex(j+3, AnimatableVertex::Property::POSITION), VertexPositionConstraint(-0.5f, LAYER_HEIGHTS[i]) ); + constraint.AddSource( Source(meshActor, bouncePropertyIndex) ); + constraint.Apply(); + } + + return meshActor; +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/scrollable/bouncing-effect-actor.h b/dali-toolkit/internal/controls/scrollable/bouncing-effect-actor.h new file mode 100644 index 0000000..0fd1b69 --- /dev/null +++ b/dali-toolkit/internal/controls/scrollable/bouncing-effect-actor.h @@ -0,0 +1,69 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_BOUNCING_EFFECT_ACTOR_H__ +#define __DALI_TOOLKIT_INTERNAL_BOUNCING_EFFECT_ACTOR_H__ + +/* + * Copyright (c) 2014 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 +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * @brief Creates a Dali::Actor to display the bouncing effect for overshoot + * + * Usage example: + * @code + * // create the actor and get the property index for animation + * Property::Index bouncePropertyIndex = Property::INVALID_INDEX; + * Actor bounceActor = CreateBouncingEffectActor( bouncePropertyIndex ); + + * // set size and color + * bounceActor.SetSize(720.f, 42.f ); + * bounceActor.SetColor( Vector4( 0.0,0.64f,0.85f,0.25f ) ); + * + * // add to stage + * bounceActor.SetParentOrigin(ParentOrigin::CENTER); + * Stage::GetCurrent().Add(bounceActor); + + * // start the bouncing animation + * Animation anim = Animation::New(2.0f); + * anim.AnimateTo( Property( bounceActor, bouncePropertyIndex ), 1.f, AlphaFunctions::Sin ); + * anim.Play(); + * @endcode + * + * @param[out] bouncePropertyIndex The property index which controls the bouncing + * @return The actor which displays the bouncing effect + */ +Actor CreateBouncingEffectActor( Property::Index& bouncePropertyIndex); + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + + +#endif /* __DALI_TOOLKIT_INTERNAL_BOUNCING_EFFECT_ACTOR_H__ */ diff --git a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp index f27dc2f..a3f222e 100644 --- a/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.cpp @@ -19,8 +19,8 @@ #include // EXTERNAL INCLUDES +#include // for strcmp #include -#include #include #include #include @@ -32,6 +32,7 @@ // INTERNAL INCLUDES #include +#include #include using std::string; @@ -86,202 +87,165 @@ float CalculateScrollDistance(Vector2 panDistance, Toolkit::ItemLayout& layout) } // Overshoot overlay constraints - -struct OvershootOverlaySizeConstraint +void OvershootOverlaySizeConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - Vector3 operator()(const Vector3& current, - const PropertyInput& parentScrollDirectionProperty, - const PropertyInput& parentOvershootProperty, - const PropertyInput& parentSizeProperty) - { - const Vector3 parentScrollDirection = parentScrollDirectionProperty.GetVector3(); - const Vector3 parentSize = parentSizeProperty.GetVector3(); - const Toolkit::ControlOrientation::Type& parentOrientation = static_cast(parentScrollDirection.z); + const Vector3& parentScrollDirection = inputs[0]->GetVector3(); + const Vector3& parentSize = inputs[1]->GetVector3(); + const Toolkit::ControlOrientation::Type& parentOrientation = static_cast(parentScrollDirection.z); - float overlayWidth; - - if(Toolkit::IsVertical(parentOrientation)) - { - overlayWidth = fabsf(parentScrollDirection.y) > Math::MACHINE_EPSILON_1 ? parentSize.x : parentSize.y; - } - else - { - overlayWidth = fabsf(parentScrollDirection.x) > Math::MACHINE_EPSILON_1 ? parentSize.y : parentSize.x; - } - - float overlayHeight = (overlayWidth > OVERSHOOT_BOUNCE_ACTOR_RESIZE_THRESHOLD) ? OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height : OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height*0.5f; - - return Vector3( overlayWidth, overlayHeight, current.depth ); + if(Toolkit::IsVertical(parentOrientation)) + { + current.width = fabsf(parentScrollDirection.y) > Math::MACHINE_EPSILON_1 ? parentSize.x : parentSize.y; + } + else + { + current.width = fabsf(parentScrollDirection.x) > Math::MACHINE_EPSILON_1 ? parentSize.y : parentSize.x; } -}; -struct OvershootOverlayRotationConstraint + current.height = ( current.width > OVERSHOOT_BOUNCE_ACTOR_RESIZE_THRESHOLD ) ? OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height : OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height*0.5f; +} + +void OvershootOverlayRotationConstraint( Quaternion& current, const PropertyInputContainer& inputs ) { - Quaternion operator()(const Quaternion& current, - const PropertyInput& parentScrollDirectionProperty, - const PropertyInput& parentOvershootProperty) - { - const Vector3 parentScrollDirection = parentScrollDirectionProperty.GetVector3(); - const float parentOvershoot = parentOvershootProperty.GetFloat(); - const Toolkit::ControlOrientation::Type& parentOrientation = static_cast(parentScrollDirection.z); + const Vector3& parentScrollDirection = inputs[0]->GetVector3(); + const float parentOvershoot = inputs[1]->GetFloat(); + const Toolkit::ControlOrientation::Type& parentOrientation = static_cast(parentScrollDirection.z); - float multiplier = 0; - if(Toolkit::IsVertical(parentOrientation)) + float multiplier = 0; + if(Toolkit::IsVertical(parentOrientation)) + { + if(fabsf(parentScrollDirection.y) <= Math::MACHINE_EPSILON_1) { - if(fabsf(parentScrollDirection.y) <= Math::MACHINE_EPSILON_1) + if( (parentOrientation == Toolkit::ControlOrientation::Up && parentOvershoot < Math::MACHINE_EPSILON_0) + || (parentOrientation == Toolkit::ControlOrientation::Down && parentOvershoot > Math::MACHINE_EPSILON_0) ) { - if( (parentOrientation == Toolkit::ControlOrientation::Up && parentOvershoot < Math::MACHINE_EPSILON_0) - || (parentOrientation == Toolkit::ControlOrientation::Down && parentOvershoot > Math::MACHINE_EPSILON_0) ) - { - multiplier = 0.5f; - } - else - { - multiplier = 1.5f; - } - } - else if( (parentOvershoot > Math::MACHINE_EPSILON_0 && parentScrollDirection.y > Math::MACHINE_EPSILON_0) - || (parentOvershoot < Math::MACHINE_EPSILON_0 && parentScrollDirection.y < Math::MACHINE_EPSILON_0) ) - { - multiplier = 0.0f; + multiplier = 0.5f; } else { - multiplier = 1.0f; + multiplier = 1.5f; } } + else if( (parentOvershoot > Math::MACHINE_EPSILON_0 && parentScrollDirection.y > Math::MACHINE_EPSILON_0) + || (parentOvershoot < Math::MACHINE_EPSILON_0 && parentScrollDirection.y < Math::MACHINE_EPSILON_0) ) + { + multiplier = 0.0f; + } else { - if(fabsf(parentScrollDirection.x) <= Math::MACHINE_EPSILON_1) - { - if( (parentOrientation == Toolkit::ControlOrientation::Left && parentOvershoot > Math::MACHINE_EPSILON_0) - ||(parentOrientation == Toolkit::ControlOrientation::Right && parentOvershoot < Math::MACHINE_EPSILON_0) ) - { - multiplier = 1.0f; - } - else - { - multiplier = 0.0f; - } - } - else if( (parentOvershoot > Math::MACHINE_EPSILON_0 && parentScrollDirection.x > Math::MACHINE_EPSILON_0) - || (parentOvershoot < Math::MACHINE_EPSILON_0 && parentScrollDirection.x < Math::MACHINE_EPSILON_0) ) + multiplier = 1.0f; + } + } + else + { + if(fabsf(parentScrollDirection.x) <= Math::MACHINE_EPSILON_1) + { + if( (parentOrientation == Toolkit::ControlOrientation::Left && parentOvershoot > Math::MACHINE_EPSILON_0) + ||(parentOrientation == Toolkit::ControlOrientation::Right && parentOvershoot < Math::MACHINE_EPSILON_0) ) { - multiplier = 1.5f; + multiplier = 1.0f; } else { - multiplier = 0.5f; + multiplier = 0.0f; } } - - Quaternion rotation( Radian( multiplier * Math::PI ), Vector3::ZAXIS ); - - return rotation; + else if( (parentOvershoot > Math::MACHINE_EPSILON_0 && parentScrollDirection.x > Math::MACHINE_EPSILON_0) + || (parentOvershoot < Math::MACHINE_EPSILON_0 && parentScrollDirection.x < Math::MACHINE_EPSILON_0) ) + { + multiplier = 1.5f; + } + else + { + multiplier = 0.5f; + } } -}; -struct OvershootOverlayPositionConstraint + current = Quaternion( Radian( multiplier * Math::PI ), Vector3::ZAXIS ); +} + +void OvershootOverlayPositionConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - Vector3 operator()(const Vector3& current, - const PropertyInput& parentSizeProperty, - const PropertyInput& parentScrollDirectionProperty, - const PropertyInput& parentOvershootProperty) - { - const Vector3 parentScrollDirection = parentScrollDirectionProperty.GetVector3(); - const float parentOvershoot = parentOvershootProperty.GetFloat(); - const Vector3 parentSize = parentSizeProperty.GetVector3(); - const Toolkit::ControlOrientation::Type& parentOrientation = static_cast(parentScrollDirection.z); + const Vector3& parentSize = inputs[0]->GetVector3(); + const Vector3& parentScrollDirection = inputs[1]->GetVector3(); + const float parentOvershoot = inputs[2]->GetFloat(); + const Toolkit::ControlOrientation::Type& parentOrientation = static_cast(parentScrollDirection.z); - Vector3 relativeOffset; + Vector3 relativeOffset; - if(Toolkit::IsVertical(parentOrientation)) + if(Toolkit::IsVertical(parentOrientation)) + { + if(fabsf(parentScrollDirection.y) <= Math::MACHINE_EPSILON_1) { - if(fabsf(parentScrollDirection.y) <= Math::MACHINE_EPSILON_1) + if( (parentOrientation == Toolkit::ControlOrientation::Up && parentOvershoot < Math::MACHINE_EPSILON_0) + || (parentOrientation == Toolkit::ControlOrientation::Down && parentOvershoot > Math::MACHINE_EPSILON_0) ) { - if( (parentOrientation == Toolkit::ControlOrientation::Up && parentOvershoot < Math::MACHINE_EPSILON_0) - || (parentOrientation == Toolkit::ControlOrientation::Down && parentOvershoot > Math::MACHINE_EPSILON_0) ) - { - relativeOffset = Vector3(1.0f, 0.0f, 0.0f); - } - else - { - relativeOffset =Vector3(0.0f, 1.0f, 0.0f); - } - } - else if( (parentOvershoot > Math::MACHINE_EPSILON_0 && parentScrollDirection.y > Math::MACHINE_EPSILON_0) - || (parentOvershoot < Math::MACHINE_EPSILON_0 && parentScrollDirection.y < Math::MACHINE_EPSILON_0) ) - { - relativeOffset = Vector3(0.0f, 0.0f, 0.0f); + relativeOffset = Vector3(1.0f, 0.0f, 0.0f); } else { - relativeOffset = Vector3(1.0f, 1.0f, 0.0f); + relativeOffset =Vector3(0.0f, 1.0f, 0.0f); } } + else if( (parentOvershoot > Math::MACHINE_EPSILON_0 && parentScrollDirection.y > Math::MACHINE_EPSILON_0) + || (parentOvershoot < Math::MACHINE_EPSILON_0 && parentScrollDirection.y < Math::MACHINE_EPSILON_0) ) + { + relativeOffset = Vector3(0.0f, 0.0f, 0.0f); + } else { - if(fabsf(parentScrollDirection.x) <= Math::MACHINE_EPSILON_1) - { - if( (parentOrientation == Toolkit::ControlOrientation::Left && parentOvershoot < Math::MACHINE_EPSILON_0) - || (parentOrientation == Toolkit::ControlOrientation::Right && parentOvershoot > Math::MACHINE_EPSILON_0) ) - { - relativeOffset = Vector3(0.0f, 0.0f, 0.0f); - } - else - { - relativeOffset = Vector3(1.0f, 1.0f, 0.0f); - } - } - else if( (parentOvershoot > Math::MACHINE_EPSILON_0 && parentScrollDirection.x > Math::MACHINE_EPSILON_0) - || (parentOvershoot < Math::MACHINE_EPSILON_0 && parentScrollDirection.x < Math::MACHINE_EPSILON_0) ) + relativeOffset = Vector3(1.0f, 1.0f, 0.0f); + } + } + else + { + if(fabsf(parentScrollDirection.x) <= Math::MACHINE_EPSILON_1) + { + if( (parentOrientation == Toolkit::ControlOrientation::Left && parentOvershoot < Math::MACHINE_EPSILON_0) + || (parentOrientation == Toolkit::ControlOrientation::Right && parentOvershoot > Math::MACHINE_EPSILON_0) ) { - relativeOffset = Vector3(0.0f, 1.0f, 0.0f); + relativeOffset = Vector3(0.0f, 0.0f, 0.0f); } else { - relativeOffset = Vector3(1.0f, 0.0f, 0.0f); + relativeOffset = Vector3(1.0f, 1.0f, 0.0f); } } - - return relativeOffset * parentSize; - + else if( (parentOvershoot > Math::MACHINE_EPSILON_0 && parentScrollDirection.x > Math::MACHINE_EPSILON_0) + || (parentOvershoot < Math::MACHINE_EPSILON_0 && parentScrollDirection.x < Math::MACHINE_EPSILON_0) ) + { + relativeOffset = Vector3(0.0f, 1.0f, 0.0f); + } + else + { + relativeOffset = Vector3(1.0f, 0.0f, 0.0f); + } } -}; -struct OvershootOverlayVisibilityConstraint -{ - bool operator()(const bool& current, - const PropertyInput& parentLayoutScrollableProperty) - { - const bool parentLayoutScrollable = parentLayoutScrollableProperty.GetBoolean(); + current = relativeOffset * parentSize; +} - return parentLayoutScrollable; - } -}; +void OvershootOverlayVisibilityConstraint( bool& current, const PropertyInputContainer& inputs ) +{ + current = inputs[0]->GetBoolean(); +} /** * Relative position Constraint * Generates the relative position value of the item view based on the layout position, * and it's relation to the layout domain. This is a value from 0.0f to 1.0f in each axis. */ -Vector3 RelativePositionConstraint(const Vector3& current, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollMinProperty, - const PropertyInput& scrollMaxProperty, - const PropertyInput& layoutSizeProperty) +void RelativePositionConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& position = Vector3(0.0f, scrollPositionProperty.GetFloat(), 0.0f); - const Vector3& min = scrollMinProperty.GetVector3(); - const Vector3& max = scrollMaxProperty.GetVector3(); + const Vector3& position = Vector3(0.0f, inputs[0]->GetFloat(), 0.0f); + const Vector3& min = inputs[1]->GetVector3(); + const Vector3& max = inputs[2]->GetVector3(); - Vector3 relativePosition; Vector3 domainSize = max - min; - relativePosition.x = fabsf(domainSize.x) > Math::MACHINE_EPSILON_1 ? ((min.x - position.x) / fabsf(domainSize.x)) : 0.0f; - relativePosition.y = fabsf(domainSize.y) > Math::MACHINE_EPSILON_1 ? ((min.y - position.y) / fabsf(domainSize.y)) : 0.0f; - - return relativePosition; + current.x = fabsf(domainSize.x) > Math::MACHINE_EPSILON_1 ? ((min.x - position.x) / fabsf(domainSize.x)) : 0.0f; + current.y = fabsf(domainSize.y) > Math::MACHINE_EPSILON_1 ? ((min.y - position.y) / fabsf(domainSize.y)) : 0.0f; + current.z = 0.0f; } } // unnamed namespace @@ -361,8 +325,6 @@ ItemView::ItemView(ItemFactory& factory) void ItemView::OnInitialize() { - RegisterCommonProperties(); - Actor self = Self(); // Disable size negotiation for item views @@ -378,13 +340,11 @@ void ItemView::OnInitialize() EnableScrollComponent(Toolkit::Scrollable::OvershootIndicator); - Constraint constraint = Constraint::New(mPropertyRelativePosition, - LocalSource(mPropertyPosition), - LocalSource(mPropertyPositionMin), - LocalSource(mPropertyPositionMax), - LocalSource(Actor::Property::SIZE), - RelativePositionConstraint); - self.ApplyConstraint(constraint); + Constraint constraint = Constraint::New( self, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION, RelativePositionConstraint ); + constraint.AddSource( LocalSource( mPropertyPosition ) ); + constraint.AddSource( LocalSource( Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( LocalSource( Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.Apply(); Vector2 stageSize = Stage::GetCurrent().GetSize(); mMouseWheelScrollDistanceStep = stageSize.y * DEFAULT_MOUSE_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION; @@ -472,8 +432,7 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz if(mActiveLayout->GetItemSize(itemId, targetSize, size)) { // resize immediately - actor.SetResizePolicy( FIXED, ALL_DIMENSIONS ); - actor.SetPreferredSize( size.GetVectorXY() ); + actor.SetSize( size.GetVectorXY() ); } mActiveLayout->ApplyConstraints(actor, itemId, durationSeconds, mScrollPositionObject, Self() ); @@ -519,7 +478,7 @@ void ItemView::ActivateLayout(unsigned int layoutIndex, const Vector3& targetSiz Radian scrollDirection(mActiveLayout->GetScrollDirection()); float orientation = static_cast(mActiveLayout->GetOrientation()); - self.SetProperty(mPropertyScrollDirection, Vector3(sinf(scrollDirection), cosf(scrollDirection), orientation)); + self.SetProperty(Toolkit::Scrollable::Property::SCROLL_DIRECTION, Vector3(sinf(scrollDirection), cosf(scrollDirection), orientation)); self.SetProperty(mPropertyScrollSpeed, mScrollSpeed); @@ -995,8 +954,7 @@ void ItemView::SetupActor( Item item, float durationSeconds ) Vector3 size; if( mActiveLayout->GetItemSize( item.first, mActiveLayoutTargetSize, size ) ) { - item.second.SetResizePolicy( FIXED, ALL_DIMENSIONS ); - item.second.SetPreferredSize( size.GetVectorXY() ); + item.second.SetSize( size.GetVectorXY() ); } mActiveLayout->ApplyConstraints( item.second, item.first, durationSeconds, mScrollPositionObject, Self() ); @@ -1454,22 +1412,22 @@ void ItemView::CalculateDomainSize(const Vector3& layoutSize) if(IsHorizontal(mActiveLayout->GetOrientation())) { - self.SetProperty(mPropertyPositionMin, Vector3(0.0f, firstItemPosition.x, 0.0f)); - self.SetProperty(mPropertyPositionMax, Vector3(0.0f, lastItemPosition.x, 0.0f)); + self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN, Vector3(0.0f, firstItemPosition.x, 0.0f)); + self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX, Vector3(0.0f, lastItemPosition.x, 0.0f)); domainSize = fabs(firstItemPosition.x - lastItemPosition.x); } else { - self.SetProperty(mPropertyPositionMin, Vector3(0.0f, firstItemPosition.y, 0.0f)); - self.SetProperty(mPropertyPositionMax, Vector3(0.0f, lastItemPosition.y, 0.0f)); + self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN, Vector3(0.0f, firstItemPosition.y, 0.0f)); + self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX, Vector3(0.0f, lastItemPosition.y, 0.0f)); domainSize = fabs(firstItemPosition.y - lastItemPosition.y); } mScrollConnector.SetScrollDomain(minLayoutPosition, 0.0f, domainSize); bool isLayoutScrollable = IsLayoutScrollable(layoutSize); - self.SetProperty(mPropertyCanScrollVertical, isLayoutScrollable); - self.SetProperty(mPropertyCanScrollHorizontal, false); + self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, isLayoutScrollable); + self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, false); } } @@ -1477,8 +1435,8 @@ Vector3 ItemView::GetDomainSize() const { Actor self = Self(); - float minScrollPosition = self.GetProperty(mPropertyPositionMin); - float maxScrollPosition = self.GetProperty(mPropertyPositionMax); + float minScrollPosition = self.GetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN); + float maxScrollPosition = self.GetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX); return Vector3(0.0f, fabs(maxScrollPosition - minScrollPosition), 0.0f); } @@ -1557,37 +1515,38 @@ void ItemView::SetOvershootEnabled( bool enable ) if( enable ) { Property::Index effectOvershootPropertyIndex = Property::INVALID_INDEX; + mOvershootOverlay = CreateBouncingEffectActor( effectOvershootPropertyIndex ); + mOvershootOverlay.SetColor(mOvershootEffectColor); + mOvershootOverlay.SetParentOrigin(ParentOrigin::TOP_LEFT); + mOvershootOverlay.SetAnchorPoint(AnchorPoint::TOP_LEFT); + mOvershootOverlay.SetDrawMode(DrawMode::OVERLAY); + self.Add(mOvershootOverlay); + + Constraint constraint = Constraint::New( mOvershootOverlay, Actor::Property::SIZE, OvershootOverlaySizeConstraint ); + constraint.AddSource( ParentSource( Toolkit::Scrollable::Property::SCROLL_DIRECTION ) ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.Apply(); - Constraint constraint = Constraint::New( Actor::Property::SIZE, - ParentSource( mPropertyScrollDirection ), - Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ), - ParentSource( Actor::Property::SIZE ), - OvershootOverlaySizeConstraint() ); - mOvershootOverlay.ApplyConstraint(constraint); mOvershootOverlay.SetSize(OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.width, OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height); - constraint = Constraint::New( Actor::Property::ORIENTATION, - ParentSource( mPropertyScrollDirection ), - Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ), - OvershootOverlayRotationConstraint() ); - mOvershootOverlay.ApplyConstraint(constraint); - - constraint = Constraint::New( Actor::Property::POSITION, - ParentSource( Actor::Property::SIZE ), - ParentSource( mPropertyScrollDirection ), - Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ), - OvershootOverlayPositionConstraint() ); - mOvershootOverlay.ApplyConstraint(constraint); - - constraint = Constraint::New( Actor::Property::VISIBLE, - ParentSource( mPropertyCanScrollVertical ), - OvershootOverlayVisibilityConstraint() ); - mOvershootOverlay.ApplyConstraint(constraint); - - constraint = Constraint::New( effectOvershootPropertyIndex, - Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ), - EqualToConstraint() ); - mOvershootOverlay.ApplyConstraint(constraint); + constraint = Constraint::New( mOvershootOverlay, Actor::Property::ORIENTATION, OvershootOverlayRotationConstraint ); + constraint.AddSource( ParentSource( Toolkit::Scrollable::Property::SCROLL_DIRECTION ) ); + constraint.AddSource( Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ) ); + constraint.Apply(); + + constraint = Constraint::New( mOvershootOverlay, Actor::Property::POSITION, OvershootOverlayPositionConstraint ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.AddSource( ParentSource( Toolkit::Scrollable::Property::SCROLL_DIRECTION ) ); + constraint.AddSource( Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ) ); + constraint.Apply(); + + constraint = Constraint::New( mOvershootOverlay, Actor::Property::VISIBLE, OvershootOverlayVisibilityConstraint ); + constraint.AddSource( ParentSource( Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL ) ); + constraint.Apply(); + + constraint = Constraint::New( mOvershootOverlay, effectOvershootPropertyIndex, EqualToConstraint() ); + constraint.AddSource( Source( mScrollPositionObject, ScrollConnector::OVERSHOOT ) ); + constraint.Apply(); } else { @@ -1635,7 +1594,12 @@ void ItemView::AnimateScrollOvershoot(float overshootAmount, bool animateBack) if(mOvershootAnimationSpeed > Math::MACHINE_EPSILON_0) { float currentOvershoot = mScrollPositionObject.GetProperty(ScrollConnector::OVERSHOOT); - float duration = mOvershootOverlay.GetCurrentSize().height * (animatingOn ? (1.0f - fabsf(currentOvershoot)) : fabsf(currentOvershoot)) / mOvershootAnimationSpeed; + float duration = 0.0f; + + if (mOvershootOverlay) + { + duration = mOvershootOverlay.GetCurrentSize().height * (animatingOn ? (1.0f - fabsf(currentOvershoot)) : fabsf(currentOvershoot)) / mOvershootAnimationSpeed; + } RemoveAnimation(mScrollOvershootAnimation); mScrollOvershootAnimation = Animation::New(duration); diff --git a/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.cpp index 613b0e8..a789981 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-connector-impl.cpp @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include // for strcmp #include #include #include diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-base-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-base-impl.cpp index 60cb127..44ceade 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-base-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-base-impl.cpp @@ -33,23 +33,9 @@ namespace Internal // ScrollBase /////////////////////////////////////////////////////////////////////////////////////////////////// -const char* const ScrollBase::SCROLL_DOMAIN_OFFSET_PROPERTY_NAME = "domain-offset"; - ScrollBase::ScrollBase() : Scrollable(), mParent(NULL), - mPropertyTime(Property::INVALID_INDEX), - mPropertyPrePosition(Property::INVALID_INDEX), - mPropertyPosition(Property::INVALID_INDEX), - mPropertyOvershootX(Property::INVALID_INDEX), - mPropertyOvershootY(Property::INVALID_INDEX), - mPropertyWrap(Property::INVALID_INDEX), - mPropertyPanning(Property::INVALID_INDEX), - mPropertyScrolling(Property::INVALID_INDEX), - mPropertyFinal(Property::INVALID_INDEX), - mPropertyDomainOffset(Property::INVALID_INDEX), - mPropertyPositionDelta(Property::INVALID_INDEX), - mPropertyScrollStartPagePosition(Property::INVALID_INDEX), mDelay(0.0f) { } @@ -59,28 +45,6 @@ void ScrollBase::SetParent(ScrollBase *parent) mParent = parent; } -void ScrollBase::RegisterProperties() -{ - Actor self = Self(); - - // Register common properties - RegisterCommonProperties(); - - // Register Scroll Properties. - mPropertyTime = self.RegisterProperty(Toolkit::ScrollView::SCROLL_TIME_PROPERTY_NAME, 0.0f); - mPropertyPrePosition = self.RegisterProperty(Toolkit::ScrollView::SCROLL_PRE_POSITION_PROPERTY_NAME, Vector3::ZERO); - mPropertyPosition = self.RegisterProperty(Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME, Vector3::ZERO); - mPropertyOvershootX = self.RegisterProperty(Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME, 0.0f); - mPropertyOvershootY = self.RegisterProperty(Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME, 0.0f); - mPropertyFinal = self.RegisterProperty(Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME, Vector3::ZERO); - mPropertyWrap = self.RegisterProperty(Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME, false); - mPropertyPanning = self.RegisterProperty(Toolkit::ScrollView::SCROLL_PANNING_PROPERTY_NAME, false); - mPropertyScrolling = self.RegisterProperty(Toolkit::ScrollView::SCROLL_SCROLLING_PROPERTY_NAME, false); - mPropertyDomainOffset = self.RegisterProperty(SCROLL_DOMAIN_OFFSET_PROPERTY_NAME, Vector3::ZERO); - mPropertyPositionDelta = self.RegisterProperty(Toolkit::ScrollView::SCROLL_POSITION_DELTA_PROPERTY_NAME, Vector3::ZERO); - mPropertyScrollStartPagePosition = self.RegisterProperty(Toolkit::ScrollView::SCROLL_START_PAGE_POSITION_PROPERTY_NAME, Vector3::ZERO); -} - void ScrollBase::BindActor(Actor child) { FindAndUnbindActor(child); diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-base-impl.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-base-impl.h index 968e3ab..d4fe048 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-base-impl.h +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-base-impl.h @@ -21,7 +21,6 @@ // EXTERNAL INCLUDES // TODO - Replace list with dali-vector.h #include -#include #include // INTERNAL INCLUDES @@ -79,8 +78,9 @@ public: */ void ApplyConstraint(Constraint constraint) { - ActiveConstraint activeConstraint = mActor.ApplyConstraint( constraint ); - mConstraints.push_back( activeConstraint ); + Constraint clone = constraint.Clone( mActor ); + clone.Apply(); + mConstraints.push_back( clone ); } /** @@ -90,17 +90,17 @@ public: */ void RemoveConstraints() { - std::vector::iterator it = mConstraints.begin(); - std::vector::iterator end = mConstraints.end(); + std::vector::iterator it = mConstraints.begin(); + std::vector::iterator end = mConstraints.end(); for(;it!=end;++it) { - mActor.RemoveConstraint(*it); + it->Remove(); } mConstraints.clear(); } Actor mActor; ///< The Actor that this ActorInfo represents. - std::vector mConstraints; ///< A list keeping track of constraints applied to the actor via this delegate. + std::vector mConstraints; ///< A list keeping track of constraints applied to the actor via this delegate. }; typedef IntrusivePtr ActorInfoPtr; @@ -191,26 +191,9 @@ protected: */ ScrollBase(); - /** - * 2nd-phase initialization. - */ - void RegisterProperties(); - protected: ScrollBase *mParent; ///< Pointer to ScrollBase parent, if exists. - Property::Index mPropertyTime; ///< Scroll Time (0 to animationDuration while animating, otherwise 0) - Property::Index mPropertyPrePosition; ///< Scroll Position ("scroll-position") [function of scroll-x, scroll-y] - Property::Index mPropertyPosition; ///< Scroll Position ("scroll-position") [function of scroll-pre-position] - Property::Index mPropertyOvershootX; ///< Scroll Overshoot ("scroll-overshoot-x") [function of scroll-pre-position, scroll-position] - Property::Index mPropertyOvershootY; ///< Scroll Overshoot ("scroll-overshoot-y") [function of scroll-pre-position, scroll-position] - Property::Index mPropertyWrap; ///< Scroll Wrap ("scroll-wrap") - Property::Index mPropertyPanning; ///< Whether we are panning - Property::Index mPropertyScrolling; ///< Whether we are scrolling - Property::Index mPropertyFinal; ///< Scroll Final Position ("scroll-final") [scroll-position + f(scroll-overshoot)] - Property::Index mPropertyDomainOffset; ///< Scroll Domain Offset ("scroll-domain-offset") keeps track of scroll position as it wraps domains - Property::Index mPropertyPositionDelta; ///< Scroll Position Delta ("scroll-position-delta") - Property::Index mPropertyScrollStartPagePosition; ///< Scroll Start Page Position ("scroll-start-page-position") private: diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.cpp index 3a9d9b9..0d2e728 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.cpp @@ -18,11 +18,9 @@ // CLASS HEADER #include -// EXTERNAL INCLUDES -#include - // INTERNAL INCLUDES #include +#include #include using namespace Dali; @@ -145,26 +143,50 @@ ScrollOvershootEffectRipple::ScrollOvershootEffectRipple( bool vertical, Scrolla mOvershoot(0.0f), mAnimationStateFlags(0) { + mOvershootOverlay = CreateBouncingEffectActor(mEffectOvershootProperty); + mOvershootOverlay.SetColor(mAttachedScrollView.GetOvershootEffectColor()); + mOvershootOverlay.SetParentOrigin(ParentOrigin::TOP_LEFT); + mOvershootOverlay.SetAnchorPoint(AnchorPoint::TOP_LEFT); + mOvershootOverlay.SetDrawMode(DrawMode::OVERLAY); + mOvershootOverlay.SetVisible(false); } void ScrollOvershootEffectRipple::Apply() { Actor self = mAttachedScrollView.Self(); - mOvershootProperty = self.GetPropertyIndex(IsVertical() ? Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME : Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME); + mOvershootProperty = IsVertical() ? Toolkit::ScrollView::Property::OVERSHOOT_Y : Toolkit::ScrollView::Property::OVERSHOOT_X; // make sure height is set, since we only create a constraint for image width + mOvershootOverlay.SetSize(OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.width, OVERSHOOT_BOUNCE_ACTOR_DEFAULT_SIZE.height); + mAttachedScrollView.AddOverlay(mOvershootOverlay); UpdatePropertyNotifications(); } void ScrollOvershootEffectRipple::Remove( Scrollable& scrollable ) { + if(mOvershootOverlay) + { + if(mOvershootIncreaseNotification) + { + scrollable.Self().RemovePropertyNotification(mOvershootIncreaseNotification); + mOvershootIncreaseNotification.Reset(); + } + if(mOvershootDecreaseNotification) + { + scrollable.Self().RemovePropertyNotification(mOvershootDecreaseNotification); + mOvershootDecreaseNotification.Reset(); + } + scrollable.RemoveOverlay(mOvershootOverlay); + } } void ScrollOvershootEffectRipple::Reset() { + mOvershootOverlay.SetVisible(false); + mOvershootOverlay.SetProperty( mEffectOvershootProperty, 0.f); } void ScrollOvershootEffectRipple::UpdatePropertyNotifications() @@ -211,10 +233,59 @@ void ScrollOvershootEffectRipple::UpdatePropertyNotifications() void ScrollOvershootEffectRipple::SetOvershootEffectColor( const Vector4& color ) { + if(mOvershootOverlay) + { + mOvershootOverlay.SetColor(color); + } } void ScrollOvershootEffectRipple::UpdateVisibility( bool visible ) { + mOvershootOverlay.SetVisible(visible); + // make sure overshoot image is correctly placed + if( visible ) + { + Actor self = mAttachedScrollView.Self(); + if(mOvershoot > 0.0f) + { + // positive overshoot + const Vector3 size = mOvershootOverlay.GetCurrentSize(); + Vector3 relativeOffset; + const Vector3 parentSize = self.GetCurrentSize(); + if(IsVertical()) + { + mOvershootOverlay.SetOrientation( Quaternion( Radian( 0.0f ), Vector3::ZAXIS ) ); + mOvershootOverlay.SetSize(parentSize.width, GetBounceActorHeight(parentSize.width), size.depth); + } + else + { + mOvershootOverlay.SetOrientation( Quaternion( Radian( 1.5f * Math::PI ), Vector3::ZAXIS ) ); + mOvershootOverlay.SetSize(parentSize.height, GetBounceActorHeight(parentSize.height), size.depth); + relativeOffset = Vector3(0.0f, 1.0f, 0.0f); + } + mOvershootOverlay.SetPosition(relativeOffset * parentSize); + } + else + { + // negative overshoot + const Vector3 size = mOvershootOverlay.GetCurrentSize(); + Vector3 relativeOffset; + const Vector3 parentSize = self.GetCurrentSize(); + if(IsVertical()) + { + mOvershootOverlay.SetOrientation( Quaternion( Radian( Math::PI ), Vector3::ZAXIS ) ); + mOvershootOverlay.SetSize(parentSize.width, GetBounceActorHeight(parentSize.width), size.depth); + relativeOffset = Vector3(1.0f, 1.0f, 0.0f); + } + else + { + mOvershootOverlay.SetOrientation( Quaternion( Radian( 0.5f * Math::PI ), Vector3::ZAXIS ) ); + mOvershootOverlay.SetSize(parentSize.height, GetBounceActorHeight(parentSize.height), size.depth); + relativeOffset = Vector3(1.0f, 0.0f, 0.0f); + } + mOvershootOverlay.SetPosition(relativeOffset * parentSize); + } + } } void ScrollOvershootEffectRipple::OnOvershootNotification(PropertyNotification& source) @@ -227,6 +298,60 @@ void ScrollOvershootEffectRipple::OnOvershootNotification(PropertyNotification& void ScrollOvershootEffectRipple::SetOvershoot(float amount, bool animate) { + float absAmount = fabsf(amount); + bool animatingOn = absAmount > Math::MACHINE_EPSILON_0; + if( (animatingOn && (mAnimationStateFlags & AnimatingIn)) ) + { + // trying to do what we are already doing + if( mAnimationStateFlags & AnimateBack ) + { + mAnimationStateFlags &= ~AnimateBack; + } + return; + } + if( (!animatingOn && (mAnimationStateFlags & AnimatingOut)) ) + { + // trying to do what we are already doing + return; + } + if( !animatingOn && (mAnimationStateFlags & AnimatingIn) ) + { + // dont interrupt while animating on + mAnimationStateFlags |= AnimateBack; + return; + } + + if( absAmount > Math::MACHINE_EPSILON_1 ) + { + UpdateVisibility(true); + } + + float overshootAnimationSpeed = mAttachedScrollView.Self().GetProperty(Toolkit::Scrollable::Property::OVERSHOOT_ANIMATION_SPEED); + + if( animate && overshootAnimationSpeed > Math::MACHINE_EPSILON_0 ) + { + float currentOvershoot = fabsf( mOvershootOverlay.GetProperty( mEffectOvershootProperty ).Get() ); + float duration = mOvershootOverlay.GetCurrentSize().height * (animatingOn ? (1.0f - currentOvershoot) : currentOvershoot) / overshootAnimationSpeed; + + if( duration > Math::MACHINE_EPSILON_0 ) + { + if(mScrollOvershootAnimation) + { + mScrollOvershootAnimation.FinishedSignal().Disconnect( this, &ScrollOvershootEffectRipple::OnOvershootAnimFinished ); + mScrollOvershootAnimation.Stop(); + mScrollOvershootAnimation.Reset(); + } + mScrollOvershootAnimation = Animation::New(duration); + mScrollOvershootAnimation.FinishedSignal().Connect( this, &ScrollOvershootEffectRipple::OnOvershootAnimFinished ); + mScrollOvershootAnimation.AnimateTo( Property(mOvershootOverlay, mEffectOvershootProperty), amount, TimePeriod(duration) ); + mScrollOvershootAnimation.Play(); + mAnimationStateFlags = animatingOn ? AnimatingIn : AnimatingOut; + } + } + else + { + mOvershootOverlay.SetProperty( mEffectOvershootProperty, amount); + } } void ScrollOvershootEffectRipple::OnOvershootAnimFinished(Animation& animation) @@ -234,6 +359,8 @@ void ScrollOvershootEffectRipple::OnOvershootAnimFinished(Animation& animation) bool animateOff = false; if( mAnimationStateFlags & AnimatingOut ) { + // should now be offscreen + mOvershootOverlay.SetVisible(false); } if( (mAnimationStateFlags & AnimateBack) ) { diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.h index 8591f44..f19e39c 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.h +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-overshoot-indicator-impl.h @@ -249,6 +249,7 @@ public: static ScrollOvershootEffectRipplePtr New( bool vertical, Scrollable& scrollable ); private: + Actor mOvershootOverlay; ///< the actor which displays the overshoot effect Scrollable& mAttachedScrollView; ///< the actor that this indicator has been attached to Animation mScrollOvershootAnimation; ///< overshoot animation PropertyNotification mOvershootIncreaseNotification;///< notification used to inform as overshoot increases diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-carousel-effect-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-carousel-effect-impl.cpp index ea529ff..86ad736 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-carousel-effect-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-carousel-effect-impl.cpp @@ -16,8 +16,6 @@ */ // EXTERNAL INCLUDES -#include -#include #include #include @@ -79,65 +77,56 @@ public: } /** - * @param[in] current The current visibility of this Actor - * @param[in] positionProperty The Actor's Position. - * @param[in] scaleProperty The Actor's Scale. - * @param[in] sizeProperty The Actor's Size - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE) + * @param[in,out] current The current visibility of this Actor + * @param[in] inputs Contains: + * The Actor's Position + * The Actor's Scale + * The Actor's Size + * The scroll-view's position property (SCROLL_POSITION) + * The size of the scroll-view (scrollView SIZE) * @return The new visibility of this Actor. */ - bool VisibilityConstraint(const bool& current, - const PropertyInput& positionProperty, - const PropertyInput& scaleProperty, - const PropertyInput& sizeProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollSizeProperty) + void VisibilityConstraint( bool& current, const PropertyInputContainer& inputs ) { const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY()); - Vector2 position(positionProperty.GetVector3() + scrollPositionProperty.GetVector3()); - Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3()); + Vector2 position( inputs[0]->GetVector3() + inputs[3]->GetVector3()); + Vector2 scaledSize( inputs[2]->GetVector3() * inputs[1]->GetVector3()); - Vector2 domain(scrollSizeProperty.GetVector3()); + Vector2 domain( inputs[4]->GetVector3() ); position -= (anchor - mVisibilityThreshold) * scaledSize; domain -= (Vector2::ONE - mVisibilityThreshold * 2.0f) * scaledSize; - return ( position.x >= 0 && - position.x <= domain.x && - position.y >= 0 && - position.y <= domain.y ); + current = ( position.x >= 0 && + position.x <= domain.x && + position.y >= 0 && + position.y <= domain.y ); } /** - * @param[in] current The current orientation of this Actor - * @param[in] positionProperty The Actor's Position. - * @param[in] scaleProperty The Actor's Scale. - * @param[in] sizeProperty The Actor's Size - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE) - * @param[in] activateProperty Activation value (0 - normal, 1.0 - full effect) + * @param[in,out] current The current orientation of this Actor + * @param[in] inputs Contains: + * The Actor's Position. + * The Actor's Scale. + * The Actor's Size + * The scroll-view's position property (SCROLL_POSITION) + * The size of the scroll-view (scrollView SIZE) + * Activation value (0 - normal, 1.0 - full effect) * @return The new orientation of this Actor. */ - Quaternion RotationConstraint(const Quaternion& current, - const PropertyInput& positionProperty, - const PropertyInput& scaleProperty, - const PropertyInput& sizeProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollSizeProperty, - const PropertyInput& activateProperty) + void RotationConstraint( Quaternion& current, const PropertyInputContainer& inputs ) { - const float activate(activateProperty.GetFloat()); + const float activate(inputs[5]->GetFloat()); if(activate <= Math::MACHINE_EPSILON_0) { - return current; + return; } const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY()); - Vector2 position(positionProperty.GetVector3() + scrollPositionProperty.GetVector3()); - Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3()); - Vector2 domain(scrollSizeProperty.GetVector3()); + Vector2 position(inputs[0]->GetVector3() + inputs[3]->GetVector3()); + Vector2 scaledSize(inputs[2]->GetVector3() * inputs[1]->GetVector3()); + Vector2 domain(inputs[4]->GetVector3()); position -= (anchor - mCanvasMargin) * scaledSize; domain -= (Vector2::ONE - mCanvasMargin * 2.0f) * scaledSize; @@ -155,38 +144,35 @@ public: angle *= activate; - return Quaternion(-angle.x, Vector3::YAXIS) * - Quaternion(angle.y, Vector3::XAXIS) * - current; + current = Quaternion( Radian( -angle.x ), Vector3::YAXIS ) * + Quaternion( Radian( angle.y ), Vector3::XAXIS ) * + current; } /** - * @param[in] current The current position of this Actor - * @param[in] scaleProperty The Actor's Scale. - * @param[in] sizeProperty The Actor's Size - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollSizeProperty The size of the scroll-view (scrollView SIZE) - * @param[in] activateProperty Activation value (0 - normal, 1.0 - full effect) + * @param[in,out] current The current position of this Actor + * @param[in] inputs Contains: + * The Actor's Scale. + * The Actor's Size + * The scroll-view's position property (SCROLL_POSITION) + * The size of the scroll-view (scrollView SIZE) + * Activation value (0 - normal, 1.0 - full effect) * @return The new position of this Actor. */ - Vector3 PositionConstraint(const Vector3& current, - const PropertyInput& scaleProperty, - const PropertyInput& sizeProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollSizeProperty, - const PropertyInput& activateProperty) + void PositionConstraint( Vector3& position, const PropertyInputContainer& inputs ) { - const float activate(activateProperty.GetFloat()); - Vector3 position(current + scrollPositionProperty.GetVector3()); + const float activate(inputs[4]->GetFloat()); if(activate <= Math::MACHINE_EPSILON_0) { - return position; + return; } + position += inputs[2]->GetVector3(); + const Vector2& anchor(AnchorPoint::CENTER.GetVectorXY()); - Vector2 scaledSize(sizeProperty.GetVector3() * scaleProperty.GetVector3()); - Vector2 domain(scrollSizeProperty.GetVector3()); + Vector2 scaledSize(inputs[1]->GetVector3() * inputs[0]->GetVector3()); + Vector2 domain(inputs[3]->GetVector3()); position.GetVectorXY() -= (anchor - mCanvasMargin) * scaledSize; domain -= (Vector2::ONE - mCanvasMargin * 2.0f) * scaledSize; @@ -207,8 +193,6 @@ public: } position.GetVectorXY() += (anchor - mCanvasMargin) * scaledSize; - - return position; } Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate. @@ -230,38 +214,34 @@ void ApplyScrollCarouselConstraints(Toolkit::ScrollView scrollView, // Apply constraints to this actor // Constraint constraint; - constraint = Constraint::New( Actor::Property::VISIBLE, - LocalSource( Actor::Property::POSITION ), - LocalSource( Actor::Property::SCALE ), - LocalSource( Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ), - boost::bind( &ScrollCarouselEffectInfo::VisibilityConstraint, info, _1, _2, _3, _4, _5, _6) ); + constraint = Constraint::New( child, Actor::Property::VISIBLE, info, &ScrollCarouselEffectInfo::VisibilityConstraint ); + constraint.AddSource( LocalSource( Actor::Property::POSITION ) ); + constraint.AddSource( LocalSource( Actor::Property::SCALE ) ); + constraint.AddSource( LocalSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source( scrollView, Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + constraint.AddSource( Source( scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source( scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::ORIENTATION, - LocalSource( Actor::Property::POSITION ), - LocalSource( Actor::Property::SCALE ), - LocalSource( Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ), - boost::bind( &ScrollCarouselEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::ORIENTATION, info, &ScrollCarouselEffectInfo::RotationConstraint ); + constraint.AddSource( LocalSource( Actor::Property::POSITION ) ); + constraint.AddSource( LocalSource( Actor::Property::SCALE ) ); + constraint.AddSource( LocalSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source( scrollView, Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + constraint.AddSource( Source( scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source( scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::POSITION, - LocalSource( Actor::Property::SCALE ), - LocalSource( Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ), - boost::bind( &ScrollCarouselEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6) ); - + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::POSITION, info, &ScrollCarouselEffectInfo::PositionConstraint ); + constraint.AddSource( LocalSource( Actor::Property::SCALE ) ); + constraint.AddSource( LocalSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollViewCarouselEffect::EFFECT_ACTIVATE ) ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); + constraint.Apply(); } } // unnamed namespace diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-cube-effect-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-cube-effect-impl.cpp index 938ba1c..f7f3384 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-cube-effect-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-cube-effect-impl.cpp @@ -16,8 +16,6 @@ */ // EXTERNAL INCLUDES -#include -#include #include #include @@ -62,25 +60,20 @@ public: } /** - * @param[in] current The current orientation of this Actor - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current orientation of this Actor + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new orientation of this Actor. */ - Quaternion RotationConstraint(const Quaternion& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void RotationConstraint( Quaternion& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -88,16 +81,16 @@ public: // short circuit: for orthognal view. if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) ) { - return current; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); - bool wrap = scrollWrap.GetBoolean(); + const Vector3& pageSize = inputs[4]->GetVector3(); + bool wrap = inputs[5]->GetBoolean(); if(wrap) { - const Vector3& min = scrollPositionMin.GetVector3(); - const Vector3& max = scrollPositionMax.GetVector3(); + const Vector3& min = inputs[2]->GetVector3(); + const Vector3& max = inputs[3]->GetVector3(); if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1) { @@ -115,7 +108,7 @@ public: // short circuit: for pages outside of view. if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) ) { - return current; + return; } position.x /= pageSize.x; @@ -124,33 +117,26 @@ public: Vector2 angle( Clamp(position.x, -1.0f,1.0f), Clamp(position.y, -1.0f,1.0f) ); - Quaternion rotation = Quaternion(angle.x * mAngleSwing.x, Vector3::YAXIS) * - Quaternion(-angle.y * mAngleSwing.y, Vector3::XAXIS) * - current; - - return rotation; + current = Quaternion( Radian( angle.x * mAngleSwing.x ), Vector3::YAXIS ) * + Quaternion( Radian( -angle.y * mAngleSwing.y ), Vector3::XAXIS ) * + current; } /** - * @param[in] current The current color of this Actor - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current color of this Actor + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new color of this Actor. */ - Vector4 ColorConstraint(const Vector4& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void ColorConstraint( Vector4& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -158,16 +144,16 @@ public: // short circuit: for orthognal view. if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) ) { - return current; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); - bool wrap = scrollWrap.GetBoolean(); + const Vector3& pageSize = inputs[4]->GetVector3(); + bool wrap = inputs[5]->GetBoolean(); if(wrap) { - const Vector3& min = scrollPositionMin.GetVector3(); - const Vector3& max = scrollPositionMax.GetVector3(); + const Vector3& min = inputs[2]->GetVector3(); + const Vector3& max = inputs[3]->GetVector3(); if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1) { @@ -187,7 +173,8 @@ public: { // note preserve color channels incase there is a shader/further constraint // that wishes to do something with that information. - return Vector4(current.r, current.g, current.b, 0.0f); + current.a = 0.0f; + return; } position.x /= pageSize.x; @@ -199,32 +186,24 @@ public: float f = (1.0f - fabsf(angle.x)) * (1.0f - fabsf(angle.y)); f = f*f; - Vector4 color = current; - color.a *= f; - - return color; + current.a *= f; } /** - * @param[in] current The current position - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current position + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new position of this Actor. */ - Vector3 PositionConstraint(const Vector3& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void PositionConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 relativePosition = pagePosition + scrollPosition; @@ -232,16 +211,17 @@ public: // short circuit: for orthognal view. if( (fabsf(relativePosition.x) < Math::MACHINE_EPSILON_1) && (fabsf(relativePosition.y) < Math::MACHINE_EPSILON_1) ) { - return current + scrollPosition; + current += scrollPosition; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); - bool wrap = scrollWrap.GetBoolean(); + const Vector3& pageSize = inputs[4]->GetVector3(); + bool wrap = inputs[5]->GetBoolean(); if(wrap) { - const Vector3& min = scrollPositionMin.GetVector3(); - const Vector3& max = scrollPositionMax.GetVector3(); + const Vector3& min = inputs[2]->GetVector3(); + const Vector3& max = inputs[3]->GetVector3(); if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1) { @@ -261,7 +241,8 @@ public: { // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this) // they will be invisible so doesn't have to be precise, just away from stage. - return current + scrollPosition; + current += scrollPosition; + return; } relativePosition.x /= pageSize.x; @@ -274,14 +255,14 @@ public: // Rotate position (current) about point. Vector3 position = current - mAnchor; - Quaternion rotatorY(angle.x, Vector3::YAXIS); + Quaternion rotatorY( Radian( angle.x ), Vector3::YAXIS); position = rotatorY.Rotate(position); - Quaternion rotatorX(-angle.y, Vector3::XAXIS); + Quaternion rotatorX( Radian( -angle.y ), Vector3::XAXIS); position = rotatorX.Rotate(position); position += mAnchor; position += relativePosition * mPositionSwing; - return position - pagePosition; + current = position - pagePosition; } Vector3 mAnchor; ///< Anchor point where Actor should rotate about. @@ -303,41 +284,35 @@ void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView, { // Apply constraints to this actor // Constraint constraint; - constraint = Constraint::New( Actor::Property::ORIENTATION, - Source(parentPage, Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - boost::bind( &ScrollCubeEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint = Constraint::New( child, Actor::Property::ORIENTATION, info, &ScrollCubeEffectInfo::RotationConstraint ); + constraint.AddSource( Source(parentPage, Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::COLOR, - Source(parentPage, Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - boost::bind( &ScrollCubeEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::COLOR, info, &ScrollCubeEffectInfo::ColorConstraint ); + constraint.AddSource( Source(parentPage, Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::POSITION, - Source(parentPage, Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - boost::bind( &ScrollCubeEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::POSITION, info, &ScrollCubeEffectInfo::PositionConstraint ); + constraint.AddSource( Source(parentPage, Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); + constraint.Apply(); } } // unnamed namespace diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-depth-effect-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-depth-effect-impl.cpp index 8b6003f..eaa99eb 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-depth-effect-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-depth-effect-impl.cpp @@ -16,7 +16,6 @@ */ // EXTERNAL INCLUDES -#include #include #include @@ -91,26 +90,21 @@ struct ScrollDepthScaleConstraint } /** - * @param[in] current The current scale - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current scale + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new scale of this Actor. */ - Vector3 operator()(const Vector3& currentScale, - const PropertyInput& currentPositionProperty, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty) + void operator()( Vector3& currentScale, const PropertyInputContainer& inputs ) { - const Vector3& currentPosition = currentPositionProperty.GetVector3(); - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& currentPosition = inputs[0]->GetVector3(); + const Vector3& pagePosition = inputs[1]->GetVector3(); + const Vector3& scrollPosition = inputs[2]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -118,15 +112,15 @@ struct ScrollDepthScaleConstraint // short circuit: for orthognal view. if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) ) { - return currentScale; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); + const Vector3& pageSize = inputs[5]->GetVector3(); // Don't have enough parameters, to provide Wrap mode (need a way of having 'uniforms' instead of scrollWrap.GetBoolean()) - const Vector3& min = scrollPositionMin.GetVector3(); - const Vector3& max = scrollPositionMax.GetVector3(); + const Vector3& min = inputs[3]->GetVector3(); + const Vector3& max = inputs[4]->GetVector3(); if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1) { @@ -143,7 +137,7 @@ struct ScrollDepthScaleConstraint // short circuit: for pages outside of view. if( (fabsf(position.x) >= pageSize.x) || (fabsf(position.y) >= pageSize.y) ) { - return currentScale; + return; } // Calculate scale //////////////////////////////////////////////////////// @@ -175,7 +169,7 @@ struct ScrollDepthScaleConstraint float f = mScaleExtent + cos(position.x * Math::PI_2) * cos(position.y * Math::PI_2) * (1.0f - mScaleExtent); - return currentScale * f; + currentScale *= f; } const Vector2 mPositionExtent; ///< Determines how much of the Actor's X and Y position affects exponent value. @@ -216,25 +210,20 @@ struct ScrollDepthPositionConstraint } /** - * @param[in] current The current position - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current position + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new position of this Actor. */ - Vector3 operator()(const Vector3& currentPosition, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void operator()( Vector3& currentPosition, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -242,16 +231,17 @@ struct ScrollDepthPositionConstraint // short circuit: for orthognal view. if( (fabsf(position.x) < Math::MACHINE_EPSILON_1) && (fabsf(position.y) < Math::MACHINE_EPSILON_1) ) { - return currentPosition + scrollPosition; + currentPosition += scrollPosition; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); - bool wrap = scrollWrap.GetBoolean(); + const Vector3& pageSize = inputs[4]->GetVector3(); + bool wrap = inputs[5]->GetBoolean(); if(wrap) { - const Vector3& min = scrollPositionMin.GetVector3(); - const Vector3& max = scrollPositionMax.GetVector3(); + const Vector3& min = inputs[2]->GetVector3(); + const Vector3& max = inputs[3]->GetVector3(); if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1) { @@ -271,7 +261,8 @@ struct ScrollDepthPositionConstraint { // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this) // they will be invisible so doesn't have to be precise, just away from stage. - return currentPosition + scrollPosition; + currentPosition += scrollPosition; + return; } // Calculate position ///////////////////////////////////////////////////// @@ -281,8 +272,6 @@ struct ScrollDepthPositionConstraint position *= mPositionScale; - Vector3 finalPosition(currentPosition - pagePosition); - Vector3 relCurrentPosition = currentPosition; relCurrentPosition.x = relCurrentPosition.x / pageSize.x + 0.5f; relCurrentPosition.y = relCurrentPosition.y / pageSize.y + 0.5f; @@ -303,9 +292,8 @@ struct ScrollDepthPositionConstraint position.x = RampFunction(position.x, mOffsetExtent.x + extent.x); position.y = RampFunction(position.y, mOffsetExtent.y + extent.y); - finalPosition += pageSize * position; - - return finalPosition; + currentPosition -= pagePosition; + currentPosition += pageSize * position; } const Vector2 mPositionExtent; ///< Determines how much of the Actor's X and Y position affects exponent value. @@ -336,29 +324,26 @@ void ApplyScrollDepthConstraints(Toolkit::ScrollView scrollView, float scaleExtent) { // Scale Constraint - Constraint constraint = Constraint::New( Actor::Property::SCALE, - LocalSource(Actor::Property::POSITION), - ParentSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - ScrollDepthScaleConstraint( positionExtent, offsetExtent, positionScale, scaleExtent ) ); + Constraint constraint = Constraint::New( child, Actor::Property::SCALE, ScrollDepthScaleConstraint( positionExtent, offsetExtent, positionScale, scaleExtent ) ); + constraint.AddSource( LocalSource( Actor::Property::POSITION ) ); + constraint.AddSource( ParentSource( Actor::Property::POSITION ) ); + constraint.AddSource( Source( scrollView, Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + constraint.AddSource( Source( scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source( scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source( scrollView, Actor::Property::SIZE ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); + constraint.Apply(); // Position Constraint (apply last as other constraints use Actor::POSITION as a function input) - constraint = Constraint::New( Actor::Property::POSITION, - ParentSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - ScrollDepthPositionConstraint( positionExtent, offsetExtent, positionScale ) ); - + constraint = Constraint::New( child, Actor::Property::POSITION, ScrollDepthPositionConstraint( positionExtent, offsetExtent, positionScale ) ); + constraint.AddSource( ParentSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); + constraint.Apply(); } } // unnamed namespace diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp index 5111cec..496d20f 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.cpp @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -29,6 +30,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -168,27 +170,21 @@ float ConstantDecelerationAlphaFunction(float progress) * scroll domain. This is a value from 0.0f to 1.0f in each * scroll position axis. */ -Vector3 InternalRelativePositionConstraint(const Vector3& current, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollMinProperty, - const PropertyInput& scrollMaxProperty, - const PropertyInput& scrollSizeProperty) +void InternalRelativePositionConstraint( Vector3& relativePosition, const PropertyInputContainer& inputs) { - Vector3 position = -scrollPositionProperty.GetVector3(); - const Vector3& min = scrollMinProperty.GetVector3(); - const Vector3& max = scrollMaxProperty.GetVector3(); - const Vector3& size = scrollSizeProperty.GetVector3(); + Vector3 position = -inputs[0]->GetVector3(); + const Vector3& min = inputs[1]->GetVector3(); + const Vector3& max = inputs[2]->GetVector3(); + const Vector3& size = inputs[3]->GetVector3(); position.x = WrapInDomain(position.x, min.x, max.x); position.y = WrapInDomain(position.y, min.y, max.y); - Vector3 relativePosition; Vector3 domainSize = (max - min) - size; relativePosition.x = domainSize.x > Math::MACHINE_EPSILON_1 ? fabsf((position.x - min.x) / domainSize.x) : 0.0f; relativePosition.y = domainSize.y > Math::MACHINE_EPSILON_1 ? fabsf((position.y - min.y) / domainSize.y) : 0.0f; - - return relativePosition; + relativePosition.z = 0.0f; } } // unnamed namespace @@ -213,6 +209,18 @@ BaseHandle Create() // Setup properties, signals and actions using the type-registry. DALI_TYPE_REGISTRATION_BEGIN( Toolkit::ScrollView, Toolkit::Scrollable, Create ) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "scroll-position", VECTOR3, SCROLL_POSITION) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "scroll-pre-position", VECTOR3, SCROLL_PRE_POSITION) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "overshoot-x", FLOAT, OVERSHOOT_X) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "overshoot-y", FLOAT, OVERSHOOT_Y) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "scroll-final", VECTOR3, SCROLL_FINAL) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "wrap", BOOLEAN, WRAP) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "panning", BOOLEAN, PANNING) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "scrolling", BOOLEAN, SCROLLING) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "scroll-domain-offset", VECTOR3, SCROLL_DOMAIN_OFFSET) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "scroll-position-delta", VECTOR3, SCROLL_POSITION_DELTA) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( ScrollView, "start-page-position", VECTOR3, START_PAGE_POSITION) + DALI_SIGNAL_REGISTRATION( ScrollView, "value-changed", SIGNAL_SNAP_STARTED ) DALI_TYPE_REGISTRATION_END() @@ -281,22 +289,19 @@ struct InternalPrePositionConstraint { } - Vector3 operator()(const Vector3& current, - const PropertyInput& gesturePositionProperty, - const PropertyInput& sizeProperty) + void operator()( Vector3& scrollPostPosition, const PropertyInputContainer& inputs ) { - Vector3 scrollPostPosition = current; - Vector2 panPosition = gesturePositionProperty.GetVector2(); + const Vector2& panPosition = inputs[0]->GetVector2(); if(!mWasPanning) { - mPrePosition = current; + mPrePosition = scrollPostPosition; mCurrentPanMask = mInitialPanMask; mWasPanning = true; } // Calculate Deltas... - Vector2 currentPosition = gesturePositionProperty.GetVector2(); + const Vector2& currentPosition = panPosition; Vector2 panDelta( currentPosition - mLocalStart ); // Axis Auto Lock - locks the panning to the horizontal or vertical axis if the pan @@ -322,7 +327,7 @@ struct InternalPrePositionConstraint scrollPostPosition.GetVectorXY() += panDelta; // if no wrapping then clamp preposition to maximum overshoot amount - const Vector3& size = sizeProperty.GetVector3(); + const Vector3& size = inputs[1]->GetVector3(); if( mClampX ) { float newXPosition = Clamp(scrollPostPosition.x, (mDomainMax.x + size.x) - mMaxOvershoot.x, mDomainMin.x + mMaxOvershoot.x ); @@ -345,8 +350,6 @@ struct InternalPrePositionConstraint } scrollPostPosition.y = newYPosition; } - - return scrollPostPosition; } Vector3 mPrePosition; @@ -384,16 +387,12 @@ struct InternalPositionConstraint { } - Vector3 operator()(const Vector3& current, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollMinProperty, - const PropertyInput& scrollMaxProperty, - const PropertyInput& scrollSizeProperty) + void operator()( Vector3& position, const PropertyInputContainer& inputs ) { - Vector3 position = scrollPositionProperty.GetVector3(); - const Vector2& size = scrollSizeProperty.GetVector3().GetVectorXY(); - const Vector3& min = scrollMinProperty.GetVector3(); - const Vector3& max = scrollMaxProperty.GetVector3(); + position = inputs[0]->GetVector3(); + const Vector2& size = inputs[3]->GetVector3().GetVectorXY(); + const Vector3& min = inputs[1]->GetVector3(); + const Vector3& max = inputs[2]->GetVector3(); if( mWrap ) { @@ -406,8 +405,6 @@ struct InternalPositionConstraint position.x = mClampX ? Clamp(position.x, mDomainMax.x + size.x, mDomainMin.x ) : position.x; position.y = mClampY ? Clamp(position.y, mDomainMax.y + size.y, mDomainMin.y ) : position.y; } - - return position; } Vector2 mDomainMin; @@ -420,25 +417,25 @@ struct InternalPositionConstraint /** * This constraint updates the X overshoot property using the difference - * mPropertyPrePosition.x and mPropertyPosition.x, returning a relative value between 0.0f and 1.0f + * SCROLL_PRE_POSITION.x and SCROLL_POSITION.x, returning a relative value between 0.0f and 1.0f */ struct OvershootXConstraint { OvershootXConstraint(float maxOvershoot) : mMaxOvershoot(maxOvershoot) {} - float operator()(const float& current, - const PropertyInput& scrollPrePositionProperty, - const PropertyInput& scrollPostPositionProperty, - const PropertyInput& canScrollProperty) + void operator()( float& current, const PropertyInputContainer& inputs ) { - if( canScrollProperty.GetBoolean() ) + if( inputs[2]->GetBoolean() ) { - const Vector3& scrollPrePosition = scrollPrePositionProperty.GetVector3(); - const Vector3& scrollPostPosition = scrollPostPositionProperty.GetVector3(); + const Vector3& scrollPrePosition = inputs[0]->GetVector3(); + const Vector3& scrollPostPosition = inputs[1]->GetVector3(); float newOvershoot = scrollPrePosition.x - scrollPostPosition.x; - return (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot; + current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot; + } + else + { + current = 0.0f; } - return 0.0f; } float mMaxOvershoot; @@ -446,25 +443,25 @@ struct OvershootXConstraint /** * This constraint updates the Y overshoot property using the difference - * mPropertyPrePosition.y and mPropertyPosition.y, returning a relative value between 0.0f and 1.0f + * SCROLL_PRE_POSITION.y and SCROLL_POSITION.y, returning a relative value between 0.0f and 1.0f */ struct OvershootYConstraint { OvershootYConstraint(float maxOvershoot) : mMaxOvershoot(maxOvershoot) {} - float operator()(const float& current, - const PropertyInput& scrollPrePositionProperty, - const PropertyInput& scrollPostPositionProperty, - const PropertyInput& canScrollProperty) + void operator()( float& current, const PropertyInputContainer& inputs ) { - if( canScrollProperty.GetBoolean() ) + if( inputs[2]->GetBoolean() ) { - const Vector3& scrollPrePosition = scrollPrePositionProperty.GetVector3(); - const Vector3& scrollPostPosition = scrollPostPositionProperty.GetVector3(); + const Vector3& scrollPrePosition = inputs[0]->GetVector3(); + const Vector3& scrollPostPosition = inputs[1]->GetVector3(); float newOvershoot = scrollPrePosition.y - scrollPostPosition.y; - return (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot; + current = (newOvershoot > 0.0f ? std::min(newOvershoot, mMaxOvershoot) : std::max(newOvershoot, -mMaxOvershoot)) / mMaxOvershoot; + } + else + { + current = 0.0f; } - return 0.0f; } float mMaxOvershoot; @@ -475,14 +472,12 @@ struct OvershootYConstraint * * Generates position-delta property based on scroll-position + scroll-offset properties. */ -Vector3 InternalPositionDeltaConstraint(const Vector3& current, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollOffsetProperty) +void InternalPositionDeltaConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); - const Vector3& scrollOffset = scrollOffsetProperty.GetVector3(); + const Vector3& scrollPosition = inputs[0]->GetVector3(); + const Vector3& scrollOffset = inputs[1]->GetVector3(); - return scrollPosition + scrollOffset; + current = scrollPosition + scrollOffset; } /** @@ -501,18 +496,15 @@ struct InternalFinalConstraint { } - Vector3 operator()(const Vector3& current, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollOvershootXProperty, - const PropertyInput& scrollOvershootYProperty) + void operator()( Vector3& current, const PropertyInputContainer& inputs ) { - const float& overshootx = scrollOvershootXProperty.GetFloat(); - const float& overshooty = scrollOvershootYProperty.GetFloat(); + const float& overshootx = inputs[1]->GetFloat(); + const float& overshooty = inputs[2]->GetFloat(); Vector3 offset( mFunctionX(overshootx), mFunctionY(overshooty), 0.0f); - return scrollPositionProperty.GetVector3() - offset; + current = inputs[0]->GetVector3() - offset; } AlphaFunction mFunctionX; @@ -590,15 +582,14 @@ void ScrollView::OnInitialize() mInternalActor = Actor::New(); mInternalActor.SetDrawMode(DrawMode::OVERLAY); self.Add(mInternalActor); - mInternalActor.ApplyConstraint( Constraint::New( Actor::Property::SIZE, ParentSource( Actor::Property::SIZE ), EqualToConstraint() ) ); + Constraint constraint = Constraint::New( mInternalActor, Actor::Property::SIZE, EqualToConstraint() ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.Apply(); mInternalActor.SetParentOrigin(ParentOrigin::CENTER); mInternalActor.SetAnchorPoint(AnchorPoint::CENTER); mAlterChild = true; - // Register Scroll Properties. - RegisterProperties(); - mScrollPostPosition = mScrollPrePosition = Vector3::ZERO; mMouseWheelScrollDistanceStep = Stage::GetCurrent().GetSize() * DEFAULT_MOUSE_WHEEL_SCROLL_DISTANCE_STEP_PROPORTION; @@ -617,6 +608,9 @@ void ScrollView::OnInitialize() EnableScrollComponent(Toolkit::Scrollable::OvershootIndicator); + self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, mCanScrollVertical); + self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, mCanScrollHorizontal); + Vector3 size = GetControlSize(); UpdatePropertyDomain(size); SetInternalConstraints(); @@ -871,24 +865,24 @@ void ScrollView::UpdatePropertyDomain(const Vector3& size) if( mCanScrollVertical != canScrollVertical ) { mCanScrollVertical = canScrollVertical; - self.SetProperty(mPropertyCanScrollVertical, canScrollVertical); + self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL, canScrollVertical); } if( mCanScrollHorizontal != canScrollHorizontal ) { mCanScrollHorizontal = canScrollHorizontal; - self.SetProperty(mPropertyCanScrollHorizontal, canScrollHorizontal); + self.SetProperty(Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL, canScrollHorizontal); } if( scrollPositionChanged ) { - DALI_LOG_SCROLL_STATE("[0x%X] Domain Changed, setting mPropertyPrePosition To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y ); - self.SetProperty(mPropertyPrePosition, mScrollPrePosition); + DALI_LOG_SCROLL_STATE("[0x%X] Domain Changed, setting SCROLL_PRE_POSITION To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y ); + self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, mScrollPrePosition); } if( domainChanged ) { mMinScroll = min; mMaxScroll = max; - self.SetProperty(mPropertyPositionMin, mMinScroll ); - self.SetProperty(mPropertyPositionMax, mMaxScroll ); + self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MIN, mMinScroll ); + self.SetProperty(Toolkit::Scrollable::Property::SCROLL_POSITION_MAX, mMaxScroll ); } } @@ -961,7 +955,7 @@ bool ScrollView::GetWrapMode() const void ScrollView::SetWrapMode(bool enable) { mWrapMode = enable; - Self().SetProperty(mPropertyWrap, enable); + Self().SetProperty(Toolkit::ScrollView::Property::WRAP, enable); } int ScrollView::GetScrollUpdateDistance() const @@ -1119,7 +1113,7 @@ void ScrollView::TransformTo(const Vector3& position, float duration, AlphaFunct this, position.x, position.y, duration, int(horizontalBias), int(verticalBias)); Vector3 currentScrollPosition = GetCurrentScrollPosition(); - self.SetProperty( mPropertyScrollStartPagePosition, currentScrollPosition ); + self.SetProperty( Toolkit::ScrollView::Property::START_PAGE_POSITION, currentScrollPosition ); if( mScrolling ) // are we interrupting a current scroll? { @@ -1134,15 +1128,15 @@ void ScrollView::TransformTo(const Vector3& position, float duration, AlphaFunct DALI_LOG_SCROLL_STATE("[0x%X] Interrupting Pan, set to false", this ); mPanning = false; mGestureStackDepth = 0; - self.SetProperty( mPropertyPanning, false ); + self.SetProperty( Toolkit::ScrollView::Property::PANNING, false ); if( mScrollMainInternalPrePositionConstraint ) { - self.RemoveConstraint(mScrollMainInternalPrePositionConstraint); + mScrollMainInternalPrePositionConstraint.Remove(); } } - self.SetProperty(mPropertyScrolling, true); + self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, true); mScrolling = true; DALI_LOG_SCROLL_STATE("[0x%X] mScrollStartedSignal 1 [%.2f, %.2f]", this, currentScrollPosition.x, currentScrollPosition.y); @@ -1158,7 +1152,7 @@ void ScrollView::TransformTo(const Vector3& position, float duration, AlphaFunct if(!animating) { // if not animating, then this pan has completed right now. - self.SetProperty(mPropertyScrolling, false); + self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, false); mScrolling = false; // If we have no duration, then in the next update frame, we will be at the position specified as we just set. @@ -1450,7 +1444,7 @@ bool ScrollView::SnapWithVelocity(Vector2 velocity) if(child) { - Vector3 position = Self().GetProperty(mPropertyPosition); + Vector3 position = Self().GetProperty(Toolkit::ScrollView::Property::SCROLL_POSITION); // Get center-point of the Actor. Vector3 childPosition = GetPositionOfAnchor(child, AnchorPoint::CENTER); @@ -1639,15 +1633,15 @@ bool ScrollView::AnimateTo(const Vector3& position, const Vector3& positionDurat if( !(mScrollStateFlags & SCROLL_ANIMATION_FLAGS) ) { - DALI_LOG_SCROLL_STATE("[0x%X] Setting mPropertyPrePosition To[%.2f, %.2f]", this, mScrollTargetPosition.x, mScrollTargetPosition.y ); - self.SetProperty(mPropertyPrePosition, mScrollTargetPosition); + DALI_LOG_SCROLL_STATE("[0x%X] Setting SCROLL_PRE_POSITION To[%.2f, %.2f]", this, mScrollTargetPosition.x, mScrollTargetPosition.y ); + self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, mScrollTargetPosition); mScrollPrePosition = mScrollTargetPosition; mScrollPostPosition = mScrollTargetPosition; WrapPosition(mScrollPostPosition); } DALI_LOG_SCROLL_STATE("[0x%X] position-changed, mScrollTargetPosition[%.2f, %.2f], mScrollPrePosition[%.2f, %.2f], mScrollPostPosition[%.2f, %.2f]", this, mScrollTargetPosition.x, mScrollTargetPosition.y, mScrollPrePosition.x, mScrollPrePosition.y, mScrollPostPosition.x, mScrollPostPosition.y ); - DALI_LOG_SCROLL_STATE("[0x%X] mPropertyPrePosition[%.2f, %.2f], mPropertyPosition[%.2f, %.2f]", this, self.GetProperty( mPropertyPrePosition ).Get().x, self.GetProperty( mPropertyPrePosition ).Get().y, self.GetProperty( mPropertyPosition ).Get().x, self.GetProperty( mPropertyPosition ).Get().y ); + DALI_LOG_SCROLL_STATE("[0x%X] SCROLL_PRE_POSITION[%.2f, %.2f], SCROLL_POSITION[%.2f, %.2f]", this, self.GetProperty( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get().x, self.GetProperty( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ).Get().y, self.GetProperty( Toolkit::ScrollView::Property::SCROLL_POSITION ).Get().x, self.GetProperty( Toolkit::ScrollView::Property::SCROLL_POSITION ).Get().y ); } SetScrollUpdateNotification(true); @@ -1728,14 +1722,14 @@ void ScrollView::FindAndUnbindActor(Actor child) Vector3 ScrollView::GetPropertyPrePosition() const { - Vector3 position = Self().GetProperty(mPropertyPrePosition); + Vector3 position = Self().GetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION); WrapPosition(position); return position; } Vector3 ScrollView::GetPropertyPosition() const { - Vector3 position = Self().GetProperty(mPropertyPosition); + Vector3 position = Self().GetProperty(Toolkit::ScrollView::Property::SCROLL_POSITION); WrapPosition(position); return position; @@ -1751,21 +1745,21 @@ void ScrollView::HandleSnapAnimationFinished() // Emit Signal that scrolling has completed. mScrolling = false; Actor self = Self(); - self.SetProperty(mPropertyScrolling, false); + self.SetProperty(Toolkit::ScrollView::Property::SCROLLING, false); Vector3 deltaPosition(mScrollPrePosition); UpdateLocalScrollProperties(); WrapPosition(mScrollPrePosition); - DALI_LOG_SCROLL_STATE("[0x%X] Setting mPropertyPrePosition To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y ); - self.SetProperty(mPropertyPrePosition, mScrollPrePosition); + DALI_LOG_SCROLL_STATE("[0x%X] Setting SCROLL_PRE_POSITION To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y ); + self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, mScrollPrePosition); Vector3 currentScrollPosition = GetCurrentScrollPosition(); DALI_LOG_SCROLL_STATE("[0x%X] mScrollCompletedSignal 3 current[%.2f, %.2f], mScrollTargetPosition[%.2f, %.2f]", this, currentScrollPosition.x, currentScrollPosition.y, -mScrollTargetPosition.x, -mScrollTargetPosition.y ); mScrollCompletedSignal.Emit( currentScrollPosition ); mDomainOffset += deltaPosition - mScrollPostPosition; - self.SetProperty(mPropertyDomainOffset, mDomainOffset); + self.SetProperty(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET, mDomainOffset); HandleStoppedAnimation(); } @@ -1782,7 +1776,7 @@ void ScrollView::SetScrollUpdateNotification( bool enabled ) if( enabled && !mScrollUpdatedSignal.Empty()) { // Only set up the notification when the application has connected to the updated signal - mScrollXUpdateNotification = self.AddPropertyNotification(mPropertyPosition, 0, StepCondition(mScrollUpdateDistance, 0.0f)); + mScrollXUpdateNotification = self.AddPropertyNotification(Toolkit::ScrollView::Property::SCROLL_POSITION, 0, StepCondition(mScrollUpdateDistance, 0.0f)); mScrollXUpdateNotification.NotifySignal().Connect( this, &ScrollView::OnScrollUpdateNotification ); } if( mScrollYUpdateNotification ) @@ -1795,7 +1789,7 @@ void ScrollView::SetScrollUpdateNotification( bool enabled ) if( enabled && !mScrollUpdatedSignal.Empty()) { // Only set up the notification when the application has connected to the updated signal - mScrollYUpdateNotification = self.AddPropertyNotification(mPropertyPosition, 1, StepCondition(mScrollUpdateDistance, 0.0f)); + mScrollYUpdateNotification = self.AddPropertyNotification(Toolkit::ScrollView::Property::SCROLL_POSITION, 1, StepCondition(mScrollUpdateDistance, 0.0f)); mScrollYUpdateNotification.NotifySignal().Connect( this, &ScrollView::OnScrollUpdateNotification ); } } @@ -1869,16 +1863,6 @@ void ScrollView::OnChildRemove(Actor& child) UnbindActor(child); } -void ScrollView::OnPropertySet( Property::Index index, Property::Value propertyValue ) -{ - Actor self = Self(); - if( index == mPropertyPrePosition ) - { - DALI_LOG_SCROLL_STATE("[0x%X]: mPropertyPrePosition[%.2f, %.2f]", this, propertyValue.Get().x, propertyValue.Get().y); - propertyValue.Get(mScrollPrePosition); - } -} - void ScrollView::StartTouchDownTimer() { if ( !mTouchDownTimer ) @@ -1917,7 +1901,7 @@ bool ScrollView::OnTouchDownTimeout() mScrollInterrupted = true; // reset domain offset as scrolling from original plane. mDomainOffset = Vector3::ZERO; - Self().SetProperty(mPropertyDomainOffset, Vector3::ZERO); + Self().SetProperty(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET, Vector3::ZERO); UpdateLocalScrollProperties(); Vector3 currentScrollPosition = GetCurrentScrollPosition(); @@ -2047,32 +2031,32 @@ bool ScrollView::OnMouseWheelEvent(const MouseWheelEvent& event) void ScrollView::ResetScrolling() { Actor self = Self(); - self.GetProperty(mPropertyPosition).Get(mScrollPostPosition); + self.GetProperty(Toolkit::ScrollView::Property::SCROLL_POSITION).Get(mScrollPostPosition); mScrollPrePosition = mScrollPostPosition; - DALI_LOG_SCROLL_STATE("[0x%X] Setting mPropertyPrePosition To[%.2f, %.2f]", this, mScrollPostPosition.x, mScrollPostPosition.y ); - self.SetProperty(mPropertyPrePosition, mScrollPostPosition); + DALI_LOG_SCROLL_STATE("[0x%X] Setting SCROLL_PRE_POSITION To[%.2f, %.2f]", this, mScrollPostPosition.x, mScrollPostPosition.y ); + self.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, mScrollPostPosition); } void ScrollView::UpdateLocalScrollProperties() { Actor self = Self(); - self.GetProperty(mPropertyPrePosition).Get(mScrollPrePosition); - self.GetProperty(mPropertyPosition).Get(mScrollPostPosition); + self.GetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION).Get(mScrollPrePosition); + self.GetProperty(Toolkit::ScrollView::Property::SCROLL_POSITION).Get(mScrollPostPosition); } // private functions void ScrollView::PreAnimatedScrollSetup() { - // mPropertyPrePosition is our unclamped property with wrapping - // mPropertyPosition is our final scroll position after clamping + // SCROLL_PRE_POSITION is our unclamped property with wrapping + // SCROLL_POSITION is our final scroll position after clamping Actor self = Self(); Vector3 deltaPosition(mScrollPostPosition); WrapPosition(mScrollPostPosition); mDomainOffset += deltaPosition - mScrollPostPosition; - Self().SetProperty(mPropertyDomainOffset, mDomainOffset); + Self().SetProperty(Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET, mDomainOffset); if( mScrollStateFlags & SCROLL_X_STATE_MASK ) { @@ -2103,11 +2087,11 @@ void ScrollView::AnimateInternalXTo( float position, float duration, AlphaFuncti if( duration > Math::MACHINE_EPSILON_10 ) { Actor self = Self(); - DALI_LOG_SCROLL_STATE("[0x%X], Animating from[%.2f] to[%.2f]", this, self.GetProperty(mPropertyPrePosition).Get().x, position ); + DALI_LOG_SCROLL_STATE("[0x%X], Animating from[%.2f] to[%.2f]", this, self.GetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION).Get().x, position ); mInternalXAnimation = Animation::New(duration); DALI_LOG_SCROLL_STATE("[0x%X], mInternalXAnimation[0x%X]", this, mInternalXAnimation.GetObjectPtr() ); mInternalXAnimation.FinishedSignal().Connect(this, &ScrollView::OnScrollAnimationFinished); - mInternalXAnimation.AnimateTo( Property(self, mPropertyPrePosition, 0), position, alpha, duration); + mInternalXAnimation.AnimateTo( Property(self, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, 0), position, alpha, duration); mInternalXAnimation.Play(); // erase current state flags @@ -2124,11 +2108,11 @@ void ScrollView::AnimateInternalYTo( float position, float duration, AlphaFuncti if( duration > Math::MACHINE_EPSILON_10 ) { Actor self = Self(); - DALI_LOG_SCROLL_STATE("[0x%X], Animating from[%.2f] to[%.2f]", this, self.GetProperty(mPropertyPrePosition).Get().y, position ); + DALI_LOG_SCROLL_STATE("[0x%X], Animating from[%.2f] to[%.2f]", this, self.GetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION).Get().y, position ); mInternalYAnimation = Animation::New(duration); DALI_LOG_SCROLL_STATE("[0x%X], mInternalYAnimation[0x%X]", this, mInternalYAnimation.GetObjectPtr() ); mInternalYAnimation.FinishedSignal().Connect(this, &ScrollView::OnScrollAnimationFinished); - mInternalYAnimation.AnimateTo( Property(self, mPropertyPrePosition, 1), position, alpha, TimePeriod(duration)); + mInternalYAnimation.AnimateTo( Property(self, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, 1), position, alpha, TimePeriod(duration)); mInternalYAnimation.Play(); // erase current state flags @@ -2151,7 +2135,7 @@ void ScrollView::OnScrollAnimationFinished( Animation& source ) if( source == mInternalXAnimation ) { - DALI_LOG_SCROLL_STATE("[0x%X] mInternalXAnimation[0x%X], expected[%.2f], actual[%.2f], post[%.2f]", this, mInternalXAnimation.GetObjectPtr(), mScrollTargetPosition.x, Self().GetProperty(mPropertyPrePosition).Get().x, mScrollPostPosition.x ); + DALI_LOG_SCROLL_STATE("[0x%X] mInternalXAnimation[0x%X], expected[%.2f], actual[%.2f], post[%.2f]", this, mInternalXAnimation.GetObjectPtr(), mScrollTargetPosition.x, Self().GetProperty(SCROLL_PRE_POSITION).Get().x, mScrollPostPosition.x ); if( !(mScrollStateFlags & AnimatingInternalY) ) { @@ -2163,15 +2147,15 @@ void ScrollView::OnScrollAnimationFinished( Animation& source ) { const RulerDomain rulerDomain = mRulerX->GetDomain(); mScrollPrePosition.x = -WrapInDomain(-mScrollPrePosition.x, rulerDomain.min, rulerDomain.max); - DALI_LOG_SCROLL_STATE("[0x%X] Setting mPropertyPrePosition To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y ); - handle.SetProperty(mPropertyPrePosition, mScrollPrePosition); + DALI_LOG_SCROLL_STATE("[0x%X] Setting SCROLL_PRE_POSITION To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y ); + handle.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, mScrollPrePosition); } SnapInternalXTo(mScrollPostPosition.x); } if( source == mInternalYAnimation ) { - DALI_LOG_SCROLL_STATE("[0x%X] mInternalYAnimation[0x%X], expected[%.2f], actual[%.2f], post[%.2f]", this, mInternalYAnimation.GetObjectPtr(), mScrollTargetPosition.y, Self().GetProperty(mPropertyPrePosition).Get().y, mScrollPostPosition.y ); + DALI_LOG_SCROLL_STATE("[0x%X] mInternalYAnimation[0x%X], expected[%.2f], actual[%.2f], post[%.2f]", this, mInternalYAnimation.GetObjectPtr(), mScrollTargetPosition.y, Self().GetProperty(SCROLL_PRE_POSITION).Get().y, mScrollPostPosition.y ); if( !(mScrollStateFlags & AnimatingInternalX) ) { @@ -2183,8 +2167,8 @@ void ScrollView::OnScrollAnimationFinished( Animation& source ) // wrap pre scroll y position and set it const RulerDomain rulerDomain = mRulerY->GetDomain(); mScrollPrePosition.y = -WrapInDomain(-mScrollPrePosition.y, rulerDomain.min, rulerDomain.max); - DALI_LOG_SCROLL_STATE("[0x%X] Setting mPropertyPrePosition To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y ); - handle.SetProperty(mPropertyPrePosition, mScrollPrePosition); + DALI_LOG_SCROLL_STATE("[0x%X] Setting SCROLL_PRE_POSITION To[%.2f, %.2f]", this, mScrollPrePosition.x, mScrollPrePosition.y ); + handle.SetProperty(Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, mScrollPrePosition); } SnapInternalYTo(mScrollPostPosition.y); } @@ -2238,7 +2222,7 @@ void ScrollView::SnapInternalXTo(float position) mInternalXAnimation = Animation::New(duration); mInternalXAnimation.FinishedSignal().Connect(this, &ScrollView::OnSnapInternalPositionFinished); - mInternalXAnimation.AnimateTo(Property(self, mPropertyPrePosition, 0), position); + mInternalXAnimation.AnimateTo(Property(self, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, 0), position); mInternalXAnimation.Play(); // add internal animation state flag @@ -2264,7 +2248,7 @@ void ScrollView::SnapInternalYTo(float position) mInternalYAnimation = Animation::New(duration); mInternalYAnimation.FinishedSignal().Connect(this, &ScrollView::OnSnapInternalPositionFinished); - mInternalYAnimation.AnimateTo(Property(self, mPropertyPrePosition, 1), position); + mInternalYAnimation.AnimateTo(Property(self, Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, 1), position); mInternalYAnimation.Play(); // add internal animation state flag @@ -2357,8 +2341,8 @@ void ScrollView::OnPan( const PanGesture& gesture ) UpdateLocalScrollProperties(); GestureStarted(); mPanning = true; - self.SetProperty( mPropertyPanning, true ); - self.SetProperty( mPropertyScrollStartPagePosition, Vector3(gesture.position.x, gesture.position.y, 0.0f) ); + self.SetProperty( Toolkit::ScrollView::Property::PANNING, true ); + self.SetProperty( Toolkit::ScrollView::Property::START_PAGE_POSITION, Vector3(gesture.position.x, gesture.position.y, 0.0f) ); UpdateMainInternalConstraint(); break; @@ -2389,11 +2373,11 @@ void ScrollView::OnPan( const PanGesture& gesture ) UpdateLocalScrollProperties(); mLastVelocity = gesture.velocity; mPanning = false; - self.SetProperty( mPropertyPanning, false ); + self.SetProperty( Toolkit::ScrollView::Property::PANNING, false ); if( mScrollMainInternalPrePositionConstraint ) { - self.RemoveConstraint(mScrollMainInternalPrePositionConstraint); + mScrollMainInternalPrePositionConstraint.Remove(); } if( mOvershootIndicator ) @@ -2428,7 +2412,7 @@ void ScrollView::OnGestureEx(Gesture::State state) if(state == Gesture::Started) { Vector3 currentScrollPosition = GetCurrentScrollPosition(); - Self().SetProperty(mPropertyScrolling, true); + Self().SetProperty(Toolkit::ScrollView::Property::SCROLLING, true); mScrolling = true; DALI_LOG_SCROLL_STATE("[0x%X] mScrollStartedSignal 2 [%.2f, %.2f]", this, currentScrollPosition.x, currentScrollPosition.y); mScrollStartedSignal.Emit( currentScrollPosition ); @@ -2474,7 +2458,7 @@ void ScrollView::FinishTransform() // if not animating, then this pan has completed right now. SetScrollUpdateNotification(false); mScrolling = false; - Self().SetProperty(mPropertyScrolling, false); + Self().SetProperty(Toolkit::ScrollView::Property::SCROLLING, false); if( fabs(mScrollPrePosition.x - mScrollTargetPosition.x) > Math::MACHINE_EPSILON_10 ) { @@ -2583,14 +2567,14 @@ void ScrollView::UpdateMainInternalConstraint() if(mScrollMainInternalPositionConstraint) { - self.RemoveConstraint(mScrollMainInternalPositionConstraint); - self.RemoveConstraint(mScrollMainInternalDeltaConstraint); - self.RemoveConstraint(mScrollMainInternalFinalConstraint); - self.RemoveConstraint(mScrollMainInternalRelativeConstraint); + mScrollMainInternalPositionConstraint.Remove(); + mScrollMainInternalDeltaConstraint.Remove(); + mScrollMainInternalFinalConstraint.Remove(); + mScrollMainInternalRelativeConstraint.Remove(); } if( mScrollMainInternalPrePositionConstraint ) { - self.RemoveConstraint(mScrollMainInternalPrePositionConstraint); + mScrollMainInternalPrePositionConstraint.Remove(); } // TODO: It's probably better to use a local displacement value as this will give a displacement when scrolling just commences @@ -2607,48 +2591,55 @@ void ScrollView::UpdateMainInternalConstraint() { initialPanMask.x = 0.0f; } - Constraint constraint; if( mPanning ) { - constraint = Constraint::New( mPropertyPrePosition, - Source( detector, PanGestureDetector::Property::LOCAL_POSITION ), - Source( self, Actor::Property::SIZE ), - InternalPrePositionConstraint( mPanStartPosition, initialPanMask, mAxisAutoLock, mAxisAutoLockGradient, mLockAxis, mMaxOvershoot, mRulerX->GetDomain(), mRulerY->GetDomain() ) ); - mScrollMainInternalPrePositionConstraint = self.ApplyConstraint( constraint ); + mScrollMainInternalPrePositionConstraint = Constraint::New( self, + Toolkit::ScrollView::Property::SCROLL_PRE_POSITION, + InternalPrePositionConstraint( mPanStartPosition, + initialPanMask, + mAxisAutoLock, + mAxisAutoLockGradient, + mLockAxis, + mMaxOvershoot, + mRulerX->GetDomain(), + mRulerY->GetDomain() ) ); + mScrollMainInternalPrePositionConstraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) ); + mScrollMainInternalPrePositionConstraint.AddSource( Source( self, Actor::Property::SIZE ) ); + mScrollMainInternalPrePositionConstraint.Apply(); } // 2. Second calculate the clamped position (actual position) - constraint = Constraint::New( mPropertyPosition, - LocalSource( mPropertyPrePosition ), - LocalSource( mPropertyPositionMin ), - LocalSource( mPropertyPositionMax ), - Source( self, Actor::Property::SIZE ), - InternalPositionConstraint( mRulerX->GetDomain(), - mRulerY->GetDomain(), mWrapMode ) ); - mScrollMainInternalPositionConstraint = self.ApplyConstraint( constraint ); - - constraint = Constraint::New( mPropertyPositionDelta, - LocalSource( mPropertyPosition ), - LocalSource( mPropertyDomainOffset ), - InternalPositionDeltaConstraint ); - mScrollMainInternalDeltaConstraint = self.ApplyConstraint( constraint ); - - constraint = Constraint::New( mPropertyFinal, - LocalSource( mPropertyPosition ), - LocalSource( mPropertyOvershootX ), - LocalSource( mPropertyOvershootY ), - InternalFinalConstraint( FinalDefaultAlphaFunction, - FinalDefaultAlphaFunction ) ); - mScrollMainInternalFinalConstraint = self.ApplyConstraint( constraint ); - - constraint = Constraint::New( mPropertyRelativePosition, - LocalSource( mPropertyPosition ), - LocalSource( mPropertyPositionMin ), - LocalSource( mPropertyPositionMax ), - LocalSource( Actor::Property::SIZE ), - InternalRelativePositionConstraint ); - mScrollMainInternalRelativeConstraint = self.ApplyConstraint( constraint ); + mScrollMainInternalPositionConstraint = Constraint::New( self, + Toolkit::ScrollView::Property::SCROLL_POSITION, + InternalPositionConstraint( mRulerX->GetDomain(), + mRulerY->GetDomain(), + mWrapMode ) ); + mScrollMainInternalPositionConstraint.AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ) ); + mScrollMainInternalPositionConstraint.AddSource( LocalSource( Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + mScrollMainInternalPositionConstraint.AddSource( LocalSource( Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + mScrollMainInternalPositionConstraint.AddSource( Source( self, Actor::Property::SIZE ) ); + mScrollMainInternalPositionConstraint.Apply(); + + mScrollMainInternalDeltaConstraint = Constraint::New( self, Toolkit::ScrollView::Property::SCROLL_POSITION_DELTA, InternalPositionDeltaConstraint ); + mScrollMainInternalDeltaConstraint.AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + mScrollMainInternalDeltaConstraint.AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_DOMAIN_OFFSET ) ); + mScrollMainInternalDeltaConstraint.Apply(); + + mScrollMainInternalFinalConstraint = Constraint::New( self, Toolkit::ScrollView::Property::SCROLL_FINAL, + InternalFinalConstraint( FinalDefaultAlphaFunction, + FinalDefaultAlphaFunction ) ); + mScrollMainInternalFinalConstraint .AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + mScrollMainInternalFinalConstraint .AddSource( LocalSource( Toolkit::ScrollView::Property::OVERSHOOT_X ) ); + mScrollMainInternalFinalConstraint .AddSource( LocalSource( Toolkit::ScrollView::Property::OVERSHOOT_Y ) ); + mScrollMainInternalFinalConstraint.Apply(); + + mScrollMainInternalRelativeConstraint = Constraint::New( self, Toolkit::Scrollable::Property::SCROLL_RELATIVE_POSITION, InternalRelativePositionConstraint ); + mScrollMainInternalRelativeConstraint.AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + mScrollMainInternalRelativeConstraint.AddSource( LocalSource( Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + mScrollMainInternalRelativeConstraint.AddSource( LocalSource( Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + mScrollMainInternalRelativeConstraint.AddSource( LocalSource( Actor::Property::SIZE ) ); + mScrollMainInternalRelativeConstraint.Apply(); // When panning we want to make sure overshoot values are affected by pre position and post position SetOvershootConstraintsEnabled(!mWrapMode); @@ -2660,31 +2651,29 @@ void ScrollView::SetOvershootConstraintsEnabled(bool enabled) // remove and reset, it may now be in wrong order with the main internal constraints if( mScrollMainInternalOvershootXConstraint ) { - self.RemoveConstraint(mScrollMainInternalOvershootXConstraint); + mScrollMainInternalOvershootXConstraint.Remove(); mScrollMainInternalOvershootXConstraint.Reset(); - self.RemoveConstraint(mScrollMainInternalOvershootYConstraint); + mScrollMainInternalOvershootYConstraint.Remove(); mScrollMainInternalOvershootYConstraint.Reset(); } if( enabled ) { - Constraint constraint = Constraint::New( mPropertyOvershootX, - LocalSource( mPropertyPrePosition ), - LocalSource( mPropertyPosition ), - LocalSource( mPropertyCanScrollHorizontal ), - OvershootXConstraint(mMaxOvershoot.x) ); - mScrollMainInternalOvershootXConstraint = self.ApplyConstraint( constraint ); + mScrollMainInternalOvershootXConstraint= Constraint::New( self, Toolkit::ScrollView::Property::OVERSHOOT_X, OvershootXConstraint(mMaxOvershoot.x) ); + mScrollMainInternalOvershootXConstraint.AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ) ); + mScrollMainInternalOvershootXConstraint.AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + mScrollMainInternalOvershootXConstraint.AddSource( LocalSource( Toolkit::Scrollable::Property::CAN_SCROLL_HORIZONTAL ) ); + mScrollMainInternalOvershootXConstraint.Apply(); - constraint = Constraint::New( mPropertyOvershootY, - LocalSource( mPropertyPrePosition ), - LocalSource( mPropertyPosition ), - LocalSource( mPropertyCanScrollVertical ), - OvershootYConstraint(mMaxOvershoot.y) ); - mScrollMainInternalOvershootYConstraint = self.ApplyConstraint( constraint ); + mScrollMainInternalOvershootYConstraint = Constraint::New( self, Toolkit::ScrollView::Property::OVERSHOOT_Y, OvershootYConstraint(mMaxOvershoot.y) ); + mScrollMainInternalOvershootYConstraint.AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_PRE_POSITION ) ); + mScrollMainInternalOvershootYConstraint.AddSource( LocalSource( Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + mScrollMainInternalOvershootYConstraint.AddSource( LocalSource( Toolkit::Scrollable::Property::CAN_SCROLL_VERTICAL ) ); + mScrollMainInternalOvershootYConstraint.Apply(); } else { - self.SetProperty(mPropertyOvershootX, 0.0f); - self.SetProperty(mPropertyOvershootY, 0.0f); + self.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_X, 0.0f); + self.SetProperty(Toolkit::ScrollView::Property::OVERSHOOT_Y, 0.0f); } } @@ -2702,21 +2691,19 @@ void ScrollView::SetInternalConstraints() Constraint constraint; // MoveActor (scrolling) - constraint = Constraint::New( Actor::Property::POSITION, - Source( self, mPropertyPosition ), - MoveActorConstraint ); + constraint = Constraint::New( self, Actor::Property::POSITION, MoveActorConstraint ); + constraint.AddSource( Source( self, Toolkit::ScrollView::Property::SCROLL_POSITION ) ); constraint.SetRemoveAction(Constraint::Discard); ApplyConstraintToBoundActors(constraint); // WrapActor (wrap functionality) - constraint = Constraint::New( Actor::Property::POSITION, - LocalSource( Actor::Property::SCALE ), - LocalSource( Actor::Property::ANCHOR_POINT ), - LocalSource( Actor::Property::SIZE ), - Source( self, mPropertyPositionMin ), - Source( self, mPropertyPositionMax ), - Source( self, mPropertyWrap ), - WrapActorConstraint ); + constraint = Constraint::New( self, Actor::Property::POSITION, WrapActorConstraint ); + constraint.AddSource( LocalSource( Actor::Property::SCALE ) ); + constraint.AddSource( LocalSource( Actor::Property::ANCHOR_POINT ) ); + constraint.AddSource( LocalSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source( self, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source( self, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source( self, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction(Constraint::Discard); ApplyConstraintToBoundActors(constraint); } diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h index 8f9abc7..f4d211b 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-impl.h @@ -525,11 +525,6 @@ private: // private overriden functions from CustomActorImpl and Controls virtual void OnChildRemove(Actor& child); /** - * @copydoc Dali::CustomActorImpl::OnPropertySet( Property::Index index, Property::Value propertyValue ) - */ - virtual void OnPropertySet( Property::Index index, Property::Value propertyValue ); - - /** * From CustomActorImpl; called after a touch-signal is received by the owning actor. * * We don't listen to these events as content within the contain may consume events. @@ -591,7 +586,7 @@ private: /** * Called whenever a snap animation has completed * @param[in] source the Animation instance that has completed. - * Resets all scrolling animations and states, leaving current scroll position at mPropertyPosition + * Resets all scrolling animations and states, leaving current scroll position at SCROLL_POSITION */ void ResetScrolling(); @@ -636,7 +631,7 @@ private: void OnScrollAnimationFinished( Animation& source ); /** - * Called when either the X or Y internal scroll positions have finished snapping back to mPropertyPrePosition + * Called when either the X or Y internal scroll positions have finished snapping back to SCROLL_PRE_POSITION * * @param[in] source the Animation instance that has completed. */ @@ -893,13 +888,13 @@ private: Vector2 mMouseWheelScrollDistanceStep; ///< The step of scroll distance in actor coordinates in X and Y axes for each mouse wheel event received. //ScrollInternalConstraintsPtr mScrollInternalConstraints; - ActiveConstraint mScrollMainInternalPrePositionConstraint; - ActiveConstraint mScrollMainInternalPositionConstraint; - ActiveConstraint mScrollMainInternalOvershootXConstraint; - ActiveConstraint mScrollMainInternalOvershootYConstraint; - ActiveConstraint mScrollMainInternalDeltaConstraint; - ActiveConstraint mScrollMainInternalFinalConstraint; - ActiveConstraint mScrollMainInternalRelativeConstraint; + Constraint mScrollMainInternalPrePositionConstraint; + Constraint mScrollMainInternalPositionConstraint; + Constraint mScrollMainInternalOvershootXConstraint; + Constraint mScrollMainInternalOvershootYConstraint; + Constraint mScrollMainInternalDeltaConstraint; + Constraint mScrollMainInternalFinalConstraint; + Constraint mScrollMainInternalRelativeConstraint; ScrollOvershootIndicatorPtr mOvershootIndicator; diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-carousel-effect-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-carousel-effect-impl.cpp index fb4578e..e44800d 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-carousel-effect-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-carousel-effect-impl.cpp @@ -19,8 +19,6 @@ #include // EXTERNAL INCLUDES -#include -#include #include #include @@ -66,25 +64,20 @@ public: } /** - * @param[in] current The current color of this Actor - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current color of this Actor + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new color of this Actor. */ - Vector4 ColorConstraint(const Vector4& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void ColorConstraint( Vector4& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -92,14 +85,14 @@ public: // short circuit: if we're looking straight on at the page. if( IsStraightOnView( position ) ) { - return current; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); + const Vector3& pageSize = inputs[4]->GetVector3(); - if( scrollWrap.GetBoolean() ) + if( inputs[5]->GetBoolean() ) { - WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() ); + WrapPositionWithinDomain( position, pageSize, inputs[2]->GetVector3(), inputs[3]->GetVector3() ); } // short circuit: for pages outside of view. @@ -107,36 +100,29 @@ public: { // note preserve color channels incase there is a shader/further constraint // that wishes to do something with that information. - return Vector4(current.r, current.g, current.b, 0.0f); + current.a = 0.0f; + return; } - Vector4 color( current ); Vector2 distance( position / pageSize * PAGE_SIZE_MULTIPLIER ); - color.a = Clamp( 1.0f - distance.Length(), 0.0f, 1.0f ); - - return color; + current.a = Clamp( 1.0f - distance.Length(), 0.0f, 1.0f ); } /** - * @param[in] current The current position - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current position + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new position of this Actor. */ - Vector3 PositionConstraint(const Vector3& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void PositionConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -144,14 +130,15 @@ public: // short circuit: if we're looking straight on at the page. if( IsStraightOnView( position ) ) { - return current + scrollPosition; + current += scrollPosition; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); + const Vector3& pageSize = inputs[4]->GetVector3(); - if( scrollWrap.GetBoolean() ) + if( inputs[5]->GetBoolean() ) { - WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() ); + WrapPositionWithinDomain( position, pageSize, inputs[2]->GetVector3(), inputs[3]->GetVector3() ); } // short circuit: for pages outside of view. @@ -159,7 +146,8 @@ public: { // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this) // they will be invisible so doesn't have to be precise, just away from stage. - return current + scrollPosition; + current += scrollPosition; + return; } Vector3 angle( position / pageSize * PAGE_SIZE_MULTIPLIER ); @@ -171,7 +159,7 @@ public: zMovement *= mPositionToPageSizeRatio; position.z = - ( ( zMovement.x - ( zMovement.x * cos( angle.x ) ) ) + ( zMovement.y - ( zMovement.y * cos( angle.y ) ) ) ); - return position; + current = position; } const Vector2 mPositionToPageSizeRatio; ///< The page will move its position according to this ratio. @@ -190,29 +178,25 @@ void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView, { // Apply constraints to this actor // Constraint constraint; - constraint = Constraint::New( Actor::Property::COLOR, - LocalSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - boost::bind( &ScrollPageCarouselEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint = Constraint::New( child, Actor::Property::COLOR, info, &ScrollPageCarouselEffectInfo::ColorConstraint ); + constraint.AddSource( LocalSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::POSITION, - LocalSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - boost::bind( &ScrollPageCarouselEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::POSITION, info, &ScrollPageCarouselEffectInfo::PositionConstraint ); + constraint.AddSource( LocalSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); + constraint.Apply(); } } // unnamed namespace diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-cube-effect-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-cube-effect-impl.cpp index 27e43e1..1184ca6 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-cube-effect-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-cube-effect-impl.cpp @@ -19,8 +19,6 @@ #include // EXTERNAL INCLUDES -#include -#include #include #include @@ -69,25 +67,20 @@ public: } /** - * @param[in] current The current orientation of this Actor - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current orientation of this Actor + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new orientation of this Actor. */ - Quaternion RotationConstraint(const Quaternion& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void RotationConstraint( Quaternion& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -95,53 +88,46 @@ public: // short circuit: if we're looking straight on at the page. if( IsStraightOnView( position ) ) { - return current; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); + const Vector3& pageSize = inputs[4]->GetVector3(); - if( scrollWrap.GetBoolean() ) + if( inputs[5]->GetBoolean() ) { - WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() ); + WrapPositionWithinDomain( position, pageSize, inputs[2]->GetVector3(), inputs[3]->GetVector3() ); } // short circuit: for pages outside of view. if( IsOutsideView( position, pageSize ) ) { - return current; + return; } // Our target is a 90 degree (PI/2) rotation per page, so calculate the angle we should be rotate // our page by calculating the amount we've moved as a fraction of the total size of the page. Vector2 angle( position / pageSize * Dali::Math::PI_2 ); - Quaternion rotation = Quaternion( -angle.x * mAngleSwing.x, Vector3::YAXIS ) * - Quaternion( angle.y * mAngleSwing.y, Vector3::XAXIS ) * - current; - - return rotation; + current = Quaternion( Radian( -angle.x * mAngleSwing.x ), Vector3::YAXIS ) * + Quaternion( Radian( angle.y * mAngleSwing.y ), Vector3::XAXIS ) * + current; } /** - * @param[in] current The current color of this Actor - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current color of this Actor + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new color of this Actor. */ - Vector4 ColorConstraint(const Vector4& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void ColorConstraint( Vector4& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -149,14 +135,14 @@ public: // short circuit: if we're looking straight on at the page. if( IsStraightOnView( position ) ) { - return current; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); + const Vector3& pageSize = inputs[4]->GetVector3(); - if( scrollWrap.GetBoolean() ) + if( inputs[5]->GetBoolean() ) { - WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() ); + WrapPositionWithinDomain( position, pageSize, inputs[2]->GetVector3(), inputs[3]->GetVector3() ); } // short circuit: for pages outside of view. @@ -164,7 +150,8 @@ public: { // note preserve color channels incase there is a shader/further constraint // that wishes to do something with that information. - return Vector4(current.r, current.g, current.b, 0.0f); + current.a = 0.0f; + return; } // Calculate the distance of this page from our view and ensure it falls within the appropriate @@ -176,32 +163,25 @@ public: if ( distanceFactor > 1.0f ) { - return Vector4(current.r, current.g, current.b, 0.0f); + current.a = 0.0f; } - - return current; } /** - * @param[in] current The current position - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollWrap Whether scroll wrap has been enabled or not (SCROLL_WRAP_PROPERTY_NAME) + * @param[in,out] current The current position + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * Whether scroll wrap has been enabled or not (SCROLL_WRAP) * @return The new position of this Actor. */ - Vector3 PositionConstraint(const Vector3& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollWrap) + void PositionConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -209,14 +189,15 @@ public: // short circuit: if we're looking straight on at the page. if( IsStraightOnView( position ) ) { - return current + scrollPosition; + current += scrollPosition; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); + const Vector3& pageSize = inputs[4]->GetVector3(); - if( scrollWrap.GetBoolean() ) + if( inputs[5]->GetBoolean() ) { - WrapPositionWithinDomain( position, pageSize, scrollPositionMin.GetVector3(), scrollPositionMax.GetVector3() ); + WrapPositionWithinDomain( position, pageSize, inputs[2]->GetVector3(), inputs[3]->GetVector3() ); } // short circuit: for pages outside of view. @@ -224,7 +205,8 @@ public: { // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this) // they will be invisible so doesn't have to be precise, just away from stage. - return current + scrollPosition; + current += scrollPosition; + return; } // Our target when scrolling is moving from the origin to the following points around a curve: @@ -236,11 +218,9 @@ public: Vector2 angle( position / pageSize * Dali::Math::PI_2 ); Vector2 radius( pageSize * 0.5 ); - position.x = radius.x * sin( angle.x ); - position.y = radius.y * sin( angle.y ); - position.z = ( radius.x - ( radius.x * cos( angle.x ) ) ) + ( radius.y - ( radius.y * cos( angle.y ) ) ); - - return position; + current.x = radius.x * sin( angle.x ); + current.y = radius.y * sin( angle.y ); + current.z = ( radius.x - ( radius.x * cos( angle.x ) ) ) + ( radius.y - ( radius.y * cos( angle.y ) ) ); } Vector2 mAngleSwing; ///< Maximum amount in X and Y axes to rotate. @@ -259,41 +239,35 @@ void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView, { // Apply constraints to this actor // Constraint constraint; - constraint = Constraint::New( Actor::Property::ORIENTATION, - LocalSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - boost::bind( &ScrollPageCubeEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint = Constraint::New( child, Actor::Property::ORIENTATION, info, &ScrollPageCubeEffectInfo::RotationConstraint ); + constraint.AddSource( LocalSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::COLOR, - LocalSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - boost::bind( &ScrollPageCubeEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::COLOR, info, &ScrollPageCubeEffectInfo::ColorConstraint ); + constraint.AddSource( LocalSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::POSITION, - LocalSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_WRAP_PROPERTY_NAME ) ), - boost::bind( &ScrollPageCubeEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::POSITION, info, &ScrollPageCubeEffectInfo::PositionConstraint ); + constraint.AddSource( LocalSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::WRAP ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); + constraint.Apply(); } } // unnamed namespace diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-spiral-effect-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-spiral-effect-impl.cpp index b414458..10d6d1e 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-spiral-effect-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-spiral-effect-impl.cpp @@ -18,9 +18,6 @@ // CLASS HEADER #include -// EXTERNAL INCLUDES -#include - // INTERNAL INCLUDES #include #include @@ -80,26 +77,21 @@ public: } /** - * @param[in] current The current orientation of this Actor - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollPageStartPositionProperty The position of the page where scrolling started. (SCROLL_START_PAGE_POSITION_PROPERTY_NAME) + * @param[in,out] current The current orientation of this Actor + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * The position of the page where scrolling started. (SCROLL_START_PAGE_POSITION) * @return The new orientation of this Actor. */ - Quaternion RotationConstraint(const Quaternion& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollStartPagePositionProperty) + void RotationConstraint( Quaternion& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); - const Vector3& scrollStartPagePosition = scrollStartPagePositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); + const Vector3& scrollStartPagePosition = inputs[5]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -107,12 +99,12 @@ public: // short circuit: if we're looking straight on at the page. if( IsStraightOnView( position ) ) { - return current; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); - const Vector3& minScrollPosition( scrollPositionMin.GetVector3() ); - const Vector3& maxScrollPosition( scrollPositionMax.GetVector3() ); + const Vector3& pageSize = inputs[4]->GetVector3(); + const Vector3& minScrollPosition( inputs[2]->GetVector3() ); + const Vector3& maxScrollPosition( inputs[3]->GetVector3() ); if( mScrollWrap ) { @@ -122,7 +114,7 @@ public: // short circuit: for pages outside of view. if( IsOutsideView( position, pageSize ) ) { - return current; + return; } Vector2 angle( position / ( pageSize * PAGE_SIZE_RELATIVE_ANGLE_FACTOR ) * Vector3( mSpiralAngle ) ); @@ -153,34 +145,27 @@ public: } ClampInPlace( angle.y, -angleMaxMin.y, angleMaxMin.y ); - Quaternion rotation = Quaternion( angle.x, Vector3::YAXIS ) * - Quaternion( angle.y, Vector3::XAXIS ) * - current; - - return rotation; + current = Quaternion( Radian( angle.x ), Vector3::YAXIS ) * + Quaternion( Radian( angle.y ), Vector3::XAXIS ) * + current; } /** - * @param[in] current The current color of this Actor - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollPageStartPositionProperty The position of the page where scrolling started. (SCROLL_START_PAGE_POSITION_PROPERTY_NAME) + * @param[in,out] current The current color of this Actor + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * The position of the page where scrolling started. (SCROLL_START_PAGE_POSITION) * @return The new color of this Actor. */ - Vector4 ColorConstraint(const Vector4& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollStartPagePositionProperty) + void ColorConstraint( Vector4& color, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); - const Vector3& scrollStartPagePosition = scrollStartPagePositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); + const Vector3& scrollStartPagePosition = inputs[5]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -188,12 +173,12 @@ public: // short circuit: if we're looking straight on at the page. if( IsStraightOnView( position ) ) { - return current; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); - const Vector3& minScrollPosition( scrollPositionMin.GetVector3() ); - const Vector3& maxScrollPosition( scrollPositionMax.GetVector3() ); + const Vector3& pageSize = inputs[4]->GetVector3(); + const Vector3& minScrollPosition( inputs[2]->GetVector3() ); + const Vector3& maxScrollPosition( inputs[3]->GetVector3() ); if( mScrollWrap ) { @@ -205,10 +190,10 @@ public: { // note preserve color channels incase there is a shader/further constraint // that wishes to do something with that information. - return Vector4(current.r, current.g, current.b, 0.0f); + color.a = 0.0f; + return; } - Vector4 color( current ); Vector2 distance( position / pageSize ); float distanceLength( distance.Length() ); const Vector2 epsilon( pageSize * PAGE_EPSILON_FACTOR ); @@ -244,31 +229,24 @@ public: { color.a = 0.0f; } - - return color; } /** - * @param[in] current The current position - * @param[in] pagePositionProperty The page's position. - * @param[in] scrollPositionProperty The scroll-view's position property (SCROLL_POSITION_PROPERTY_NAME) - * @param[in] scrollPositionMin The minimum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] scrollPositionMax The maximum extent of this scroll domain. (SCROLL_POSITION_MIN_PROPERTY_NAME) - * @param[in] pageSizeProperty The size of the page. (scrollView SIZE) - * @param[in] scrollPageStartPositionProperty The position of the page where scrolling started. (SCROLL_START_PAGE_POSITION_PROPERTY_NAME) + * @param[in,out] current The current position + * @param[in] inputs Contains: + * The page's position. + * The scroll-view's position property (SCROLL_POSITION) + * The minimum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The maximum extent of this scroll domain. (SCROLL_POSITION_MIN) + * The size of the page. (scrollView SIZE) + * The position of the page where scrolling started. (SCROLL_START_PAGE_POSITION) * @return The new position of this Actor. */ - Vector3 PositionConstraint(const Vector3& current, - const PropertyInput& pagePositionProperty, - const PropertyInput& scrollPositionProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& pageSizeProperty, - const PropertyInput& scrollStartPagePositionProperty) + void PositionConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - const Vector3& pagePosition = pagePositionProperty.GetVector3(); - const Vector3& scrollPosition = scrollPositionProperty.GetVector3(); - const Vector3& scrollStartPagePosition = scrollStartPagePositionProperty.GetVector3(); + const Vector3& pagePosition = inputs[0]->GetVector3(); + const Vector3& scrollPosition = inputs[1]->GetVector3(); + const Vector3& scrollStartPagePosition = inputs[5]->GetVector3(); // Get position of page. Vector3 position = pagePosition + scrollPosition; @@ -276,12 +254,13 @@ public: // short circuit: if we're looking straight on at the page. if( IsStraightOnView( position ) ) { - return current + scrollPosition; + current += scrollPosition; + return; } - const Vector3& pageSize = pageSizeProperty.GetVector3(); - const Vector3& minScrollPosition( scrollPositionMin.GetVector3() ); - const Vector3& maxScrollPosition( scrollPositionMax.GetVector3() ); + const Vector3& pageSize = inputs[4]->GetVector3(); + const Vector3& minScrollPosition( inputs[2]->GetVector3() ); + const Vector3& maxScrollPosition( inputs[3]->GetVector3() ); if( mScrollWrap ) { @@ -293,7 +272,8 @@ public: { // position actors at: scrollposition (Property) + pagePosition (Parent) + current (this) // they will be invisible so doesn't have to be precise, just away from stage. - return current + scrollPosition; + current += scrollPosition; + return; } const Vector2 angle( position / pageSize * ( Dali::Math::PI_4 ) ); @@ -329,7 +309,7 @@ public: position.z += fabsf( position.y ) * NON_SCROLL_PAGE_Z_POSITION_FACTOR; } - return position; + current = position; } Vector2 mSpiralAngle; ///< The angle of the spirald page @@ -349,41 +329,35 @@ void ApplyScrollCubeConstraints(Toolkit::ScrollView scrollView, { // Apply constraints to this actor // Constraint constraint; - constraint = Constraint::New( Actor::Property::ORIENTATION, - LocalSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_START_PAGE_POSITION_PROPERTY_NAME ) ), - boost::bind( &ScrollPageSpiralEffectInfo::RotationConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint = Constraint::New( child, Actor::Property::ORIENTATION, info, &ScrollPageSpiralEffectInfo::RotationConstraint ); + constraint.AddSource( LocalSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::START_PAGE_POSITION ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::COLOR, - LocalSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_START_PAGE_POSITION_PROPERTY_NAME ) ), - boost::bind( &ScrollPageSpiralEffectInfo::ColorConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::COLOR, info, &ScrollPageSpiralEffectInfo::ColorConstraint ); + constraint.AddSource( LocalSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::START_PAGE_POSITION ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); - - constraint = Constraint::New( Actor::Property::POSITION, - LocalSource(Actor::Property::POSITION), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_FINAL_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MIN_PROPERTY_NAME ) ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_POSITION_MAX_PROPERTY_NAME ) ), - Source(scrollView, Actor::Property::SIZE ), - Source(scrollView, scrollView.GetPropertyIndex( Toolkit::ScrollView::SCROLL_START_PAGE_POSITION_PROPERTY_NAME ) ), - boost::bind( &ScrollPageSpiralEffectInfo::PositionConstraint, info, _1, _2, _3, _4, _5, _6, _7) ); - + constraint.Apply(); + + constraint = Constraint::New( child, Actor::Property::POSITION, info, &ScrollPageSpiralEffectInfo::PositionConstraint ); + constraint.AddSource( LocalSource(Actor::Property::POSITION) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::SCROLL_FINAL ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MIN ) ); + constraint.AddSource( Source(scrollView, Toolkit::Scrollable::Property::SCROLL_POSITION_MAX ) ); + constraint.AddSource( Source(scrollView, Actor::Property::SIZE ) ); + constraint.AddSource( Source(scrollView, Toolkit::ScrollView::Property::START_PAGE_POSITION ) ); constraint.SetRemoveAction( Constraint::Discard ); - child.ApplyConstraint( constraint ); + constraint.Apply(); } } // unnamed namespace diff --git a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-wobble-effect-impl.cpp b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-wobble-effect-impl.cpp index e21ef87..573b792 100644 --- a/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-wobble-effect-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-wobble-effect-impl.cpp @@ -89,19 +89,14 @@ struct ScrollViewWobbleEffectConstraint } /** - * @param[out] current The new wobble value - * @param[in] propertyTime The current time since the wobble effect started - * @param[in] propertyPosition The scroll-position - * @param[in] propertyOffset The scroll-overshoot + * @param[in,out] direction The new wobble value + * @param[in] inputs Contains: + * The current time since the wobble effect started + * The scroll-position + * The scroll-overshoot x & y */ - Vector3 operator()(const Vector3& current, - const PropertyInput& propertyTime, - const PropertyInput& propertyPosition, - const PropertyInput& propertyOffsetX, - const PropertyInput& propertyOffsetY) + void operator()( Vector3& direction, const PropertyInputContainer& inputs ) { - Vector3 dir; - if(mStabilized) { // check if animation cycle id has changed (if so then this spells @@ -114,9 +109,9 @@ struct ScrollViewWobbleEffectConstraint else { // not stable (i.e. wobbling) - Vector3 offset(propertyOffsetX.GetFloat(), propertyOffsetY.GetFloat(), 0.0f); - const Vector3& position = propertyPosition.GetVector3() - offset; - const float time = propertyTime.GetFloat(); + Vector3 offset(inputs[2]->GetFloat(), inputs[3]->GetFloat(), 0.0f); + const Vector3& position = inputs[1]->GetVector3() - offset; + const float time = inputs[0]->GetFloat(); const float timePassed = time - mTime; mTime = time; @@ -159,11 +154,9 @@ struct ScrollViewWobbleEffectConstraint } } - dir.x = propertyPosition.GetVector3().x - mChase.x; - dir.y = propertyPosition.GetVector3().y - mChase.y; + direction.x = position.x - mChase.x; + direction.y = position.y - mChase.y; } // end else - - return dir; } Vector3 mChase; ///< Chaser position @@ -231,10 +224,6 @@ void ScrollViewWobbleEffect::OnDetach(Toolkit::ScrollView& scrollView) void ScrollViewWobbleEffect::AttachActor(Actor actor) { - Property::Index propertyPosition = actor.GetPropertyIndex(Toolkit::ScrollView::SCROLL_POSITION_PROPERTY_NAME); - Property::Index propertyOvershootX = actor.GetPropertyIndex(Toolkit::ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME); - Property::Index propertyOvershootY = actor.GetPropertyIndex(Toolkit::ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME); - // Create effect-overshoot property if not already created. Property::Index propertyEffectOvershoot = actor.GetPropertyIndex(Toolkit::ScrollViewWobbleEffect::EFFECT_OVERSHOOT); if(propertyEffectOvershoot == Property::INVALID_INDEX) @@ -244,13 +233,12 @@ void ScrollViewWobbleEffect::AttachActor(Actor actor) Actor scrollView = GetScrollView(); - Constraint constraint = Constraint::New( propertyEffectOvershoot, - Source(scrollView, mPropertyTime), - Source(actor, propertyPosition), - Source(actor, propertyOvershootX), - Source(actor, propertyOvershootY), - ScrollViewWobbleEffectConstraint(*this) ); - actor.ApplyConstraint(constraint); + Constraint constraint = Constraint::New( actor, propertyEffectOvershoot, ScrollViewWobbleEffectConstraint(*this) ); + constraint.AddSource( Source( scrollView, mPropertyTime ) ); + constraint.AddSource( Source( actor, Toolkit::ScrollView::Property::SCROLL_POSITION ) ); + constraint.AddSource( Source( actor, Toolkit::ScrollView::Property::OVERSHOOT_X ) ); + constraint.AddSource( Source( actor, Toolkit::ScrollView::Property::OVERSHOOT_Y ) ); + constraint.Apply(); } void ScrollViewWobbleEffect::DetachActor(Actor actor) diff --git a/dali-toolkit/internal/controls/scrollable/scrollable-impl.cpp b/dali-toolkit/internal/controls/scrollable/scrollable-impl.cpp index 0c73cd4..5f7cf72 100644 --- a/dali-toolkit/internal/controls/scrollable/scrollable-impl.cpp +++ b/dali-toolkit/internal/controls/scrollable/scrollable-impl.cpp @@ -16,6 +16,7 @@ */ // EXTERNAL INCLUDES +#include // for strcmp #include #include @@ -49,6 +50,13 @@ DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Scrollable, Toolkit::Control, Create ); DALI_PROPERTY_REGISTRATION( Scrollable, "overshoot-effect-color", VECTOR4, OVERSHOOT_EFFECT_COLOR ) DALI_PROPERTY_REGISTRATION( Scrollable, "overshoot-animation-speed", FLOAT, OVERSHOOT_ANIMATION_SPEED ) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "scroll-relative-position", VECTOR3, SCROLL_RELATIVE_POSITION) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "scroll-position-min", VECTOR3, SCROLL_POSITION_MIN) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "scroll-position-max", VECTOR3, SCROLL_POSITION_MAX) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "scroll-direction", VECTOR3, SCROLL_DIRECTION) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "can-scroll-vertical", BOOLEAN, CAN_SCROLL_VERTICAL) +DALI_ANIMATABLE_PROPERTY_REGISTRATION( Scrollable, "can-scroll-horizontal", BOOLEAN, CAN_SCROLL_HORIZONTAL) + DALI_SIGNAL_REGISTRATION( Scrollable, "scroll-started", SIGNAL_SCROLL_STARTED ) DALI_SIGNAL_REGISTRATION( Scrollable, "scroll-completed", SIGNAL_SCROLL_COMPLETED ) DALI_SIGNAL_REGISTRATION( Scrollable, "scroll-updated", SIGNAL_SCROLL_UPDATED ) @@ -60,9 +68,6 @@ const float DEFAULT_OVERSHOOT_ANIMATION_SPEED(120.0f); // 120 pixels per second } -const char* const Scrollable::SCROLLABLE_CAN_SCROLL_VERTICAL = "scrollable-can-scroll-vertical"; -const char* const Scrollable::SCROLLABLE_CAN_SCROLL_HORIZONTAL = "scrollable-can-scroll-horizontal"; - /////////////////////////////////////////////////////////////////////////////////////////////////// // Scrollable /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -73,12 +78,6 @@ Scrollable::Scrollable() : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS | NO_SIZE_NEGOTIATION ) ), mOvershootEffectColor( DEFAULT_OVERSHOOT_COLOUR ), mOvershootAnimationSpeed ( DEFAULT_OVERSHOOT_ANIMATION_SPEED ), - mPropertyRelativePosition(Property::INVALID_INDEX), - mPropertyPositionMin(Property::INVALID_INDEX), - mPropertyPositionMax(Property::INVALID_INDEX), - mPropertyScrollDirection(Property::INVALID_INDEX), - mPropertyCanScrollVertical(Property::INVALID_INDEX), - mPropertyCanScrollHorizontal(Property::INVALID_INDEX), mOvershootEnabled(false) { } @@ -89,19 +88,6 @@ Scrollable::~Scrollable() mComponents.clear(); } -void Scrollable::RegisterCommonProperties() -{ - Actor self = Self(); - - // Register properties. - mPropertyRelativePosition = self.RegisterProperty(Toolkit::Scrollable::SCROLL_RELATIVE_POSITION_PROPERTY_NAME, Vector3::ZERO); - mPropertyPositionMin = self.RegisterProperty(Toolkit::Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME, Vector3::ZERO); - mPropertyPositionMax = self.RegisterProperty(Toolkit::Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME, Vector3::ZERO); - mPropertyScrollDirection = self.RegisterProperty(Toolkit::Scrollable::SCROLL_DIRECTION_PROPERTY_NAME, Vector3::ZERO); - mPropertyCanScrollVertical = self.RegisterProperty(SCROLLABLE_CAN_SCROLL_VERTICAL, true); - mPropertyCanScrollHorizontal = self.RegisterProperty(SCROLLABLE_CAN_SCROLL_HORIZONTAL, true); -} - bool Scrollable::IsScrollComponentEnabled(Toolkit::Scrollable::ScrollComponentType type) const { if(type == Toolkit::Scrollable::OvershootIndicator) diff --git a/dali-toolkit/internal/controls/scrollable/scrollable-impl.h b/dali-toolkit/internal/controls/scrollable/scrollable-impl.h index 799ed62..eb9f377 100644 --- a/dali-toolkit/internal/controls/scrollable/scrollable-impl.h +++ b/dali-toolkit/internal/controls/scrollable/scrollable-impl.h @@ -44,16 +44,6 @@ typedef IntrusivePtr ScrollablePtr; class Scrollable : public Control { public: - static const char* const SCROLLABLE_CAN_SCROLL_VERTICAL; - static const char* const SCROLLABLE_CAN_SCROLL_HORIZONTAL; - - /** - * Create a new Scrollable. - * @return A public handle to the newly allocated Scrollable. - */ -// static Dali::Toolkit::Scrollable New(); - -public: /** * @copydoc Dali::Toolkit::Scrollable::IsScrollComponentEnabled(Scrollable::ScrollComponentType type) @@ -196,11 +186,6 @@ protected: */ virtual ~Scrollable(); - /** - * Register common properties - */ - void RegisterCommonProperties(); - private: /** @@ -231,13 +216,6 @@ protected: Vector4 mOvershootEffectColor; /// mComponent; ///< ScrollComponent (such as a scrollbar/page indicator/status) Toolkit::Scrollable::ScrollStartedSignalType mScrollStartedSignal; diff --git a/dali-toolkit/internal/controls/shadow-view/shadow-view-impl.cpp b/dali-toolkit/internal/controls/shadow-view/shadow-view-impl.cpp index 5ce5e22..2011b7f 100644 --- a/dali-toolkit/internal/controls/shadow-view/shadow-view-impl.cpp +++ b/dali-toolkit/internal/controls/shadow-view/shadow-view-impl.cpp @@ -21,7 +21,6 @@ // EXTERNAL INCLUDES #include #include -#include #include #include #include @@ -106,19 +105,6 @@ const char* const RENDER_SHADOW_FRAGMENT_SOURCE = " gl_FragColor = vec4(uShadowColor.rgb, uShadowColor.a * alpha);\n" "}\n"; -// TODO: Add this to dali-core constraints.h -/** - * EqualToConstraintMatrix - * - * f(current, property) = property - */ -struct EqualToConstraintMatrix -{ - EqualToConstraintMatrix(){} - - Dali::Matrix operator()(const Dali::Matrix& current, const PropertyInput& property) {return property.GetMatrix();} -}; - } // namespace ShadowView::ShadowView( float downsampleWidthScale, float downsampleHeightScale ) @@ -168,6 +154,7 @@ void ShadowView::SetShadowPlane(Actor shadowPlane) mShadowPlaneBg = shadowPlane; mShadowPlane = ImageActor::New(); + mShadowPlane.SetName( "SHADOW_PLANE" ); mShadowPlane.SetParentOrigin(ParentOrigin::CENTER); mShadowPlane.SetAnchorPoint(AnchorPoint::CENTER); @@ -182,9 +169,9 @@ void ShadowView::SetShadowPlane(Actor shadowPlane) ConstrainCamera(); - mShadowPlane.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mShadowPlane.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); - mBlurRootActor.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mBlurRootActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); } void ShadowView::SetPointLight(Actor pointLight) @@ -240,7 +227,7 @@ void ShadowView::OnInitialize() // root actor to parent all user added actors. Used as source actor for shadow render task. mChildrenRoot.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); mChildrenRoot.SetRelayoutEnabled( true ); - mChildrenRoot.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mChildrenRoot.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); Vector2 stageSize = Stage::GetCurrent().GetSize(); mCameraActor = CameraActor::New(stageSize); @@ -275,8 +262,9 @@ void ShadowView::OnInitialize() mBlurFilter.SetPixelFormat(Pixel::RGBA8888); mBlurRootActor = Actor::New(); - + mBlurRootActor.SetName( "BLUR_ROOT_ACTOR" ); mBlurRootActor.SetRelayoutEnabled( true ); + // Turn off inheritance to ensure filter renders properly mBlurRootActor.SetPositionInheritanceMode(USE_PARENT_POSITION); mBlurRootActor.SetInheritOrientation(false); @@ -316,18 +304,15 @@ void ShadowView::ConstrainCamera() // Constrain camera to look directly at center of shadow plane. (mPointLight position // is under control of application, can't use transform inheritance) - Constraint cameraOrientationConstraint = - Constraint::New ( Actor::Property::ORIENTATION, - Source( mShadowPlane, Actor::Property::WORLD_POSITION ), - Source( mPointLight, Actor::Property::WORLD_POSITION ), - Source( mShadowPlane, Actor::Property::WORLD_ORIENTATION ), - &LookAt ); - - mCameraActor.ApplyConstraint( cameraOrientationConstraint ); - - Constraint pointLightPositionConstraint = Constraint::New( Actor::Property::POSITION, Source( mPointLight, Actor::Property::WORLD_POSITION ), EqualToConstraint() ); + Constraint cameraOrientationConstraint = Constraint::New ( mCameraActor, Actor::Property::ORIENTATION, &LookAt ); + cameraOrientationConstraint.AddSource( Source( mShadowPlane, Actor::Property::WORLD_POSITION ) ); + cameraOrientationConstraint.AddSource( Source( mPointLight, Actor::Property::WORLD_POSITION ) ); + cameraOrientationConstraint.AddSource( Source( mShadowPlane, Actor::Property::WORLD_ORIENTATION ) ); + cameraOrientationConstraint.Apply(); - mCameraActor.ApplyConstraint( pointLightPositionConstraint ); + Constraint pointLightPositionConstraint = Constraint::New( mCameraActor, Actor::Property::POSITION, EqualToConstraint() ); + pointLightPositionConstraint.AddSource( Source( mPointLight, Actor::Property::WORLD_POSITION ) ); + pointLightPositionConstraint.Apply(); } } @@ -373,23 +358,29 @@ void ShadowView::SetShaderConstants() Property::Index lightCameraProjectionMatrixPropertyIndex = mShadowRenderShader.GetPropertyIndex(SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME); Property::Index lightCameraViewMatrixPropertyIndex = mShadowRenderShader.GetPropertyIndex(SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME); - Constraint projectionMatrixConstraint = Constraint::New( lightCameraProjectionMatrixPropertyIndex, Source( mCameraActor, CameraActor::Property::PROJECTION_MATRIX ), EqualToConstraintMatrix()); - Constraint viewMatrixConstraint = Constraint::New( lightCameraViewMatrixPropertyIndex, Source( mCameraActor, CameraActor::Property::VIEW_MATRIX ), EqualToConstraintMatrix()); + Constraint projectionMatrixConstraint = Constraint::New( mShadowRenderShader, lightCameraProjectionMatrixPropertyIndex, EqualToConstraint() ); + projectionMatrixConstraint.AddSource( Source( mCameraActor, CameraActor::Property::PROJECTION_MATRIX ) ); - mShadowRenderShader.ApplyConstraint(projectionMatrixConstraint); - mShadowRenderShader.ApplyConstraint(viewMatrixConstraint); + Constraint viewMatrixConstraint = Constraint::New( mShadowRenderShader, lightCameraViewMatrixPropertyIndex, EqualToConstraint() ); + viewMatrixConstraint.AddSource( Source( mCameraActor, CameraActor::Property::VIEW_MATRIX ) ); + + projectionMatrixConstraint.Apply(); + viewMatrixConstraint.Apply(); // Register a property that the user can use to control the blur in the internal object mBlurStrengthPropertyIndex = self.RegisterProperty(BLUR_STRENGTH_PROPERTY_NAME, BLUR_STRENGTH_DEFAULT); - mBlurFilter.GetHandleForAnimateBlurStrength().ApplyConstraint( Constraint::New( mBlurFilter.GetBlurStrengthPropertyIndex() , - Source( self, mBlurStrengthPropertyIndex), - EqualToConstraint()) ); + + Constraint blurStrengthConstraint = Constraint::New( mBlurFilter.GetHandleForAnimateBlurStrength(), mBlurFilter.GetBlurStrengthPropertyIndex(), EqualToConstraint() ); + blurStrengthConstraint.AddSource( Source( self, mBlurStrengthPropertyIndex) ); + blurStrengthConstraint.Apply(); // Register a property that the user can use to control the color of the shadow. Property::Index index = mShadowRenderShader.GetPropertyIndex(SHADER_SHADOW_COLOR_PROPERTY_NAME); mShadowColorPropertyIndex = self.RegisterProperty(SHADOW_COLOR_PROPERTY_NAME, mCachedShadowColor); - mShadowRenderShader.ApplyConstraint(Constraint::New( index, Source( self, mShadowColorPropertyIndex ), EqualToConstraint()) ); + Constraint shadowRenderShaderConstraint = Constraint::New( mShadowRenderShader, index, EqualToConstraint() ); + shadowRenderShaderConstraint.AddSource( Source( self, mShadowColorPropertyIndex ) ); + shadowRenderShaderConstraint.Apply(); } } // namespace Internal diff --git a/dali-toolkit/internal/controls/slider/slider-impl.cpp b/dali-toolkit/internal/controls/slider/slider-impl.cpp index 0cd8783..4c1b2fa 100755 --- a/dali-toolkit/internal/controls/slider/slider-impl.cpp +++ b/dali-toolkit/internal/controls/slider/slider-impl.cpp @@ -19,7 +19,9 @@ #include // EXTERNAL INCLUDES +#include // for strcmp #include +#include #include #include #include @@ -348,13 +350,13 @@ void Slider::DisplayValue( float value, bool raiseSignals ) } } - if( mHandleValueTextView ) + if( mHandleValueTextLabel ) { std::stringstream ss; ss.precision( GetValuePrecision() ); ss << std::fixed << clampledValue; - mHandleValueTextView.SetText( ss.str() ); + mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, ss.str() ); } } @@ -523,13 +525,15 @@ ImageActor Slider::CreatePopupArrow() return arrow; } -Toolkit::TextView Slider::CreatePopupText() +Toolkit::TextLabel Slider::CreatePopupText() { - Toolkit::TextView textView = Toolkit::TextView::New(); - textView.SetParentOrigin( ParentOrigin::CENTER ); - textView.SetAnchorPoint( AnchorPoint::CENTER ); - textView.SetZ( VALUE_DISPLAY_TEXT_Z ); - return textView; + Toolkit::TextLabel textLabel = Toolkit::TextLabel::New(); + textLabel.SetParentOrigin( ParentOrigin::CENTER ); + textLabel.SetAnchorPoint( AnchorPoint::CENTER ); + textLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + textLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + textLabel.SetZ( VALUE_DISPLAY_TEXT_Z ); + return textLabel; } ImageActor Slider::CreatePopup() @@ -539,8 +543,8 @@ ImageActor Slider::CreatePopup() popup.SetParentOrigin( ParentOrigin::TOP_CENTER ); popup.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); - mValueTextView = CreatePopupText(); - popup.Add( mValueTextView ); + mValueTextLabel = CreatePopupText(); + popup.Add( mValueTextLabel ); return popup; } @@ -574,24 +578,21 @@ void Slider::ResizeHandleRegion( const Vector2& region ) void Slider::CreateHandleValueDisplay() { - if( mHandle && !mHandleValueTextView ) + if( mHandle && !mHandleValueTextLabel ) { - mHandleValueTextView = Toolkit::TextView::New(); - mHandleValueTextView.SetParentOrigin( ParentOrigin::CENTER ); - mHandleValueTextView.SetAnchorPoint( AnchorPoint::CENTER ); - mHandleValueTextView.SetSize( GetHandleRegion() ); - mHandleValueTextView.SetZ( HANDLE_VALUE_DISPLAY_TEXT_Z ); - mHandle.Add( mHandleValueTextView ); + mHandleValueTextLabel = Toolkit::TextLabel::New(); + mHandleValueTextLabel.SetParentOrigin( ParentOrigin::CENTER ); + mHandleValueTextLabel.SetAnchorPoint( AnchorPoint::CENTER ); + mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + mHandleValueTextLabel.SetProperty( Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + mHandleValueTextLabel.SetDrawMode( DrawMode::OVERLAY ); + mHandle.Add( mHandleValueTextLabel ); } } void Slider::DestroyHandleValueDisplay() { - if(mHandleValueTextView) - { - mHandleValueTextView.Unparent(); - mHandleValueTextView.Reset(); - } + UnparentAndReset(mHandleValueTextLabel); } void Slider::SetPopupTextColor( const Vector4& color ) @@ -1018,26 +1019,15 @@ bool Slider::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tr void Slider::DisplayPopup( float value ) { // Value displayDoConnectSignal - if( mValueTextView ) + if( mValueTextLabel ) { std::stringstream ss; ss.precision( GetValuePrecision() ); ss << std::fixed << value; - mValueTextView.SetText( ss.str() ); - TextStyle style; - style.SetTextColor( GetPopupTextColor() ); - mValueTextView.SetStyleToCurrentText( style, TextStyle::COLOR); + mValueTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, ss.str() ); if( mValueDisplay ) { - Font font = Font::New(); - float popupWidth = font.MeasureText( ss.str() ).x + VALUE_POPUP_MARGIN * 2.0f; - if( popupWidth < VALUE_POPUP_MIN_WIDTH ) - { - popupWidth = VALUE_POPUP_MIN_WIDTH; - } - - mPopup.SetSize( popupWidth, VALUE_POPUP_HEIGHT ); mValueDisplay.SetVisible( true ); mValueTimer.SetInterval( VALUE_VIEW_SHOW_DURATION ); diff --git a/dali-toolkit/internal/controls/slider/slider-impl.h b/dali-toolkit/internal/controls/slider/slider-impl.h index 8fee62e..a8003c7 100755 --- a/dali-toolkit/internal/controls/slider/slider-impl.h +++ b/dali-toolkit/internal/controls/slider/slider-impl.h @@ -25,7 +25,7 @@ // INTERNAL INCLUDES #include #include -#include +#include namespace Dali { @@ -434,7 +434,7 @@ private: * * @return The textview created for the popup */ - Toolkit::TextView CreatePopupText(); + Toolkit::TextLabel CreatePopupText(); /** * Create the value display for the slider @@ -687,8 +687,8 @@ private: ImageActor mPopup; ///< Popup backing ImageActor mPopupArrow; ///< Popup arrow backing - Toolkit::TextView mValueTextView; //< The text value in popup - Toolkit::TextView mHandleValueTextView; ///< The text value on handle + Toolkit::TextLabel mValueTextLabel; //< The text value in popup + Toolkit::TextLabel mHandleValueTextLabel; ///< The text value on handle Vector2 mHandleLastTouchPoint; ///< The last touch point for the handle Timer mValueTimer; ///< Timer used to hide value view diff --git a/dali-toolkit/internal/controls/super-blur-view/super-blur-view-impl.cpp b/dali-toolkit/internal/controls/super-blur-view/super-blur-view-impl.cpp index 5544761..f2b8a5f 100644 --- a/dali-toolkit/internal/controls/super-blur-view/super-blur-view-impl.cpp +++ b/dali-toolkit/internal/controls/super-blur-view/super-blur-view-impl.cpp @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include #include #include #include @@ -54,20 +53,20 @@ struct ActorOpacityConstraint mRange = Vector2( index*rangeLength, (index+1.f)*rangeLength ); } - float operator()( float current, const PropertyInput& blurProperty ) + void operator()( float& current, const PropertyInputContainer& inputs ) { - float blurStrength = blurProperty.GetFloat(); + float blurStrength = inputs[0]->GetFloat(); if(blurStrength <= mRange.x) { - return 1.f; + current = 1.f; } else if(blurStrength > mRange.y) { - return 0.f; + current = 0.f; } else { - return (mRange.y - blurStrength)/(mRange.y-mRange.x); + current = ( mRange.y - blurStrength) / ( mRange.y - mRange.x ); } } @@ -144,6 +143,7 @@ void SuperBlurView::OnInitialize() for(unsigned int i=0; i<=mBlurLevels;i++) { mImageActors[i] = ImageActor::New( ); + mImageActors[i].SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mImageActors[i].SetParentOrigin( ParentOrigin::CENTER ); mImageActors[i].SetZ(-static_cast(i)*0.01f); mImageActors[i].SetColorMode( USE_OWN_MULTIPLY_PARENT_ALPHA ); @@ -152,7 +152,9 @@ void SuperBlurView::OnInitialize() for(unsigned int i=0; i < mBlurLevels; i++) { - mImageActors[i].ApplyConstraint( Constraint::New( Actor::Property::COLOR_ALPHA, ParentSource( mBlurStrengthPropertyIndex ), ActorOpacityConstraint(mBlurLevels, i) ) ); + Constraint constraint = Constraint::New( mImageActors[i], Actor::Property::COLOR_ALPHA, ActorOpacityConstraint(mBlurLevels, i) ); + constraint.AddSource( ParentSource( mBlurStrengthPropertyIndex ) ); + constraint.Apply(); } Self().SetSize(Stage::GetCurrent().GetSize()); @@ -250,16 +252,6 @@ void SuperBlurView::ClearBlurResource() } } -void SuperBlurView::OnRelayout( const Vector2& size, RelayoutContainer& container ) -{ - unsigned int numChildren = Self().GetChildCount(); - - for( unsigned int i=0; i 0.0f; + return actor.GetResizePolicy( dimension ) != ResizePolicy::FILL_TO_PARENT && actor.GetRelayoutSize( dimension ) > 0.0f; } #if defined(DEBUG_ENABLED) @@ -60,11 +60,13 @@ void PrintArray( Array2d& array ) { Dali::Toolkit::Internal::TableView::CellData data = array[i][j]; char actor = ' '; + std::string actorName; if( data.actor ) { actor = 'A'; + actorName = data.actor.GetName(); } - TV_LOG("Array[%d,%d]=%c %d,%d,%d,%d ", i, j, actor, + TV_LOG("Array[%d,%d]=%c %s %d,%d,%d,%d ", i, j, actor, actorName.c_str(), data.position.rowIndex, data.position.columnIndex, data.position.rowSpan, data.position.columnSpan ); } @@ -192,50 +194,33 @@ bool TableView::AddChild( Actor& child, const Toolkit::TableView::CellPosition& // adopt the child Self().Add( child ); - // put the actor to the main cell - CellData& data = mCellData[ position.rowIndex ][ position.columnIndex ]; - data.actor = child; - data.position = position; - // if child spans multiple rows of columns - bool spanned = false; - if( position.rowSpan > 1 ) + if( ( position.rowSpan > 1 ) && ( position.rowIndex + position.rowSpan > mCellData.GetRows() ) ) { - // span might go outside table - if( position.rowIndex + position.rowSpan > mCellData.GetRows() ) - { - // increase table size for the full span, only increasing rows - ResizeContainers( position.rowIndex + position.rowSpan, mCellData.GetColumns() ); - } - - spanned = true; + // increase table size for the full span, only increasing rows + ResizeContainers( position.rowIndex + position.rowSpan, mCellData.GetColumns() ); } - if( position.columnSpan > 1 ) + if( ( position.columnSpan > 1 ) && ( position.columnIndex + position.columnSpan > mCellData.GetColumns() ) ) { - // span might go outside table - if( position.columnIndex + position.columnSpan > mCellData.GetColumns() ) - { - // increase table size for the full span, only increasing columns - ResizeContainers( mCellData.GetRows(), position.columnIndex + position.columnSpan ); - } - - spanned = true; + // increase table size for the full span, only increasing columns + ResizeContainers( mCellData.GetRows(), position.columnIndex + position.columnSpan ); } - // if it spanned multiple rows, put the cellinfo in all of those - if( spanned ) + // Fill in all cells that need the data + CellData data; + data.actor = child; + data.position = position; + + for( unsigned int row = position.rowIndex; row < ( position.rowIndex + position.rowSpan ); ++row ) { - for( unsigned int row = position.rowIndex; row < ( position.rowIndex + position.rowSpan ); ++row ) + // store same information to all cells, this way we can identify + // if a cell is the prime location of an actor or a spanned one + for( unsigned int column = position.columnIndex; column < ( position.columnIndex + position.columnSpan ); ++column ) { // store same information to all cells, this way we can identify // if a cell is the prime location of an actor or a spanned one - for( unsigned int column = position.columnIndex; column < ( position.columnIndex + position.columnSpan ); ++column ) - { - // store same information to all cells, this way we can identify - // if a cell is the prime location of an actor or a spanned one - mCellData[ row ][ column ] = data; - } + mCellData[ row ][ column ] = data; } } @@ -686,29 +671,29 @@ void TableView::CalculateRowColumnData() } } -void TableView::OnCalculateRelayoutSize( Dimension dimension ) +void TableView::OnCalculateRelayoutSize( Dimension::Type dimension ) { CalculateRowColumnData(); - if( dimension & WIDTH ) + if( dimension & Dimension::WIDTH ) { - CalculateFixedSizes( mColumnData, WIDTH ); + CalculateFixedSizes( mColumnData, Dimension::WIDTH ); mFixedTotals.width = CalculateTotalFixedSize( mColumnData ); } - if( dimension & HEIGHT ) + if( dimension & Dimension::HEIGHT ) { - CalculateFixedSizes( mRowData, HEIGHT ); + CalculateFixedSizes( mRowData, Dimension::HEIGHT ); mFixedTotals.height = CalculateTotalFixedSize( mRowData ); } } -void TableView::OnLayoutNegotiated( float size, Dimension dimension ) +void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension ) { CalculateRowColumnData(); // Calculate the value of all relative sized rows and columns - if( dimension & WIDTH ) + if( dimension & Dimension::WIDTH ) { float remainingSize = size - mFixedTotals.width; if( remainingSize < 0.0f ) @@ -719,7 +704,7 @@ void TableView::OnLayoutNegotiated( float size, Dimension dimension ) CalculateRelativeSizes( mColumnData, remainingSize ); } - if( dimension & HEIGHT ) + if( dimension & Dimension::HEIGHT ) { float remainingSize = size - mFixedTotals.height; if( remainingSize < 0.0f ) @@ -1249,7 +1234,7 @@ Vector3 TableView::GetNaturalSize() return Vector3( mFixedTotals.width, mFixedTotals.height, 1.0f ); } -float TableView::CalculateChildSize( const Actor& child, Dimension dimension ) +float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimension ) { CalculateRowColumnData(); @@ -1273,13 +1258,14 @@ float TableView::CalculateChildSize( const Actor& child, Dimension dimension ) { switch( dimension ) { - case WIDTH: + case Dimension::WIDTH: { float cellSize = 0.0f; // Accumulate the width for( unsigned int i = 0; i < position.columnSpan; ++i ) { + DALI_ASSERT_DEBUG( column + i < mColumnData.Size() ); cellSize += mColumnData[ column + i ].size; } @@ -1293,13 +1279,14 @@ float TableView::CalculateChildSize( const Actor& child, Dimension dimension ) return cellSize; } - case HEIGHT: + case Dimension::HEIGHT: { float cellSize = 0.0f; // Accumulate the height for( unsigned int i = 0; i < position.rowSpan; ++i ) { + DALI_ASSERT_DEBUG( row + i < mRowData.Size() ); cellSize += mRowData[ row + i ].size; } @@ -1326,7 +1313,7 @@ float TableView::CalculateChildSize( const Actor& child, Dimension dimension ) return 0.0f; // Child not found } -bool TableView::RelayoutDependentOnChildren( Dimension dimension ) +bool TableView::RelayoutDependentOnChildren( Dimension::Type dimension ) { if ( Control::RelayoutDependentOnChildren( dimension ) ) { @@ -1429,8 +1416,31 @@ float TableView::CalculateTotalFixedSize( const RowColumnArray& data ) return totalSize; } -void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension dimension ) +Vector2 TableView::GetCellPadding( Dimension::Type dimension ) { + switch( dimension ) + { + case Dimension::WIDTH: + { + return Vector2( mPadding.x, mPadding.x ); + } + case Dimension::HEIGHT: + { + return Vector2( mPadding.y, mPadding.y ); + } + default: + { + break; + } + } + + return Vector2(); +} + +void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimension ) +{ + Vector2 cellPadding = GetCellPadding( dimension ); + const unsigned int dataCount = data.Size(); for( unsigned int i = 0; i < dataCount; ++i ) @@ -1442,12 +1452,12 @@ void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension dimension ) // Find the size of the biggest actor in the row or column float maxActorHeight = 0.0f; - unsigned int fitCount = ( dimension == WIDTH ) ? mCellData.GetRows() : mCellData.GetColumns(); + unsigned int fitCount = ( dimension == Dimension::WIDTH ) ? mCellData.GetRows() : mCellData.GetColumns(); for( unsigned int j = 0; j < fitCount; ++j ) { - unsigned int row = ( dimension == WIDTH ) ? j : i; - unsigned int column = ( dimension == WIDTH ) ? i : j; + unsigned int row = ( dimension == Dimension::WIDTH ) ? j : i; + unsigned int column = ( dimension == Dimension::WIDTH ) ? i : j; DALI_ASSERT_DEBUG( row < mCellData.GetRows() ); DALI_ASSERT_DEBUG( column < mCellData.GetColumns() ); @@ -1456,7 +1466,7 @@ void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension dimension ) { if( FitToChild( actor, dimension ) ) { - maxActorHeight = std::max( maxActorHeight, actor.GetRelayoutSize( dimension ) ); + maxActorHeight = std::max( maxActorHeight, actor.GetRelayoutSize( dimension ) + cellPadding.x + cellPadding.y ); } } } diff --git a/dali-toolkit/internal/controls/table-view/table-view-impl.h b/dali-toolkit/internal/controls/table-view/table-view-impl.h index 55a7d7b..be41e47 100644 --- a/dali-toolkit/internal/controls/table-view/table-view-impl.h +++ b/dali-toolkit/internal/controls/table-view/table-view-impl.h @@ -251,7 +251,7 @@ private: // From Control /** * @copydoc Control::CalculateChildSize */ - virtual float CalculateChildSize( const Actor& child, Dimension dimension ); + virtual float CalculateChildSize( const Actor& child, Dimension::Type dimension ); /** * @copydoc Control::OnInitialize() @@ -271,17 +271,17 @@ private: // From Control /** * @copydoc Control::RelayoutDependentOnChildren() */ - virtual bool RelayoutDependentOnChildren( Dimension dimension = ALL_DIMENSIONS ); + virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); /** * @copydoc Control::OnCalculateRelayoutSize */ - virtual void OnCalculateRelayoutSize( Dimension dimension ); + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ); /** * @copydoc Control::OnLayoutNegotiated */ - virtual void OnLayoutNegotiated( float size, Dimension dimension ); + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ); private: // Implementation @@ -404,9 +404,9 @@ private: * @brief Calculate the fixed sizes for a row or column * * @param[in] data The row or column data to process - * @param[in] dimension The dimension being calculated: row == HEIGHT, column == WIDTH + * @param[in] dimension The dimension being calculated: row == Dimension::HEIGHT, column == Dimension::WIDTH */ - void CalculateFixedSizes( RowColumnArray& data, Dimension dimension ); + void CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimension ); /** * @brief Calculate the value of the relative sizes @@ -430,6 +430,14 @@ private: void CalculateRowColumnData(); /** + * @brief Return the cell padding for a given dimension + * + * @param[in] dimension The dimension to return the padding for + * @return Return the padding (x = low, y = high) + */ + Vector2 GetCellPadding( Dimension::Type dimension ); + + /** * A reference counted object may only be deleted by calling Unreference() */ virtual ~TableView(); diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp new file mode 100644 index 0000000..f17ea34 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -0,0 +1,646 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +using namespace Dali::Toolkit::Text; + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND; +} + +namespace +{ + +const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] = +{ + { "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN }, + { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER }, + { "END", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END }, +}; +const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); + +const Scripting::StringEnum< Toolkit::Text::LayoutEngine::VerticalAlignment > VERTICAL_ALIGNMENT_STRING_TABLE[] = +{ + { "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP }, + { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER }, + { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM }, +}; +const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); + +// Type registration +BaseHandle Create() +{ + return Toolkit::TextField::New(); +} + +// Setup properties, signals and actions using the type-registry. +DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextField, Toolkit::Control, Create ); + +DALI_PROPERTY_REGISTRATION( TextField, "rendering-backend", INTEGER, RENDERING_BACKEND ) +DALI_PROPERTY_REGISTRATION( TextField, "placeholder-text", STRING, PLACEHOLDER_TEXT ) +DALI_PROPERTY_REGISTRATION( TextField, "text", STRING, TEXT ) +DALI_PROPERTY_REGISTRATION( TextField, "font-family", STRING, FONT_FAMILY ) +DALI_PROPERTY_REGISTRATION( TextField, "font-style", STRING, FONT_STYLE ) +DALI_PROPERTY_REGISTRATION( TextField, "point-size", FLOAT, POINT_SIZE ) +DALI_PROPERTY_REGISTRATION( TextField, "exceed-policy", INTEGER, EXCEED_POLICY ) +DALI_PROPERTY_REGISTRATION( TextField, "primary-cursor-color", VECTOR4, PRIMARY_CURSOR_COLOR ) +DALI_PROPERTY_REGISTRATION( TextField, "secondary-cursor-color", VECTOR4, SECONDARY_CURSOR_COLOR ) +DALI_PROPERTY_REGISTRATION( TextField, "enable-cursor-blink", BOOLEAN, ENABLE_CURSOR_BLINK ) +DALI_PROPERTY_REGISTRATION( TextField, "cursor-blink-interval", FLOAT, CURSOR_BLINK_INTERVAL ) +DALI_PROPERTY_REGISTRATION( TextField, "cursor-blink-duration", FLOAT, CURSOR_BLINK_DURATION ) +DALI_PROPERTY_REGISTRATION( TextField, "grab-handle-image", STRING, GRAB_HANDLE_IMAGE ) +DALI_PROPERTY_REGISTRATION( TextField, "decoration-bounding-box", RECTANGLE, DECORATION_BOUNDING_BOX ) +DALI_PROPERTY_REGISTRATION( TextField, "horizontal-alignment", STRING, HORIZONTAL_ALIGNMENT ) +DALI_PROPERTY_REGISTRATION( TextField, "vertical-alignment", STRING, VERTICAL_ALIGNMENT ) +DALI_TYPE_REGISTRATION_END() + +} // namespace + +Toolkit::TextField TextField::New() +{ + // Create the implementation, temporarily owned by this handle on stack + IntrusivePtr< TextField > impl = new TextField(); + + // Pass ownership to CustomActor handle + Toolkit::TextField handle( *impl ); + + // Second-phase init of the implementation + // This can only be done after the CustomActor connection has been made... + impl->Initialize(); + + return handle; +} + +void TextField::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +{ + Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) ); + + if( textField ) + { + TextField& impl( GetImpl( textField ) ); + + switch( index ) + { + case Toolkit::TextField::Property::RENDERING_BACKEND: + { + int backend = value.Get< int >(); + + if( impl.mRenderingBackend != backend ) + { + impl.mRenderingBackend = backend; + impl.mRenderer.Reset(); + } + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT: + { + if( impl.mController ) + { + //impl.mController->SetPlaceholderText( value.Get< std::string >() ); TODO + } + break; + } + case Toolkit::TextField::Property::TEXT: + { + if( impl.mController ) + { + impl.mController->SetText( value.Get< std::string >() ); + } + break; + } + case Toolkit::TextField::Property::FONT_FAMILY: + { + if( impl.mController ) + { + std::string fontFamily = value.Get< std::string >(); + + if( impl.mController->GetDefaultFontFamily() != fontFamily ) + { + impl.mController->SetDefaultFontFamily( fontFamily ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextField::Property::FONT_STYLE: + { + if( impl.mController ) + { + std::string fontStyle = value.Get< std::string >(); + + if( impl.mController->GetDefaultFontStyle() != fontStyle ) + { + impl.mController->SetDefaultFontStyle( fontStyle ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextField::Property::POINT_SIZE: + { + if( impl.mController ) + { + float pointSize = value.Get< float >(); + + if( impl.mController->GetDefaultPointSize() != pointSize /*TODO - epsilon*/ ) + { + impl.mController->SetDefaultPointSize( pointSize ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextField::Property::EXCEED_POLICY: + { + impl.mExceedPolicy = value.Get< int >(); + break; + } + case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetColor( PRIMARY_CURSOR, value.Get< Vector4 >() ); + } + break; + } + case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetColor( SECONDARY_CURSOR, value.Get< Vector4 >() ); + } + break; + } + case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK: + { + if( impl.mController ) + { + impl.mController->SetEnableCursorBlink( value.Get< bool >() ); + } + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetCursorBlinkInterval( value.Get< float >() ); + } + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_DURATION: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetCursorBlinkDuration( value.Get< float >() ); + } + break; + } + case Toolkit::TextField::Property::GRAB_HANDLE_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + + if( impl.mDecorator ) + { + impl.mDecorator->SetGrabHandleImage( image ); + } + break; + } + case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX: + { + if( impl.mDecorator ) + { + impl.mDecorator->SetBoundingBox( value.Get< Rect >() ); + } + break; + } + case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT: + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); + + if( engine.GetHorizontalAlignment() != alignment ) + { + engine.SetHorizontalAlignment( alignment ); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextField::Property::VERTICAL_ALIGNMENT: + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + const LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); + + if( engine.GetVerticalAlignment() != alignment ) + { + engine.SetVerticalAlignment( alignment ); + impl.RequestTextRelayout(); + } + break; + } + } // switch + } // textfield +} + +Property::Value TextField::GetProperty( BaseObject* object, Property::Index index ) +{ + Property::Value value; + + Toolkit::TextField textField = Toolkit::TextField::DownCast( Dali::BaseHandle( object ) ); + + if( textField ) + { + TextField& impl( GetImpl( textField ) ); + + switch( index ) + { + case Toolkit::TextField::Property::RENDERING_BACKEND: + { + value = impl.mRenderingBackend; + break; + } + case Toolkit::TextField::Property::PLACEHOLDER_TEXT: + { + if( impl.mController ) + { + std::string text; + impl.mController->GetPlaceholderText( text ); + value = text; + } + break; + } + case Toolkit::TextField::Property::TEXT: + { + if( impl.mController ) + { + std::string text; + impl.mController->GetText( text ); + value = text; + } + break; + } + case Toolkit::TextField::Property::EXCEED_POLICY: + { + value = impl.mExceedPolicy; + break; + } + case Toolkit::TextField::Property::PRIMARY_CURSOR_COLOR: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetColor( PRIMARY_CURSOR ); + } + break; + } + case Toolkit::TextField::Property::SECONDARY_CURSOR_COLOR: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetColor( SECONDARY_CURSOR ); + } + break; + } + case Toolkit::TextField::Property::ENABLE_CURSOR_BLINK: + { + value = impl.mController->GetEnableCursorBlink(); + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_INTERVAL: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetCursorBlinkInterval(); + } + break; + } + case Toolkit::TextField::Property::CURSOR_BLINK_DURATION: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetCursorBlinkDuration(); + } + break; + } + case Toolkit::TextField::Property::DECORATION_BOUNDING_BOX: + { + if( impl.mDecorator ) + { + value = impl.mDecorator->GetBoundingBox(); + } + break; + } + case Toolkit::TextField::Property::HORIZONTAL_ALIGNMENT: + { + if( impl.mController ) + { + value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) ); + } + break; + } + case Toolkit::TextField::Property::VERTICAL_ALIGNMENT: + { + if( impl.mController ) + { + value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) ); + } + break; + } + } //switch + } + + return value; +} + +void TextField::OnInitialize() +{ + Actor self = Self(); + + mController = Text::Controller::New( *this ); + + mDecorator = Text::Decorator::New( *this, *mController ); + + mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX ); + + mController->EnableTextInput( mDecorator ); + + // Forward input events to controller + EnableGestureDetection(Gesture::Tap); + GetTapGestureDetector().SetMaximumTapsRequired( 2 ); + EnableGestureDetection(Gesture::Pan); + + // Set BoundingBox to stage size if not already set. + if ( mDecorator->GetBoundingBox().IsEmpty() ) + { + Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); + mDecorator->SetBoundingBox( Rect( 0.0f, 0.0f, stageSize.width, stageSize.height ) ); + } + + // Fill-parent area by default + self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); + self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT ); +} + +void TextField::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) +{ + GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); +} + +Vector3 TextField::GetNaturalSize() +{ + return mController->GetNaturalSize(); +} + +float TextField::GetHeightForWidth( float width ) +{ + return mController->GetHeightForWidth( width ); +} + +void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container ) +{ + if( mController->Relayout( size ) || + !mRenderer ) + { + const Vector2& scrollPosition = mController->GetScrollPosition(); + const Vector2& alignmentOffset = mController->GetAlignmentOffset(); + + Vector2 offset = scrollPosition + alignmentOffset; + + if( mDecorator ) + { + mDecorator->Relayout( size, offset ); + } + + if( !mRenderer ) + { + mRenderer = Backend::Get().NewRenderer( mRenderingBackend ); + } + + RenderableActor renderableActor; + if( mRenderer ) + { + renderableActor = mRenderer->Render( mController->GetView() ); + } + + EnableClipping( (Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy), size ); + + if( renderableActor != mRenderableActor ) + { + UnparentAndReset( mRenderableActor ); + mRenderableActor = renderableActor; + } + + if( mRenderableActor ) + { + mRenderableActor.SetPosition( offset.x, offset.y ); + + // Make sure the actor is parented correctly with/without clipping + if( mClipper ) + { + mClipper->GetRootActor().Add( mRenderableActor ); + } + else + { + Self().Add( mRenderableActor ); + } + } + } +} + +void TextField::OnKeyInputFocusGained() +{ + VirtualKeyboard::StatusChangedSignal().Connect( this, &TextField::KeyboardStatusChanged ); + + ImfManager imfManager = ImfManager::Get(); + + if ( imfManager ) + { + imfManager.EventReceivedSignal().Connect( this, &TextField::OnImfEvent ); + + // Notify that the text editing start. + imfManager.Activate(); + + // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated. + imfManager.SetRestoreAfterFocusLost( true ); + } + + mController->KeyboardFocusGainEvent(); +} + +void TextField::OnKeyInputFocusLost() +{ + VirtualKeyboard::StatusChangedSignal().Disconnect( this, &TextField::KeyboardStatusChanged ); + + ImfManager imfManager = ImfManager::Get(); + if ( imfManager ) + { + // The text editing is finished. Therefore the imf manager don't have restore activation. + imfManager.SetRestoreAfterFocusLost( false ); + + // Notify that the text editing finish. + imfManager.Deactivate(); + + imfManager.EventReceivedSignal().Disconnect( this, &TextField::OnImfEvent ); + } + + mController->KeyboardFocusLostEvent(); +} + +void TextField::OnTap( const TapGesture& gesture ) +{ + // Show the keyboard if it was hidden. + if (!VirtualKeyboard::IsVisible()) + { + VirtualKeyboard::Show(); + } + + SetKeyInputFocus(); + + mController->TapEvent( gesture.numberOfTaps, gesture.localPoint.x, gesture.localPoint.y ); +} + +void TextField::OnPan( const PanGesture& gesture ) +{ + mController->PanEvent( gesture.state, gesture.displacement ); +} + +bool TextField::OnKeyEvent( const KeyEvent& event ) +{ + if( Dali::DALI_KEY_ESCAPE == event.keyCode ) + { + ClearKeyInputFocus(); + } + + return mController->KeyEvent( event ); +} + +ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent ) +{ + switch ( imfEvent.eventName ) + { + case ImfManager::COMMIT: + { + KeyEvent event( "", imfEvent.predictiveString, 0, 0, 0, KeyEvent::Down ); + mController->KeyEvent( event ); + break; + } + case ImfManager::PREEDIT: // fall through + case ImfManager::DELETESURROUNDING: + case ImfManager::GETSURROUNDING: + case ImfManager::VOID: + { + // do nothing + } + } // end switch + + return ImfManager::ImfCallbackData(); +} + +void TextField::RequestTextRelayout() +{ + RelayoutRequest(); +} + +void TextField::EnableClipping( bool clipping, const Vector2& size ) +{ + if( clipping ) + { + // Not worth to created clip actor if width or height is equal to zero. + if( size.width > Math::MACHINE_EPSILON_1000 && size.height > Math::MACHINE_EPSILON_1000 ) + { + if( !mClipper ) + { + Actor self = Self(); + + mClipper = Clipper::New( size ); + self.Add( mClipper->GetRootActor() ); + self.Add( mClipper->GetImageActor() ); + } + else if ( mClipper ) + { + mClipper->Refresh( size ); + } + } + } + else + { + // Note - this will automatically remove the root & image actors + mClipper.Reset(); + } +} + +void TextField::KeyboardStatusChanged(bool keyboardShown) +{ + // Just hide the grab handle when keyboard is hidden. + if (!keyboardShown ) + { + mController->KeyboardFocusLostEvent(); + } +} + +TextField::TextField() +: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ), + mRenderingBackend( DEFAULT_RENDERING_BACKEND ), + mExceedPolicy( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP ) +{ +} + +TextField::~TextField() +{ + mClipper.Reset(); +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h new file mode 100644 index 0000000..5428275 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -0,0 +1,212 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_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 + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * @brief A control which renders a short text string. + */ +class TextField : public Control, public Text::ControlInterface +{ +public: + + /** + * @copydoc Dali::Toollkit::TextField::New() + */ + static Toolkit::TextField New(); + + // Properties + + /** + * @brief Called when a property of an object of this type is set. + * + * @param[in] object The object whose property is set. + * @param[in] index The property index. + * @param[in] value The new property value. + */ + static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); + + /** + * @brief Called to retrieve a property of an object of this type. + * + * @param[in] object The object whose property is to be retrieved. + * @param[in] index The property index. + * @return The current value of the property. + */ + static Property::Value GetProperty( BaseObject* object, Property::Index index ); + +private: // From Control + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnInitialize(); + + /** + * @copydoc Control::OnStyleChange() + */ + virtual void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); + + /** + * @copydoc Control::GetNaturalSize() + */ + virtual Vector3 GetNaturalSize(); + + /** + * @copydoc Control::GetHeightForWidth() + */ + virtual float GetHeightForWidth( float width ); + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); + + /** + * @copydoc Control::OnKeyInputFocusGained() + */ + virtual void OnKeyInputFocusGained(); + + /** + * @copydoc Control::OnKeyInputFocusLost() + */ + virtual void OnKeyInputFocusLost(); + + /** + * @copydoc Control::OnTap() + */ + virtual void OnTap( const TapGesture& tap ); + + /** + * @copydoc Control::OnPan() + */ + virtual void OnPan( const PanGesture& gesture ); + + /** + * @copydoc Dali::CustomActorImpl::OnKeyEvent(const KeyEvent&) + */ + virtual bool OnKeyEvent(const KeyEvent& event); + + /** + * @brief Event received from IMF manager + * + * @param[in] imfManager The IMF manager. + * @param[in] imfEvent The event received. + * @return A data struture indicating if update is needed, cursor position and current text. + */ + ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent ); + + /** + * @copydoc Text::ControlInterface::RequestTextRelayout() + */ + virtual void RequestTextRelayout(); + +private: // Implementation + + /** + * @brief Enable or disable clipping. + * + * @param[in] clipping True if clipping should be enabled. + * @param[in] size The area to clip within. + */ + void EnableClipping( bool clipping, const Vector2& size ); + + /** + * @brief Callback when keyboard is shown/hidden. + * + * @param[in] keyboardShown True if keyboard is shown. + */ + void KeyboardStatusChanged( bool keyboardShown ); + + /** + * Construct a new TextField. + */ + TextField(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~TextField(); + +private: + + // Undefined copy constructor and assignment operators + TextField(const TextField&); + TextField& operator=(const TextField& rhs); + +private: // Data + + Text::ControllerPtr mController; + Text::RendererPtr mRenderer; + Text::DecoratorPtr mDecorator; + Text::ClipperPtr mClipper; ///< For EXCEED_POLICY_CLIP + + RenderableActor mRenderableActor; + + int mRenderingBackend; + int mExceedPolicy; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Toolkit::Internal::TextField& GetImpl( Toolkit::TextField& textField ) +{ + DALI_ASSERT_ALWAYS(textField); + + Dali::RefObject& handle = textField.GetImplementation(); + + return static_cast(handle); +} + +inline const Toolkit::Internal::TextField& GetImpl( const Toolkit::TextField& textField ) +{ + DALI_ASSERT_ALWAYS(textField); + + const Dali::RefObject& handle = textField.GetImplementation(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__ diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp new file mode 100644 index 0000000..afe74e2 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -0,0 +1,497 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +using Dali::Toolkit::Text::LayoutEngine; +using Dali::Toolkit::Text::Backend; + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND; +} + +namespace +{ + +const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] = +{ + { "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN }, + { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER }, + { "END", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END }, +}; +const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); + +const Scripting::StringEnum< Toolkit::Text::LayoutEngine::VerticalAlignment > VERTICAL_ALIGNMENT_STRING_TABLE[] = +{ + { "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP }, + { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER }, + { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM }, +}; +const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); + +// Type registration +BaseHandle Create() +{ + return Toolkit::TextLabel::New(); +} + +// Setup properties, signals and actions using the type-registry. +DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextLabel, Toolkit::Control, Create ); + +DALI_PROPERTY_REGISTRATION( TextLabel, "rendering-backend", INTEGER, RENDERING_BACKEND ) +DALI_PROPERTY_REGISTRATION( TextLabel, "text", STRING, TEXT ) +DALI_PROPERTY_REGISTRATION( TextLabel, "font-family", STRING, FONT_FAMILY ) +DALI_PROPERTY_REGISTRATION( TextLabel, "font-style", STRING, FONT_STYLE ) +DALI_PROPERTY_REGISTRATION( TextLabel, "point-size", FLOAT, POINT_SIZE ) +DALI_PROPERTY_REGISTRATION( TextLabel, "multi-line", BOOLEAN, MULTI_LINE ) +DALI_PROPERTY_REGISTRATION( TextLabel, "horizontal-alignment", STRING, HORIZONTAL_ALIGNMENT ) +DALI_PROPERTY_REGISTRATION( TextLabel, "vertical-alignment", STRING, VERTICAL_ALIGNMENT ) +DALI_PROPERTY_REGISTRATION( TextLabel, "text-color", VECTOR4, TEXT_COLOR ) +DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-offset", VECTOR2, SHADOW_OFFSET ) +DALI_PROPERTY_REGISTRATION( TextLabel, "shadow-color", VECTOR4, SHADOW_COLOR ) +DALI_PROPERTY_REGISTRATION( TextLabel, "underline-enabled", BOOLEAN, UNDERLINE_ENABLED ) +DALI_PROPERTY_REGISTRATION( TextLabel, "underline-color", VECTOR4, UNDERLINE_COLOR ) +DALI_PROPERTY_REGISTRATION( TextLabel, "underline-height", FLOAT, UNDERLINE_HEIGHT ) +DALI_TYPE_REGISTRATION_END() + +} // namespace + +Toolkit::TextLabel TextLabel::New() +{ + // Create the implementation, temporarily owned by this handle on stack + IntrusivePtr< TextLabel > impl = new TextLabel(); + + // Pass ownership to CustomActor handle + Toolkit::TextLabel handle( *impl ); + + // Second-phase init of the implementation + // This can only be done after the CustomActor connection has been made... + impl->Initialize(); + + return handle; +} + +void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +{ + Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) ); + + if( label ) + { + TextLabel& impl( GetImpl( label ) ); + switch( index ) + { + case Toolkit::TextLabel::Property::RENDERING_BACKEND: + { + int backend = value.Get< int >(); + + if( impl.mRenderingBackend != backend ) + { + impl.mRenderingBackend = backend; + impl.mRenderer.Reset(); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextLabel::Property::TEXT: + { + if( impl.mController ) + { + impl.mController->SetText( value.Get< std::string >() ); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextLabel::Property::FONT_FAMILY: + { + if( impl.mController ) + { + std::string fontFamily = value.Get< std::string >(); + + if( impl.mController->GetDefaultFontFamily() != fontFamily ) + { + impl.mController->SetDefaultFontFamily( fontFamily ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::FONT_STYLE: + { + if( impl.mController ) + { + std::string fontStyle = value.Get< std::string >(); + + if( impl.mController->GetDefaultFontStyle() != fontStyle ) + { + impl.mController->SetDefaultFontStyle( fontStyle ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::POINT_SIZE: + { + if( impl.mController ) + { + float pointSize = value.Get< float >(); + + if( fabsf(impl.mController->GetDefaultPointSize() - pointSize) > Math::MACHINE_EPSILON_1 ) + { + impl.mController->SetDefaultPointSize( pointSize ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::MULTI_LINE: + { + if( impl.mController ) + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + LayoutEngine::Layout layout = value.Get< bool >() ? LayoutEngine::MULTI_LINE_BOX : LayoutEngine::SINGLE_LINE_BOX; + + if( engine.GetLayout() != layout ) + { + engine.SetLayout( layout ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT: + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); + + if( engine.GetHorizontalAlignment() != alignment ) + { + engine.SetHorizontalAlignment( alignment ); + impl.RequestTextRelayout(); + } + break; + } + case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT: + { + LayoutEngine& engine = impl.mController->GetLayoutEngine(); + const LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); + + if( engine.GetVerticalAlignment() != alignment ) + { + engine.SetVerticalAlignment( alignment ); + impl.RequestTextRelayout(); + } + break; + } + + case Toolkit::TextLabel::Property::TEXT_COLOR: + { + if ( impl.mController ) + { + Vector4 textColor = value.Get< Vector4 >(); + if ( impl.mController->GetTextColor() != textColor ) + { + impl.mController->SetTextColor( textColor ); + impl.RequestTextRelayout(); + } + } + break; + } + + case Toolkit::TextLabel::Property::SHADOW_OFFSET: + { + if( impl.mController ) + { + Vector2 shadowOffset = value.Get< Vector2 >(); + if ( impl.mController->GetShadowOffset() != shadowOffset ) + { + impl.mController->SetShadowOffset( shadowOffset ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::SHADOW_COLOR: + { + if( impl.mController ) + { + Vector4 shadowColor = value.Get< Vector4 >(); + if ( impl.mController->GetShadowColor() != shadowColor ) + { + impl.mController->SetShadowColor( shadowColor ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_COLOR: + { + if( impl.mController ) + { + Vector4 color = value.Get< Vector4 >(); + if ( impl.mController->GetUnderlineColor() != color ) + { + impl.mController->SetUnderlineColor( color ); + impl.RequestTextRelayout(); + } + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: + { + if( impl.mController ) + { + bool enabled = value.Get< bool >(); + if ( impl.mController->IsUnderlineEnabled() != enabled ) + { + impl.mController->SetUnderlineEnabled( enabled ); + impl.RequestTextRelayout(); + } + } + break; + } + + case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT: + { + if( impl.mController ) + { + float height = value.Get< float >(); + if ( impl.mController->GetUnderlineHeight() != height ) + { + impl.mController->SetUnderlineHeight( height ); + impl.RequestTextRelayout(); + } + } + break; + } + } + } +} + +Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index index ) +{ + Property::Value value; + + Toolkit::TextLabel label = Toolkit::TextLabel::DownCast( Dali::BaseHandle( object ) ); + + if( label ) + { + TextLabel& impl( GetImpl( label ) ); + switch( index ) + { + case Toolkit::TextLabel::Property::RENDERING_BACKEND: + { + value = impl.mRenderingBackend; + break; + } + case Toolkit::TextLabel::Property::TEXT: + { + if( impl.mController ) + { + std::string text; + impl.mController->GetText( text ); + value = text; + } + break; + } + case Toolkit::TextLabel::Property::MULTI_LINE: + { + if( impl.mController ) + { + value = static_cast( LayoutEngine::MULTI_LINE_BOX == impl.mController->GetLayoutEngine().GetLayout() ); + } + break; + } + case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT: + { + if( impl.mController ) + { + value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) ); + } + break; + } + case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT: + { + if( impl.mController ) + { + value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) ); + } + break; + } + case Toolkit::TextLabel::Property::TEXT_COLOR: + { + if ( impl.mController ) + { + value = impl.mController->GetTextColor(); + } + break; + } + case Toolkit::TextLabel::Property::SHADOW_OFFSET: + { + if ( impl.mController ) + { + value = impl.mController->GetShadowOffset(); + } + break; + } + case Toolkit::TextLabel::Property::SHADOW_COLOR: + { + if ( impl.mController ) + { + value = impl.mController->GetShadowColor(); + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_COLOR: + { + if ( impl.mController ) + { + value = impl.mController->GetUnderlineColor(); + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: + { + if ( impl.mController ) + { + value = impl.mController->IsUnderlineEnabled(); + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT: + { + if ( impl.mController ) + { + value = impl.mController->GetUnderlineHeight(); + } + break; + } + } + } + + return value; +} + +void TextLabel::OnInitialize() +{ + Actor self = Self(); + + mController = Text::Controller::New( *this ); + + // Use height-for-width negotiation by default + self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); + self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); +} + +void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) +{ + GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); +} + +Vector3 TextLabel::GetNaturalSize() +{ + return mController->GetNaturalSize(); +} + +float TextLabel::GetHeightForWidth( float width ) +{ + return mController->GetHeightForWidth( width ); +} + +void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container ) +{ + if( mController->Relayout( size ) || + !mRenderer ) + { + if( !mRenderer ) + { + mRenderer = Backend::Get().NewRenderer( mRenderingBackend ); + } + + RenderableActor renderableActor; + if( mRenderer ) + { + renderableActor = mRenderer->Render( mController->GetView() ); + } + + if( renderableActor != mRenderableActor ) + { + UnparentAndReset( mRenderableActor ); + + if( renderableActor ) + { + const Vector2& alignmentOffset = mController->GetAlignmentOffset(); + renderableActor.SetPosition( alignmentOffset.x, alignmentOffset.y ); + + Self().Add( renderableActor ); + } + + mRenderableActor = renderableActor; + } + } +} + +void TextLabel::RequestTextRelayout() +{ + RelayoutRequest(); +} + +TextLabel::TextLabel() +: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ), + mRenderingBackend( DEFAULT_RENDERING_BACKEND ) +{ +} + +TextLabel::~TextLabel() +{ +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.h b/dali-toolkit/internal/controls/text-controls/text-label-impl.h new file mode 100644 index 0000000..c69bd7c --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -0,0 +1,153 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_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. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * @brief A control which renders a short text string. + */ +class TextLabel : public Control, public Text::ControlInterface +{ +public: + + /** + * @copydoc Dali::Toollkit::TextLabel::New() + */ + static Toolkit::TextLabel New(); + + // Properties + + /** + * @brief Called when a property of an object of this type is set. + * + * @param[in] object The object whose property is set. + * @param[in] index The property index. + * @param[in] value The new property value. + */ + static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); + + /** + * @brief Called to retrieve a property of an object of this type. + * + * @param[in] object The object whose property is to be retrieved. + * @param[in] index The property index. + * @return The current value of the property. + */ + static Property::Value GetProperty( BaseObject* object, Property::Index index ); + +private: // From Control + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnInitialize(); + + /** + * @copydoc Control::OnStyleChange() + */ + virtual void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); + + /** + * @copydoc Control::OnRelayout() + */ + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); + + /** + * @copydoc Control::GetNaturalSize() + */ + virtual Vector3 GetNaturalSize(); + + /** + * @copydoc Control::GetHeightForWidth() + */ + virtual float GetHeightForWidth( float width ); + + /** + * @copydoc Text::ControlInterface::RequestTextRelayout() + */ + virtual void RequestTextRelayout(); + +private: // Implementation + + /** + * Construct a new TextLabel. + */ + TextLabel(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~TextLabel(); + +private: + + // Undefined copy constructor and assignment operators + TextLabel(const TextLabel&); + TextLabel& operator=(const TextLabel& rhs); + +private: // Data + + Text::ControllerPtr mController; + Text::RendererPtr mRenderer; + RenderableActor mRenderableActor; + + int mRenderingBackend; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Toolkit::Internal::TextLabel& GetImpl( Toolkit::TextLabel& textLabel ) +{ + DALI_ASSERT_ALWAYS(textLabel); + + Dali::RefObject& handle = textLabel.GetImplementation(); + + return static_cast(handle); +} + +inline const Toolkit::Internal::TextLabel& GetImpl( const Toolkit::TextLabel& textLabel ) +{ + DALI_ASSERT_ALWAYS(textLabel); + + const Dali::RefObject& handle = textLabel.GetImplementation(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__ diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp new file mode 100644 index 0000000..7347fd3 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp @@ -0,0 +1,623 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +// todo Move this to adaptor?? +#define GET_LOCALE_TEXT(string) dgettext("elementary", string) + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ +const Dali::Vector4 DEFAULT_POPUP_BACKGROUND( Dali::Vector4( .20f, 0.29f, 0.44f, 1.0f ) ); +const Dali::Vector4 DEFAULT_POPUP_BACKGROUND_PRESSED( Dali::Vector4( 0.07f, 0.10f, 0.17f, 1.0f ) ); +const Dali::Vector4 DEFAULT_POPUP_LINE_COLOR( Dali::Vector4( 0.36f, 0.45f, 0.59f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_ICON( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_ICON_PRESSED( Dali::Vector4( 0.5f, 1.0f, 1.0f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_TEXT( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); +const Dali::Vector4 DEFAULT_OPTION_TEXT_PRESSED( Dali::Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); + +const std::string DEFAULT_POPUP_BACKGROUND_IMAGE( DALI_IMAGE_DIR "popup_bubble_bg.#.png" ); +const std::string OPTION_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" ); +const std::string OPTION_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" ); +const std::string OPTION_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.png" ); +const std::string OPTION_ICON_PASTE( DALI_IMAGE_DIR "copy_paste_icon_paste.png" ); +const std::string OPTION_ICON_SELECT( DALI_IMAGE_DIR "copy_paste_icon_select.png" ); +const std::string OPTION_ICON_SELECT_ALL( DALI_IMAGE_DIR "copy_paste_icon_select_all.png" ); + +const Dali::Vector2 DEFAULT_POPUP_MAX_SIZE( 450.0f, 100.0f ); ///< The maximum size of the popup. + +const Dali::Vector2 OPTION_ICON_SIZE( 65.0f, 65.0f ); ///< The size of the icon. +const float OPTION_MARGIN_WIDTH( 10.f ); ///< The margin between the right or lefts edge and the text or icon. +const float OPTION_MAX_WIDTH( 110.0f ); ///< The maximum width of the option //todo Make Property +const float OPTION_MIN_WIDTH( 86.0f ); ///< The minimum width of the option. //todo Make Property +const float POPUP_DIVIDER_WIDTH( 3.f ); ///< The size of the divider. + +const Dali::Vector2 POPUP_TAIL_SIZE( 20.0f, 16.0f ); ///< The size of the tail. +const float POPUP_TAIL_Y_OFFSET( 5.f ); ///< The y offset of the tail (when its position is on the bottom). +const float POPUP_TAIL_TOP_Y_OFFSET( 3.f ); ///< The y offset of the tail (when its position is on the top). + +const float HIDE_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup hide animation in seconds. +const float SHOW_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup show animation in seconds. + +const char* const OPTION_SELECT_WORD = "option-select_word"; // "Select Word" popup option. +const char* const OPTION_SELECT_ALL("option-select_all"); // "Select All" popup option. +const char* const OPTION_CUT("option-cut"); // "Cut" popup option. +const char* const OPTION_COPY("option-copy"); // "Copy" popup option. +const char* const OPTION_PASTE("option-paste"); // "Paste" popup option. +const char* const OPTION_CLIPBOARD("option-clipboard"); // "Clipboard" popup option. + +} // namespace + +//// Comparison function for ButtonRequirement Priority +//bool TextSelectionPopup::PriorityCompare( ButtonRequirement const& a, ButtonRequirement const& b ) +//{ +// return a.priority < b.priority; +//} + + +Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New() +{ + // Create the implementation, temporarily owned by this handle on stack + IntrusivePtr< TextSelectionPopup > impl = new TextSelectionPopup(); + + // Pass ownership to CustomActor handle + Dali::Toolkit::TextSelectionPopup handle( *impl ); + + // Second-phase init of the implementation + // This can only be done after the CustomActor connection has been made... + impl->Initialize(); + + return handle; +} + +void TextSelectionPopup::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +{ + Toolkit::TextSelectionPopup selectionPopup = Toolkit::TextSelectionPopup::DownCast( Dali::BaseHandle( object ) ); + + if( selectionPopup ) + { + TextSelectionPopup& impl( GetImpl( selectionPopup ) ); + + switch( index ) + { + case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE: + { + impl.SetPopupMaxSize( value.Get< Vector2 >() ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_BACKGROUND_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_BACKGROUND, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_CLIPBOARD_BUTTON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_CUT_BUTTON_ICON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_COPY_BUTTON_ICON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_PASTE_BUTTON_ICON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_SELECT_BUTTON_ICON, image ); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::New( value.Get< std::string >() ); + impl.SetPopupImage( POPUP_SELECT_ALL_BUTTON_ICON, image ); + break; + } + } // switch + } // TextSelectionPopup +} + +Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::Index index ) +{ + Property::Value value; + + Toolkit::TextSelectionPopup selectionPopup = Toolkit::TextSelectionPopup::DownCast( Dali::BaseHandle( object ) ); + + if( selectionPopup ) + { + TextSelectionPopup& impl( GetImpl( selectionPopup ) ); + + switch( index ) + { + case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE: + { + value = impl.GetPopupMaxSize(); + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_BACKGROUND_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_BACKGROUND ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_CLIPBOARD_BUTTON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_CUT_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_COPY_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_PASTE_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_SELECT_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE: + { + ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_SELECT_ALL_BUTTON_ICON ) ); + if( image ) + { + value = image.GetUrl(); + } + break; + } + } // switch + } + return value; +} + +void TextSelectionPopup::OnInitialize() +{ + CreatePopup(); +} + +void TextSelectionPopup::OnRelayout( const Vector2& size, RelayoutContainer& container ) +{ + +} + +void TextSelectionPopup::SetPopupMaxSize( const Size& maxSize ) +{ + mMaxSize = maxSize; +} + +const Dali::Vector2& TextSelectionPopup::GetPopupMaxSize() const +{ + return mMaxSize; +} + +void TextSelectionPopup::SetPopupImage( PopupParts part, Dali::Image image ) +{ + switch ( part ) + { + case POPUP_BACKGROUND : + { + mBackgroundImage = image; + } + break; + case POPUP_CLIPBOARD_BUTTON : + { + mClipboardIconImage = image; + } + break; + case POPUP_CUT_BUTTON_ICON : + { + mCutIconImage = image; + } + break; + case POPUP_COPY_BUTTON_ICON : + { + mCopyIconImage = image; + } + break; + case POPUP_PASTE_BUTTON_ICON : + { + mPasteIconImage = image; + } + break; + case POPUP_SELECT_BUTTON_ICON : + { + mSelectIconImage = image; + } + break; + case POPUP_SELECT_ALL_BUTTON_ICON : + { + mSelectAllIconImage = image; + } + break; + + } // switch +} + +Dali::Image TextSelectionPopup::GetPopupImage( PopupParts part ) +{ + switch ( part ) + { + case POPUP_BACKGROUND : + { + return mBackgroundImage; + } + break; + case POPUP_CLIPBOARD_BUTTON : + { + return mClipboardIconImage; + } + break; + case POPUP_CUT_BUTTON_ICON : + { + return mCutIconImage; + } + break; + case POPUP_COPY_BUTTON_ICON : + { + return mCopyIconImage; + } + break; + case POPUP_PASTE_BUTTON_ICON : + { + return mPasteIconImage; + } + break; + case POPUP_SELECT_BUTTON_ICON : + { + return mSelectIconImage; + } + break; + case POPUP_SELECT_ALL_BUTTON_ICON : + { + return mSelectAllIconImage; + } + break; + default : + { + DALI_ASSERT_DEBUG( "Unknown Popup Part" ); + } + } // switch + + return Dali::Image(); +} + + void TextSelectionPopup::CreateOrderedListOfPopupOptions() + { + mOrderListOfButtons.clear(); + + // Create button for each possible option using Option priority + if ( !mCutIconImage ) + { + mCutIconImage = ResourceImage::New( OPTION_ICON_CUT ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), mCutIconImage, true ) ); + + if ( !mCopyIconImage ) + { + mCopyIconImage = ResourceImage::New( OPTION_ICON_COPY ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), mCopyIconImage, true ) ); + + if ( !mPasteIconImage ) + { + mPasteIconImage = ResourceImage::New( OPTION_ICON_PASTE ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), mPasteIconImage, true ) ); + + if ( !mSelectIconImage ) + mSelectIconImage = ResourceImage::New( OPTION_ICON_SELECT ); + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), mSelectIconImage, true ) ); + + if ( !mSelectAllIconImage ) + { + mSelectAllIconImage = ResourceImage::New( OPTION_ICON_SELECT_ALL ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), mSelectAllIconImage, true ) ); + + if ( !mClipboardIconImage ) + { + mClipboardIconImage = ResourceImage::New( OPTION_ICON_CLIPBOARD ); + } + mOrderListOfButtons.push_back( ButtonRequirement( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), mClipboardIconImage, true ) ); + + // Sort the buttons according their priorities. + std::sort( mOrderListOfButtons.begin(), mOrderListOfButtons.end(), TextSelectionPopup::ButtonPriorityCompare() ); + } + + void TextSelectionPopup::CreateBackground() + { + if ( mBackgroundImage ) + { + SetBackgroundImage ( mBackgroundImage ); + } + + SetBackgroundColor( mBackgroundColor ); + } + + void TextSelectionPopup::AddOption( Dali::Toolkit::TableView& parent, const std::string& name, const std::string& caption, const Image iconImage, bool finalOption, bool showIcons, bool showCaption, std::size_t& indexInTable ) + { + // 1. Create the backgrounds for the popup option both normal and pressed. + // Both containers will be added to a button. + + Toolkit::TableView optionContainer = Toolkit::TableView::New( (showIcons)?2:1 , 1 ); + optionContainer.SetDrawMode( DrawMode::OVERLAY ); + optionContainer.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + optionContainer.SetMinimumSize( Vector2( OPTION_MIN_WIDTH, 0 ) ); + optionContainer.SetFitWidth( 0 ); + + Toolkit::TableView optionPressedContainer = Toolkit::TableView::New( (showIcons)?2:1 , 1 ); + optionPressedContainer.SetDrawMode( DrawMode::OVERLAY ); + optionPressedContainer.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + optionPressedContainer.SetMinimumSize( Vector2( OPTION_MIN_WIDTH, 0 ) ); + optionPressedContainer.SetFitWidth( 0 ); +#ifdef DECORATOR_DEBUG + optionContainer.SetName("optionContainer"); + optionPressedContainer.SetName("optionPressedContainer"); +#endif + // 2. Add text. + + if ( showCaption ) + { + Toolkit::TextLabel captionTextLabel = Toolkit::TextLabel::New(); + captionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption ); + optionContainer.SetFitHeight( 0 ); + + Toolkit::TextLabel pressedCaptionTextLabel = Toolkit::TextLabel::New(); + pressedCaptionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption ); + optionPressedContainer.SetFitHeight( 0 ); + + captionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH ); + captionTextLabel.SetMaximumSize( Vector2( OPTION_MAX_WIDTH - 2.f * OPTION_MARGIN_WIDTH , FLT_MAX ) ); //todo FLT_MAX Size negotiation feature needed + + pressedCaptionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH ); + pressedCaptionTextLabel.SetMaximumSize( Vector2( OPTION_MAX_WIDTH - 2.f * OPTION_MARGIN_WIDTH , FLT_MAX) ); //todo FLT_MAX Size negotiation feature needed + + optionContainer.AddChild( captionTextLabel, Toolkit::TableView::CellPosition( 1, 0 ) ); // todo Labels need ellipsis or similar + optionPressedContainer.AddChild( pressedCaptionTextLabel, Toolkit::TableView::CellPosition( 1, 0 ) ); // todo Labels need ellipsis or similar + } + + if ( showIcons ) + { + // 3. Create the icons + ImageActor pressedIcon = ImageActor::New( iconImage ); + ImageActor icon = ImageActor::New( iconImage ); + icon.SetName("image-icon-2014"); + icon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + pressedIcon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + pressedIcon.SetColor( mIconPressedColor ); + optionContainer.SetFitHeight( 0 ); + optionPressedContainer.SetFitHeight( 0 ); + optionContainer.AddChild( icon, Toolkit::TableView::CellPosition( 0, 0 ) ); + optionPressedContainer.AddChild( pressedIcon, Toolkit::TableView::CellPosition( 0, 0 ) ); + icon.SetPadding( Padding( 10.0f, 10.0f, 10.0f, 10.0f ) ); + pressedIcon.SetPadding( Padding( 10.0f, 10.0f, 10.0f, 10.0f ) ); + } + + // 5. Create a option. + Toolkit::PushButton option = Toolkit::PushButton::New(); + option.SetName( name ); + option.SetAnimationTime( 0.0f ); + option.SetSize( OPTION_ICON_SIZE ); + option.SetRelayoutEnabled( false ); + //option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed ); + + // 6. Set the normal option image. + option.SetButtonImage( optionContainer ); + + // 7. Set the pressed option image + option.SetSelectedImage( optionPressedContainer ); + + // 9 Add option to table view + parent.SetFitWidth( indexInTable ); + parent.AddChild( option, Toolkit::TableView::CellPosition( 0, indexInTable ) ); + indexInTable++; + + // 10. Add the divider + if( !finalOption ) + { + const Size size( POPUP_DIVIDER_WIDTH, 0.0f ); // Height FILL_TO_PARENT + + ImageActor divider = Toolkit::CreateSolidColorActor( Color::WHITE ); + + divider.SetSize( size ); + divider.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT ); + parent.SetFitWidth( indexInTable ); + parent.AddChild( divider, Toolkit::TableView::CellPosition( 0, indexInTable ) ); + indexInTable++; + } + } + + void TextSelectionPopup::SetUpPopup() + { + Actor self = Self(); + self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); + + // Create Layer and Stencil. + mStencilLayer = Layer::New(); + mStencilLayer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); + mStencilLayer.SetParentOrigin( ParentOrigin::CENTER ); + + ImageActor stencil = CreateSolidColorActor( Color::RED ); + stencil.SetDrawMode( DrawMode::STENCIL ); + stencil.SetVisible( true ); + stencil.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); + stencil.SetParentOrigin( ParentOrigin::CENTER ); + + Actor scrollview = Actor::New(); //todo make a scrollview + scrollview.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); + scrollview.SetParentOrigin( ParentOrigin::CENTER ); + scrollview.SetRelayoutEnabled( true ); + + mTableOfButtons.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + mTableOfButtons.SetFitHeight( 0 ); + mTableOfButtons.SetParentOrigin( ParentOrigin::CENTER ); + + mStencilLayer.Add( stencil ); + mStencilLayer.Add( scrollview ); + scrollview.Add( mTableOfButtons ); + self.Add( mStencilLayer ); + //self.Add ( mTableOfButtons ); + } + + void TextSelectionPopup::AddPopupOptions( bool createTail, bool showIcons, bool showCaptions ) + { + mContentSize = Vector2::ZERO; + // Add the options into the buttons container. + + // 1. Determine how many buttons are active and should be added to container. + std::size_t numberOfOptions = 0u; + for( std::vector::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it ) + { + const ButtonRequirement& button( *it ); + if( button.enabled ) + { + ++numberOfOptions; + } + } + + // 2. Iterate list of buttons and add active ones. + std::size_t optionsAdded = 0u; + + numberOfOptions = ( numberOfOptions*2 ) - 1 ; // Last Option does not get a divider so -1 or if only one option then also no divider + + mTableOfButtons = Dali::Toolkit::TableView::New( 1, numberOfOptions ); + + for( std::vector::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it ) + { + const ButtonRequirement& button( *it ); + if ( button.enabled ) + { + AddOption( mTableOfButtons, button.name, button.caption, button.icon, optionsAdded == numberOfOptions - 1, showIcons, showCaptions, optionsAdded ); // -1 to ignore the last divider + } + } + } + + void TextSelectionPopup::CreatePopup() + { + if ( !mStencilLayer ) + { + CreateOrderedListOfPopupOptions(); //todo Currently causes all options to be shown + CreateBackground(); + AddPopupOptions( true, true, false ); // todo false so not to show Labels until ellipses or similar possible. + SetUpPopup(); + } + + mStencilLayer.RaiseToTop(); + } + +TextSelectionPopup::TextSelectionPopup() +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_NONE ) ), + mMaxSize ( DEFAULT_POPUP_MAX_SIZE ), + mVisiblePopUpSize( DEFAULT_POPUP_MAX_SIZE ), + mRequiredPopUpSize( DEFAULT_POPUP_MAX_SIZE ), + mBackgroundColor( DEFAULT_POPUP_BACKGROUND ), + mBackgroundPressedColor( DEFAULT_POPUP_BACKGROUND_PRESSED ), + mLineColor( DEFAULT_POPUP_LINE_COLOR ), + mIconColor( DEFAULT_OPTION_ICON ), + mIconPressedColor( DEFAULT_OPTION_ICON_PRESSED ), + mTextColor( DEFAULT_OPTION_TEXT ), + mTextPressedColor( DEFAULT_OPTION_TEXT_PRESSED ), + mSelectOptionPriority( 1 ), + mSelectAllOptionPriority ( 2 ), + mCutOptionPriority ( 3 ), + mCopyOptionPriority ( 4 ), + mPasteOptionPriority ( 5 ), + mClipboardOptionPriority( 6 ), + mShowIcons( true ), + mShowCaptions( false ) +{ +} + +TextSelectionPopup::~TextSelectionPopup() +{ +} + + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h new file mode 100644 index 0000000..0753579 --- /dev/null +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h @@ -0,0 +1,307 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_POPUP_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_POPUP_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. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ +enum PopupParts +{ + POPUP_BACKGROUND, + POPUP_CLIPBOARD_BUTTON, + POPUP_CUT_BUTTON_ICON, + POPUP_COPY_BUTTON_ICON, + POPUP_PASTE_BUTTON_ICON, + POPUP_SELECT_BUTTON_ICON, + POPUP_SELECT_ALL_BUTTON_ICON, +}; + +} // namespace + +class TextSelectionPopup : public Control +{ +public: + + enum Buttons + { + ButtonsCut, + ButtonsCopy, + ButtonsPaste, + ButtonsSelect, + ButtonsSelectAll, + ButtonsClipboard, + ButtonsEnumEnd + }; + + struct ButtonRequirement + { + ButtonRequirement() + : id( ButtonsEnumEnd ), + priority( 0u ), + name(), + caption(), + icon(), + enabled( false ) + {} + + ButtonRequirement( Buttons buttonId, + std::size_t buttonPriority, + const std::string& buttonName, + const std::string& buttonCaption, + Dali::Image& buttonIcon, + bool buttonEnabled ) + : id( buttonId ), + priority( buttonPriority ), + name( buttonName ), + caption( buttonCaption ), + icon( buttonIcon ), + enabled( buttonEnabled ) + {} + + Buttons id; + std::size_t priority; + std::string name; + std::string caption; + Dali::Image icon; + bool enabled; + }; + + struct ButtonPriorityCompare + { + bool operator()( const ButtonRequirement& lhs, const ButtonRequirement& rhs ) const { + return lhs.priority < rhs.priority; + } + }; + +// static inline bool ButtonPriorityCompare( ButtonRequirement a, ButtonRequirement b ) +// { +// return a.priority < b.priority ? true : false; +// } + + /** + * @copydoc Dali::Toollkit::TextSelectionPopup::New() + */ + static Toolkit::TextSelectionPopup New(); + + // Properties + + /** + * @brief Called when a property of an object of this type is set. + * @param[in] object The object whose property is set. + * @param[in] index The property index. + * @param[in] value The new property value. + */ + static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); + + /** + * @brief Called to retrieve a property of an object of this type. + * + * @param[in] object The object whose property is to be retrieved. + * @param[in] index The property index. + * @return The current value of the property. + */ + static Property::Value GetProperty( BaseObject* object, Property::Index index ); + + void CreatePopup(); + + void DestroyPopup(); + +private: // From Control + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnInitialize(); + +// /** +// * @copydoc Control::GetNaturalSize() +// */ +// virtual Vector3 GetNaturalSize(); +// +// /** +// * @copydoc Control::GetHeightForWidth() +// */ +// virtual float GetHeightForWidth( float width ); + + /** + * @copydoc Control::OnInitialize() + */ + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); +// +// /** +// * Received for single & double taps +// */ +// virtual void OnTap( const TapGesture& tap ); +// +// /** +// * @copydoc Text::ControlInterface::RequestTextRelayout() +// */ +// virtual void RequestTextRelayout(); + + /** + * Set max size of Popup + * @param[in] maxSize Size (Vector2) + */ + void SetPopupMaxSize( const Size& maxSize ); + + /** + * Get Max size of Popup + * @return Vector2 the max size of the Popup + */ + const Dali::Vector2& GetPopupMaxSize() const; + + /** + * @brief Sets the image for the given part of the Popup. + * + * @param[in] part The part of the pop from the Enum PopupParts + * @param[in] image The image to use. + */ + void SetPopupImage( PopupParts part, Dali::Image image ); + + /** + * @brief Retrieves the image of the given part used by the popup + * + * @param[in] part The part of the popup + * @return The image used for that part. + */ + Dali::Image GetPopupImage( PopupParts part ); + + void CreateOrderedListOfPopupOptions(); + + void CreateBackground(); + + void AddOption( Dali::Toolkit::TableView& parent, const std::string& name, const std::string& caption, const Image iconImage, bool finalOption, bool showIcons, bool showCaption, std::size_t& indexInTable ); + + void SetUpPopup(); + + void AddPopupOptions( bool createTail, bool showIcons, bool showCaptions ); + +private: // Implementation + + /** + * Construct a new TextField. + */ + TextSelectionPopup(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~TextSelectionPopup(); + +private: + + // Undefined copy constructor and assignment operators + TextSelectionPopup(const TextSelectionPopup&); + TextSelectionPopup& operator=(const TextSelectionPopup& rhs); + +private: // Data + + Dali::Toolkit::TableView mTableOfButtons; // Actor which holds all the buttons, sensitivity can be set on buttons via this actor + Layer mStencilLayer; // Layer to enable clipping when buttons exceed popup + + // Images to be used by the Popup + Image mBackgroundImage; + Image mCutIconImage; + Image mCopyIconImage; + Image mPasteIconImage; + Image mClipboardIconImage; + Image mSelectIconImage; + Image mSelectAllIconImage; + + ImageActor mBackground; // The background popup panel + ImageActor mTail; // The tail for the popup + ImageActor mTailEffect; //todo remove // the tail effect + ImageActor mTailLine; //todo remove // The border/outline around the tail + + Size mMaxSize; // Max size of the Popup + Size mVisiblePopUpSize; // Visible Size of popup excluding content that needs scrolling. + Size mRequiredPopUpSize; // Total size of popup including any invisible margin + + Vector4 mNinePatchMargins; // Margins between the edge of the cropped image and the nine patch rect (left, right, top, bottom). + + Size mContentSize; // Size of Content (i.e. Buttons) + //Animation mAnimation; // Popup Hide/Show animation. + + std::vector mOrderListOfButtons; // List of buttons in the order to be displayed and a flag to indicate if needed. + + Vector4 mBackgroundColor; // Color of the background of the text input popup + Vector4 mBackgroundPressedColor; // Color of the option background. + Vector4 mLineColor; // Color of the line around the text input popup + Vector4 mIconColor; // Color of the popup icon. + Vector4 mIconPressedColor; // Color of the popup icon when pressed. + Vector4 mTextColor; // Color of the popup text. + Vector4 mTextPressedColor; // Color of the popup text when pressed. + + // Priority of Options/Buttons in the Cut and Paste pop-up, higher priority buttons are displayed first, left to right. + std::size_t mSelectOptionPriority; // Position of Select Button + std::size_t mSelectAllOptionPriority; // Position of Select All button + std::size_t mCutOptionPriority; // Position of Cut button + std::size_t mCopyOptionPriority; // Position of Copy button + std::size_t mPasteOptionPriority; // Position of Paste button + std::size_t mClipboardOptionPriority; // Position of Clipboard button + + bool mShowIcons; // Flag to show icons + bool mShowCaptions; // Flag to show text captions + +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Toolkit::Internal::TextSelectionPopup& GetImpl( Toolkit::TextSelectionPopup& textSelectionPopup ) +{ + DALI_ASSERT_ALWAYS( textSelectionPopup ); + + Dali::RefObject& handle = textSelectionPopup.GetImplementation(); + + return static_cast(handle); +} + +inline const Toolkit::Internal::TextSelectionPopup& GetImpl( const Toolkit::TextSelectionPopup& textSelectionPopup ) +{ + DALI_ASSERT_ALWAYS( textSelectionPopup ); + + const Dali::RefObject& handle = textSelectionPopup.GetImplementation(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_POPUP_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp deleted file mode 100644 index b134d6c..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.cpp +++ /dev/null @@ -1,1040 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include - -using namespace Dali; - -namespace -{ -#if defined(DEBUG_ENABLED) - Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXT_INPUT_DECORATOR"); -#endif - -const Vector3 DEFAULT_SELECTION_HANDLE_SIZE( 51.0f, 79.0f, 0.0f ); -const float TOP_HANDLE_TOP_OFFSET(-1.5f); // Offset between top handle and cutCopyPaste pop-up -const float BOTTOM_HANDLE_BOTTOM_OFFSET(1.5f); // Offset between bottom handle and cutCopyPaste pop-up -const float UI_Z_OFFSET( 0.2f ); // Text Selection Handles/Cursor z-offset. -const Vector3 UI_OFFSET(0.0f, 0.0f, UI_Z_OFFSET); // Text Selection Handles/Cursor offset. -const char* DEFAULT_CURSOR( DALI_IMAGE_DIR "cursor.png" ); -const Vector4 DEFAULT_CURSOR_IMAGE_9_BORDER( 2.0f, 2.0f, 2.0f, 2.0f ); -const std::size_t CURSOR_BLINK_INTERVAL = 500; // Cursor blink interval -const float CURSOR_THICKNESS(6.0f); -const Degree CURSOR_ANGLE_OFFSET(2.0f); // Offset from the angle - -const unsigned int SCROLL_TICK_INTERVAL = 50u; -const float SCROLL_THRESHOLD = 10.f; -const float SCROLL_SPEED = 15.f; - -/** - * Whether the given position plus the cursor size offset is inside the given boundary. - * - * @param[in] position The given position. - * @param[in] cursorSize The cursor size. - * @param[in] controlSize The given boundary. - * @param[in] threshold imaginary indent around boundary that will trigger the position to be outside of control. - * - * @return whether the given position is inside the given boundary. - */ -bool IsPositionWithinControl( const Vector3& position, const Size& cursorSize, const Vector3& controlSize, const Vector2 threshold = Vector2::ZERO ) -{ - return ( position.x >= -Math::MACHINE_EPSILON_1000 + threshold.x ) && - ( position.x <= controlSize.width - threshold.x + Math::MACHINE_EPSILON_1000 ) && - ( position.y - cursorSize.height >= -Math::MACHINE_EPSILON_1000 + threshold.y ) && - ( position.y <= controlSize.height + Math::MACHINE_EPSILON_1000 - threshold.y); -} - -} - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -Decorator::Decorator( TextViewCharacterPositioning& textViewManager, TextInputTextStyle& textStyle ): - mTextViewCharacterPositioning( textViewManager ), - mTextStyle( textStyle ), - mSelectionHandleOnePosition(0), - mSelectionHandleTwoPosition(0), - mGrabHandlePosition(0), - mCursorPosition( 0 ), - mTextHighlight( textViewManager ), - mCursorBlinkStatus( true ), - mCursorVisibility( true ), - mCursorRTLEnabled( false ), - mIsGrabHandleInScrollArea( false ), - mIsCursorInScrollArea( false ), - mGrabHandleVisibility( false ), - mGrabHandleEnabled( true ) -{ -} - -Decorator::~Decorator() -{ -} - -/** - * Bounding Box - */ -void Decorator::SetBoundingBox( const Rect& boundingRectangle ) -{ - // Convert to world coordinates and store as a Vector4 to be compatible with Property Notifications. - Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); - - const float originX = boundingRectangle.x - 0.5f * stageSize.width; - const float originY = boundingRectangle.y - 0.5f * stageSize.height; - - const Vector4 boundary( originX, - originY, - originX + boundingRectangle.width, - originY + boundingRectangle.height ); - - mBoundingRectangleWorldCoordinates = boundary; -} - -Vector4 Decorator::GetBoundingBox() const -{ - return mBoundingRectangleWorldCoordinates; -} - -/** - * Selection Handles - */ -void Decorator::OnHandlePan(Actor actor, const PanGesture& gesture) -{ - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - - switch (gesture.state) - { - case Gesture::Started: - // fall through so code not duplicated - case Gesture::Continuing: - { - if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleOne() ) - { - MoveSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition, gesture.displacement ); - HidePopUp(); - } - else if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleTwo() ) - { - MoveSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition, gesture.displacement ); - HidePopUp(); - } - else if ( actor.GetParent() == mTextInputHandles.GetGrabHandle() ) - { - SetCursorVisibility( true ); - ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea ); - MoveGrabHandle( gesture.displacement ); - HidePopUp(); // Do not show popup while handle is moving - } - } - break; - - case Gesture::Finished: - { - // Revert back to non-pressed selection handle images - if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleOne() ) - { - mSelectionHandleOneActualPosition = MoveSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition, gesture.displacement ); - ShowPopupCutCopyPaste(); - } - else if ( actor.GetParent() == mTextInputHandles.GetSelectionHandleTwo() ) - { - mSelectionHandleTwoActualPosition = MoveSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition, gesture.displacement ); - ShowPopupCutCopyPaste(); - } - else if ( actor.GetParent() == mTextInputHandles.GetGrabHandle() ) - { - MoveGrabHandle( gesture.displacement ); - SetCursorVisibility( true ); - ShowPopupCutCopyPaste(); - } - } - break; - default: - break; - } -} - -void Decorator::CreateSelectionHandles( Actor targetParent ) -{ - if ( !mPanGestureDetector ) - { - mPanGestureDetector = PanGestureDetector::New(); - mPanGestureDetector.DetectedSignal().Connect(this, &Decorator::OnHandlePan); - } - - if ( !mTextInputHandles.GetSelectionHandleOne() ) - { - mTextInputHandles.CreateSelectionHandles(); - - mTextInputHandles.AttachSelectionHandlesToGivenPanGesture( mPanGestureDetector ); - - targetParent.Add( mTextInputHandles.GetSelectionHandleOne() ); - targetParent.Add( mTextInputHandles.GetSelectionHandleTwo() ); - - SetUpHandlePropertyNotifications(); - } -} - -void Decorator::RemoveSelectionHandles() -{ - mTextInputHandles.DestorySelectionHandles(); -} - -Vector3 Decorator::GetSelectionHandleSize() -{ - return DEFAULT_SELECTION_HANDLE_SIZE; -} - -std::size_t Decorator::GetHandleOnePosition() const -{ - return mSelectionHandleOnePosition; -} - -std::size_t Decorator::GetHandleTwoPosition() const -{ - return mSelectionHandleTwoPosition; -} - -Vector3 Decorator::PositionSelectionHandle( Actor selectionHandle, std::size_t position ) -{ - bool direction(false); - Vector3 alternatePosition; - bool alternatePositionValid(false); - - Vector3 actualPositionOfSelectionHandle = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( position, direction, alternatePosition,alternatePositionValid ); - - return PositionSelectionHandle( selectionHandle, actualPositionOfSelectionHandle, position ); - -} - -Vector3 Decorator::PositionSelectionHandle( Actor selectionHandle, Vector3& actualPosition, std::size_t position ) -{ - const Vector3 DEFAULT_HANDLE_OFFSET(0.0f, -5.0f, 0.0f); - - selectionHandle.SetPosition( actualPosition += DEFAULT_HANDLE_OFFSET ); - - return actualPosition; -} - -void Decorator::SetSelectionHandlesVisibility(bool visible ) -{ - mTextInputHandles.SetSelectionHandleOneVisibility( visible ); - mTextInputHandles.SetSelectionHandleTwoVisibility( visible ); -} - -void Decorator::PositionSelectionHandles( std::size_t start, std::size_t end ) -{ - mSelectionHandleOnePosition = start; - mSelectionHandleTwoPosition = end; - - mTextViewCharacterPositioning.UpdateTextLayoutInfo(); - - mSelectionHandleOneActualPosition = PositionSelectionHandle( mTextInputHandles.GetSelectionHandleOne(), mSelectionHandleOnePosition ); - mSelectionHandleTwoActualPosition = PositionSelectionHandle( mTextInputHandles.GetSelectionHandleTwo(), mSelectionHandleTwoPosition ); -} - -Vector3 Decorator::MoveSelectionHandle( Actor selectionHandle, - Vector3& actualSelectionHandlePosition, - std::size_t& currentSelectionHandlePosition, - const Vector2& displacement ) -{ - Vector3 actualHandlePosition; - actualSelectionHandlePosition.x += displacement.x * selectionHandle.GetCurrentScale().x; - actualSelectionHandlePosition.y += displacement.y * selectionHandle.GetCurrentScale().y; - - // Selection handles should jump to the nearest character - std::size_t newHandlePosition = 0; - newHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( actualSelectionHandlePosition.GetVectorXY() ); - - bool direction(false); - Vector3 alternatePosition; - bool alternatePositionValid(false); - actualHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandlePosition,direction, alternatePosition, alternatePositionValid ); - - bool handleVisible = true; - - if ( handleVisible && // Ensure the handle is visible. - ( newHandlePosition != currentSelectionHandlePosition ) && // Ensure the handle has moved. - ( newHandlePosition != mSelectionHandleTwoPosition ) && // Ensure new handle position not the same position as an existing handle. - ( newHandlePosition != mSelectionHandleOnePosition ) ) - { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::MoveSelectionHandle Handle visible and moved]\n"); - - currentSelectionHandlePosition = newHandlePosition; - - PositionSelectionHandle( selectionHandle, actualHandlePosition, newHandlePosition ); - - ShowUpdatedHighlight(); - - // Set Active Style to that of first character in selection - std::size_t firstHandleInSelection = std::min( mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - - const TextStyle inputStyle = mTextViewCharacterPositioning.GetStyleAt( firstHandleInSelection ); - mTextStyle.SetInputStyle( inputStyle ); - } - return actualHandlePosition; // Returns Handle position passed in if new value not assigned. -} - -/** - * GrabHandle - */ -void Decorator::PositionGrabHandle( std::size_t positionInText ) -{ - bool direction(false); - Vector3 alternatePosition; - bool alternatePositionValid(false); - - mGrabHandlePosition = positionInText; - - mTextViewCharacterPositioning.UpdateTextLayoutInfo(); - mActualGrabHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( positionInText, direction, alternatePosition,alternatePositionValid ); - - mTextInputHandles.GetGrabHandle().SetPosition( mActualGrabHandlePosition ); -} - -void Decorator::MoveGrabHandle( const Vector2& displacement /*, std::size_t currentHandlePosition */) -{ - mActualGrabHandlePosition.x += displacement.x; - mActualGrabHandlePosition.y += displacement.y; - - // Grab handle should jump to the nearest character and take cursor with it - std::size_t newHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY() ); - - Vector3 actualHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandlePosition ); - - bool handleVisible = true; - - if( ( newHandlePosition != mGrabHandlePosition ) && // Only redraw cursor and do updates if position changed - ( handleVisible ) )// and the new position is visible (if scroll is not enabled, it's always true). - { - mActualGrabHandlePosition = actualHandlePosition; - mTextInputHandles.GetGrabHandle().SetPosition( mActualGrabHandlePosition ); - - //PositionGrabHandle( newHandlePosition ); - mGrabHandlePosition = newHandlePosition; - SetCurrentCursorPosition( mGrabHandlePosition ); - DrawCursor( mGrabHandlePosition ); - - const std::size_t cursorPosition = GetCurrentCursorPosition(); - - // Let keyboard know the new cursor position so can 're-capture' for prediction. - mCursorRePositionedSignal.Emit(); - - // Set Input Style to that of cursor position - if ( !mTextViewCharacterPositioning.IsStyledTextEmpty() && ( cursorPosition > 0 ) ) - { - DALI_ASSERT_DEBUG( ( 0 <= cursorPosition-1 ) && ( cursorPosition-1 < mTextViewCharacterPositioning.StyledTextSize() ) ); - } - } -} - -void Decorator::ShowGrabHandle( bool visible ) -{ - mGrabHandleVisibility = visible; - mTextInputHandles.SetGrabHandleVisibility( visible ); -} - -void Decorator::CreateGrabHandle( Actor targetParent ) -{ - if ( !mPanGestureDetector ) - { - mPanGestureDetector = PanGestureDetector::New(); - mPanGestureDetector.DetectedSignal().Connect(this, &Decorator::OnHandlePan); - } - - if ( !mTextInputHandles.GetGrabHandle() ) - { - mTextInputHandles.CreateGrabHandle(); - mTextInputHandles.AttachGrabHandleToGivenPanGesture( mPanGestureDetector ); - targetParent.Add( mTextInputHandles.GetGrabHandle() ); - } -} - -void Decorator::SetGrabHandleImage( Image image ) -{ - mTextInputHandles.SetGrabHandleImage( image ); -} - -void Decorator::EnableGrabHandle( bool toggle) -{ - // enables grab handle with will in turn de-activate magnifier - mGrabHandleEnabled = toggle; -} - -bool Decorator::IsGrabHandleEnabled() -{ - // if false then magnifier will be shown instead. - return mGrabHandleEnabled; -} - -/** - * Cursor - */ -std::size_t Decorator::GetCurrentCursorPosition() const -{ - return mCursorPosition; -} - -void Decorator::SetCurrentCursorPosition( std::size_t newCursorPosition ) -{ - mCursorPosition = newCursorPosition; -} - -void Decorator::SetCursorVisibility( bool visible ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::SetCursorVisibility[%s]\n", ( visible )?"true":"false"); - - mCursorVisibility = visible; - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea ); - mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled ); -} - -void Decorator::DrawCursor(const std::size_t nthChar) -{ - std::size_t cursorPosition = GetCurrentCursorPosition(); - - // Get height of cursor and set its size - Size size( CURSOR_THICKNESS, 0.0f ); - - Vector2 min, max; // out parameters for GetRowRectFromCharacterPosition - size.height = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mTextViewCharacterPositioning.GetVisualPosition( cursorPosition ), min, max ).height; - - mCursor.SetSize(size); - - // If the character is italic then the cursor also tilts. - if ( !mTextViewCharacterPositioning.IsStyledTextEmpty() && ( cursorPosition > 0 ) ) - { - DALI_ASSERT_DEBUG( ( 0 <= cursorPosition-1 ) && ( cursorPosition-1 < mTextViewCharacterPositioning.StyledTextSize() ) ); - const TextStyle styleAtCursor = mTextViewCharacterPositioning.GetStyleAt( cursorPosition-1 ); - mCursor.SetOrientation( styleAtCursor.IsItalicsEnabled() ? Degree( styleAtCursor.GetItalicsAngle() - CURSOR_ANGLE_OFFSET ) : Degree( 0.f ), Vector3::ZAXIS ); - } - - DALI_ASSERT_DEBUG( cursorPosition <= mTextViewCharacterPositioning.GetNumberOfCharactersInText() ); - if ( ( cursorPosition <= mTextViewCharacterPositioning.GetNumberOfCharactersInText() ) ) - { - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid( false ); // Alternate cursor validity flag. - bool directionRTL( false ); // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 position = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition, directionRTL, altPosition, altPositionValid ); - - SetAltCursorEnabled( altPositionValid ); - - mCursor.SetPosition( position + UI_OFFSET ); - } -} - -void Decorator::SetAltCursorEnabled( bool enabled ) -{ - mCursorRTLEnabled = enabled; - mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled ); -} - -void Decorator::SetCursorImage(Dali::Image image, const Vector4& border ) -{ - DALI_ASSERT_DEBUG ( image && "Create cursor image invalid") - - if ( image ) - { - mCursor.SetImage( image ); - mCursor.SetNinePatchBorder( border ); - } -} - -void Decorator::SetRTLCursorImage( Image image, const Vector4& border ) -{ - DALI_ASSERT_DEBUG ( image && "Create cursor image invalid") - - if ( image ) - { - mCursorRTL.SetImage( image ); - mCursorRTL.SetNinePatchBorder( border ); - } -} - -ImageActor Decorator::CreateCursor( Image cursorImage, const Vector4& border, const std::string& cursorName ) -{ - ImageActor cursor; - - if ( cursorImage ) - { - cursor = ImageActor::New( cursorImage ); - } - else - { - cursor = ImageActor::New( ResourceImage::New( DEFAULT_CURSOR ) ); - } - - cursor.SetStyle(ImageActor::STYLE_NINE_PATCH); - cursor.SetNinePatchBorder( border ); - cursor.SetAnchorPoint(AnchorPoint::BOTTOM_CENTER); - cursor.SetVisible(false); - cursor.SetName( cursorName ); - return cursor; -} - -void Decorator::CreateCursors( Actor targetParent ) -{ - Image mCursorImage = ResourceImage::New( DEFAULT_CURSOR ); - mCursor = CreateCursor (mCursorImage, DEFAULT_CURSOR_IMAGE_9_BORDER , "mainCursor"); - mCursorRTL = CreateCursor ( mCursorImage, DEFAULT_CURSOR_IMAGE_9_BORDER, "rtlCursor"); - targetParent.Add( mCursor ); - targetParent.Add( mCursorRTL ); -} - -Size Decorator::GetCursorSizeAt( std::size_t positionWithinTextToGetCursorSize ) -{ - std::size_t visualPosition = mTextViewCharacterPositioning.GetVisualPosition( positionWithinTextToGetCursorSize ); - - Vector2 min, max; - - const Size cursorSize( CURSOR_THICKNESS, - mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( visualPosition, min, max ).height ); - - return cursorSize; -} - -void Decorator::StartCursorBlinkTimer() -{ - if ( !mCursorBlinkTimer ) - { - mCursorBlinkTimer = Timer::New( CURSOR_BLINK_INTERVAL ); - mCursorBlinkTimer.TickSignal().Connect( this, &Decorator::OnCursorBlinkTimerTick ); - } - - if ( !mCursorBlinkTimer.IsRunning() ) - { - mCursorBlinkTimer.Start(); - } -} - -void Decorator::StopCursorBlinkTimer() -{ - if ( mCursorBlinkTimer ) - { - mCursorBlinkTimer.Stop(); - } -} - -bool Decorator::OnCursorBlinkTimerTick() -{ - // Cursor blinking - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus ); - if ( mCursorRTLEnabled ) - { - mCursorRTL.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus ); - } - mCursorBlinkStatus = !mCursorBlinkStatus; - - return true; -} - -/** - * Highlight - */ -void Decorator::ShowUpdatedHighlight() -{ - Toolkit::TextView::TextLayoutInfo textLayoutInfo = mTextViewCharacterPositioning.GetLayoutInfo(); - TextHighlight::HighlightInfo highlightInfo = mTextHighlight.CalculateHighlightInfo( mSelectionHandleOnePosition, mSelectionHandleTwoPosition, textLayoutInfo ); - - // Clamp highlightInfo so they don't exceed the boundary of the control. - const Vector3& controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize(); - highlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) ); - - mTextHighlight.UpdateHighlight( highlightInfo ); -} - -void Decorator::CreateHighlight( Actor parent ) -{ - DALI_ASSERT_DEBUG( parent && "Highlight target parent does not exist" ); - -} - -void Decorator::RemoveHighlight() -{ -} - -void Decorator::HighlightVisibility( bool visiblility ) -{ -} - -/** - * Callbacks connected to be Property notifications for Boundary checking. - */ -// Note If PropertyNotification signal definition included Actor we would not need to duplicate functions. -void Decorator::OnHandleOneLeavesBoundary( PropertyNotification& source) -{ - mTextInputHandles.GetSelectionHandleOne().SetOpacity(0.0f); -} - -void Decorator::OnHandleOneWithinBoundary(PropertyNotification& source) -{ - mTextInputHandles.GetSelectionHandleOne().SetOpacity(1.0f); -} - -void Decorator::OnHandleTwoLeavesBoundary( PropertyNotification& source) -{ - mTextInputHandles.GetSelectionHandleTwo().SetOpacity(0.0f); -} - -void Decorator::OnHandleTwoWithinBoundary(PropertyNotification& source) -{ - mTextInputHandles.GetSelectionHandleTwo().SetOpacity(1.0f); -} - -void Decorator::OnLeftBoundaryExceeded(PropertyNotification& source) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "TextInputDecorationLayouter::OnLeftBoundaryExceeded\n"); - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - selectionHandleOne.SetScale( -1.0f, 1.0f, 1.0f ); - selectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_LEFT); -} - -void Decorator::OnReturnToLeftBoundary(PropertyNotification& source) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "TextInputDecorationLayouter::OnReturnToLeftBoundary\n"); - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - selectionHandleOne.SetScale( 1.0f, 1.0f, 1.0f ); - selectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_RIGHT); -} - -void Decorator::OnRightBoundaryExceeded(PropertyNotification& source) -{ - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - selectionHandleTwo.SetScale( -1.0f, 1.0f, 1.0f ); - selectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_RIGHT); -} - -void Decorator::OnReturnToRightBoundary(PropertyNotification& source) -{ - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - selectionHandleTwo.SetScale( 1.0f, 1.0f, 1.0f ); - selectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_LEFT); -} - -void Decorator::SetUpHandlePropertyNotifications() -{ - /* Property notifications for handles exceeding the boundary and returning back within boundary */ - - Vector3 handlesize = GetSelectionHandleSize(); - - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - - // Exceeding horizontal boundary - PropertyNotification leftNotification = selectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.x + handlesize.x) ); - leftNotification.NotifySignal().Connect( this, &Decorator::OnLeftBoundaryExceeded ); - - PropertyNotification rightNotification = selectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.z - handlesize.x ) ); - rightNotification.NotifySignal().Connect( this, &Decorator::OnRightBoundaryExceeded ); - - // Within horizontal boundary - PropertyNotification leftLeaveNotification = selectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.x + 2*handlesize.x ) ); - leftLeaveNotification.NotifySignal().Connect( this, &Decorator::OnReturnToLeftBoundary ); - - PropertyNotification rightLeaveNotification = selectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.z - 2*handlesize.x ) ); - rightLeaveNotification.NotifySignal().Connect( this, &Decorator::OnReturnToRightBoundary ); - - // Exceeding vertical boundary - PropertyNotification verticalExceedNotificationOne = selectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalExceedNotificationOne.NotifySignal().Connect( this, &Decorator::OnHandleOneLeavesBoundary ); - - PropertyNotification verticalExceedNotificationTwo = selectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalExceedNotificationTwo.NotifySignal().Connect( this, &Decorator::OnHandleTwoLeavesBoundary ); - - // Within vertical boundary - PropertyNotification verticalWithinNotificationOne = selectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalWithinNotificationOne.NotifySignal().Connect( this, &Decorator::OnHandleOneWithinBoundary ); - - PropertyNotification verticalWithinNotificationTwo = selectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalWithinNotificationTwo.NotifySignal().Connect( this, &Decorator::OnHandleTwoWithinBoundary ); -} - -/** - * PopUp - */ -Vector3 Decorator::PositionOfPopUpRelativeToSelectionHandles() -{ - Vector3 position; - Vector2 min, max; - Vector3 topHandle; - Size rowSize; - - // When text is selected, show popup above top handle (and text), or below bottom handle. - - // topHandle: referring to the top most point of the handle or the top line of selection. - if ( mSelectionHandleTwoActualPosition.y > mSelectionHandleOneActualPosition.y ) // Handle may switch positions so calculate which is top. - { - topHandle = mSelectionHandleOneActualPosition; - rowSize= mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mSelectionHandleOnePosition, min, max ); - } - else - { - topHandle = mSelectionHandleTwoActualPosition; - rowSize = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( mSelectionHandleTwoPosition, min, max ); - } - topHandle.y += TOP_HANDLE_TOP_OFFSET - rowSize.height; - position = Vector3(topHandle.x, topHandle.y, 0.0f); - - return position; -} - -Vector3 Decorator::AlternatePopUpPositionRelativeToSelectionHandles() -{ - // alternativePosition: referring to the bottom most point of the handle or the bottom line of selection. - Vector3 alternativePosition; - alternativePosition.y = std::max ( mSelectionHandleTwoActualPosition.y , mSelectionHandleOneActualPosition.y ); - alternativePosition.y += GetSelectionHandleSize().y + mPopUpPanel.GetSize().y + BOTTOM_HANDLE_BOTTOM_OFFSET; - - return alternativePosition; -} - -Vector3 Decorator::PositionOfPopUpRelativeToCursor() -{ - // When no text is selected, show PopUp at position of cursor - Vector3 position; - Vector2 min, max; - std::size_t cursorPosition = GetCurrentCursorPosition(); - position = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition ); - const Size rowSize = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( cursorPosition, min, max ); - position.y -= rowSize.height; - - return position; -} - -Vector3 Decorator::AlternatePopUpPositionRelativeToCursor() -{ - std::size_t cursorPosition = GetCurrentCursorPosition(); - Vector3 alternativePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorPosition ); - - if ( mTextInputHandles.GetGrabHandle() ) - { - // If grab handle enabled then position pop-up below the grab handle. - alternativePosition.y += mTextInputHandles.GetGrabHandle().GetCurrentSize().height + mPopUpPanel.GetSize().y + BOTTOM_HANDLE_BOTTOM_OFFSET ; - } - else - { - alternativePosition.y += mPopUpPanel.GetSize().y; - } - - return alternativePosition; - -} - -Vector3 Decorator::PositionOfPopUpRelativeToGrabHandle() -{ - return Vector3::ZERO; -} - -void Decorator::ShowPopUp() -{ - Vector3 position; - Vector3 alternativePosition; - Size rowSize; - - DALI_ASSERT_DEBUG( mPopUpTarget && "PopUp Target Actor does not exist" ); - - { - position = PositionOfPopUpRelativeToCursor(); - } - - // reposition popup above the desired cursor position. - mPopUpPanel.Show( mPopUpTarget, true ); - mPopUpPanel.Self().SetPosition( position ); - mPopUpPanel.PressedSignal().Connect( this, &Decorator::OnPopupButtonPressed ); - - SetUpPopUpPositionNotifications(); - mPopUpPanel.ApplyConfinementConstraint( mBoundingRectangleWorldCoordinates ); -} - -void Decorator::ShowPopUp( Actor target ) -{ - mPopUpTarget = target; - ShowPopupCutCopyPaste(); -} - -void Decorator::ShowPopupCutCopyPaste() -{ - bool isAllTextSelectedAlready = ( mTextViewCharacterPositioning.StyledTextSize() == GetSelectedText().size() ); - bool isTextEmpty = mTextViewCharacterPositioning.IsStyledTextEmpty() ; - bool isSubsetOfTextAlreadySelected = ( !isAllTextSelectedAlready ) &&false; - - Clipboard clipboard = Clipboard::Get(); - bool hasClipboardGotContent = clipboard.NumberOfItems(); - - mPopUpPanel.CreateCutCopyPastePopUp( isAllTextSelectedAlready, isTextEmpty, hasClipboardGotContent, isSubsetOfTextAlreadySelected ); - ShowPopUp(); -} - -void Decorator::HidePopUp( bool animate, bool signalFinished ) -{ -} - -void Decorator::AddPopupOption(const std::string& name, const std::string& caption, const Image icon, bool finalOption) -{ - mPopUpPanel.AddButton(name, caption, icon, finalOption); -} - -void Decorator::ClearPopup() -{ - mPopUpPanel.Clear(); -} - -void Decorator::PopUpLeavesVerticalBoundary( PropertyNotification& source) -{ - Vector3 position, alternativePosition; - - { - alternativePosition = AlternatePopUpPositionRelativeToCursor(); - // if can't be positioned above, then position below row. - } - // reposition popup above the desired cursor position. - mPopUpPanel.Self().SetPosition( alternativePosition ); -} - -void Decorator::SetUpPopUpPositionNotifications( ) -{ - // Note Property notifications ignore any set anchor point so conditions must allow for this. Default is Top Left. - - // Exceeding vertical boundary - PropertyNotification verticalExceedNotificationOne = mPopUpPanel.Self().AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + mPopUpPanel.GetSize().y/2, - mBoundingRectangleWorldCoordinates.w - mPopUpPanel.GetSize().y/2 ) ); - verticalExceedNotificationOne.NotifySignal().Connect( this, &Decorator::PopUpLeavesVerticalBoundary ); -} - -bool Decorator::OnPopupButtonPressed( Toolkit::Button button ) -{ - mPopUpButtonPressedSignal.Emit( button ); - return false; -} - -Decorator::PressedSignal& Decorator::PopUpButtonPressedSignal() -{ - return mPopUpButtonPressedSignal; -} - -Decorator::CursorPositionedSignal& Decorator::CursorRePositionedSignal() -{ - return mCursorRePositionedSignal; -} - -/** - * Decoration Positioning during Scrolling - */ -void Decorator::TextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::TextViewScrolled\n"); - - const Vector3& controlSize = mTextViewCharacterPositioning.GetTextView().GetCurrentSize(); // todo Could store size and only update in Control Size change. - Size cursorSize( CURSOR_THICKNESS, 0.f ); - - // Updates the cursor and grab handle position and visibility. - if( mTextInputHandles.GetGrabHandle() || mCursor ) - { - Vector2 min, max; - size_t cursorTextPosition = GetCurrentCursorPosition(); - cursorSize.height = mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( cursorTextPosition, min, max ).height; - - const Vector3 cursorPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( cursorTextPosition ); - - bool mIsCursorInScrollArea = IsPositionWithinControl( cursorPosition, cursorSize, controlSize ); - bool mIsGrabHandleInScrollArea = mIsCursorInScrollArea; - - Vector2 actualGrabHandlePosition = cursorPosition.GetVectorXY(); - - if( mTextInputHandles.GetGrabHandle() ) - { - ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea ); - PositionGrabHandle( cursorTextPosition ); - } - - if( mCursor ) - { - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea ); - DrawCursor( cursorTextPosition ); - mCursor.SetPosition( Vector3(actualGrabHandlePosition) + UI_OFFSET ); - } - } - - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - - // Updates the selection handles and highlighted text position and visibility. - if( mTextInputHandles.GetSelectionHandleOne() && mTextInputHandles.GetSelectionHandleTwo() ) - { - const Vector3 cursorPositionOne = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition ); - const Vector3 cursorPositionTwo = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition ); - - Size cursorSize( GetCursorSizeAt( mSelectionHandleOnePosition ) ); - const bool isSelectionHandleOneVisible = IsPositionWithinControl( cursorPositionOne, cursorSize, controlSize ); - - cursorSize = GetCursorSizeAt( mSelectionHandleTwoPosition ); - const bool isSelectionHandleTwoVisible = IsPositionWithinControl( cursorPositionTwo, cursorSize, controlSize ); - - mSelectionHandleOneActualPosition = cursorPositionOne.GetVectorXY(); - mSelectionHandleTwoActualPosition = cursorPositionTwo.GetVectorXY(); - - selectionHandleOne.SetVisible( isSelectionHandleOneVisible ); - selectionHandleTwo.SetVisible( isSelectionHandleTwoVisible ); - - PositionSelectionHandle( selectionHandleOne, mSelectionHandleOneActualPosition, mSelectionHandleOnePosition ); - PositionSelectionHandle( selectionHandleTwo, mSelectionHandleTwoActualPosition, mSelectionHandleTwoPosition ); - - } -} - -void Decorator::StartScrollTimer() -{ - if( !mScrollTimer ) - { - mScrollTimer = Timer::New( SCROLL_TICK_INTERVAL ); - mScrollTimer.TickSignal().Connect( this, &Decorator::OnScrollTimerTick ); - } - - if( !mScrollTimer.IsRunning() ) - { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::StartScrollTimer\n"); - mScrollTimer.Start(); - } -} - -void Decorator::StopScrollTimer() -{ - if( mScrollTimer ) - { - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::StopScrollTimer\n"); - - mScrollTimer.Stop(); - mScrollTimer.Reset(); - } -} - -bool Decorator::OnScrollTimerTick() -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::OnScrollTimerTick\n"); - - if ( mGrabHandleVisibility && mTextInputHandles.GetGrabHandle() ) - { - std::size_t newGrabHandlePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY() ); - if ( mGrabHandlePosition != newGrabHandlePosition ) - { - Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition(); - Vector2 scrollDelta = ( mActualGrabHandlePosition - mCurrentHandlePosition ).GetVectorXY(); - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputDecorationLayouter::OnScrollTimerTick scrollPosition(%f) scrollDelta(%f)\n", scrollPosition.x, scrollDelta.x); - scrollPosition += scrollDelta; - mTextViewCharacterPositioning.SetScrollPosition( scrollPosition ); - - mActualGrabHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newGrabHandlePosition ).GetVectorXY(); - } - } - - Actor selectionHandleOne = mTextInputHandles.GetSelectionHandleOne(); - Actor selectionHandleTwo = mTextInputHandles.GetSelectionHandleTwo(); - - if ( selectionHandleOne && selectionHandleTwo ) - { - std::size_t newHandleOnePosition = mTextViewCharacterPositioning.ReturnClosestIndex( mSelectionHandleOneActualPosition.GetVectorXY() ); - - // todo duplicated code should be a function - - if ( mSelectionHandleOnePosition != newHandleOnePosition ) - { - const Vector3 actualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandleOnePosition ); - - Vector2 scrollDelta = ( actualPosition - mSelectionHandleOneActualPosition ).GetVectorXY(); - - Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition(); - scrollPosition += scrollDelta; - mTextViewCharacterPositioning.SetScrollPosition( scrollPosition ); - - mSelectionHandleOnePosition = newHandleOnePosition; - mSelectionHandleOneActualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition ).GetVectorXY(); - } - else - { - mSelectionHandleOneActualPosition.x += mScrollDisplacement.x; - mSelectionHandleOneActualPosition.y += mScrollDisplacement.y; - } - - std::size_t newHandleTwoPosition = mTextViewCharacterPositioning.ReturnClosestIndex( mSelectionHandleTwoActualPosition.GetVectorXY() ); - - if ( mSelectionHandleTwoPosition != newHandleTwoPosition ) - { - const Vector3 actualPosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( newHandleTwoPosition ); - - Vector2 scrollDelta = ( actualPosition - mSelectionHandleTwoActualPosition ).GetVectorXY(); - - Vector2 scrollPosition = mTextViewCharacterPositioning.GetScrollPosition(); - scrollPosition += scrollDelta; - mTextViewCharacterPositioning.SetScrollPosition( scrollPosition ); - - mSelectionHandleTwoPosition = newHandleTwoPosition; - mCurrentHandlePosition = mTextViewCharacterPositioning.GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition ).GetVectorXY(); - - } - else - { - mSelectionHandleTwoActualPosition.x += mScrollDisplacement.x; - mSelectionHandleTwoActualPosition.y += mScrollDisplacement.y; - } - } - - return true; -} - -/** - * Text Selection - */ -MarkupProcessor::StyledTextArray Decorator::GetSelectedText() -{ - MarkupProcessor::StyledTextArray currentSelectedText; - - return currentSelectedText; -} - -} // Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h b/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h deleted file mode 100644 index 46a03e6..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-decorator-impl.h +++ /dev/null @@ -1,631 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__ - -/* - * Copyright (c) 2014 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 -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class Decorator; - -typedef IntrusivePtr DecoratorPtr; - -/** - * @brief Decorator Class - * - * Decorations are Selection Handles, cursor, grab handle, magnifier the "cut copy paste" PopUp and Selection highlight. - * The Decorator triggers creation of these decorations and positions them. - * Decoration positions can be dependent on other decorations like the PopUp on the Selection handles. - * The decorator maintains a Bounding Box which the decorations have to be positioned within, decorations can be flipped or hidden to obey this Bounding Box. - * Scrolling of Text can effect positioning of decorations, the decorator repositions decorations in this case. - */ - -class Decorator : public ConnectionTracker -{ - -public: - - /** - * @brief Constructor - * - * @param[in] textviewManager TextViewManager to be used - */ - Decorator( TextViewCharacterPositioning& textviewManager, TextInputTextStyle& textStyle); - - /** - * @brief Default destructor - */ - ~Decorator(); - - /** - * @brief Set the dimensions of the bounding rectangle for decorations to obey. - * - * @param[in] boundingRectangle - */ - void SetBoundingBox( const Rect& boundingRectangle ); - - /** - * @brief Get the bounding dimensions of the bounding box - * - * @return dimensions of the bounding box from world origin. (x, y, w, z ) - * - * ----------------- - * | ^ | - * | | | - * | y | - * | | | - * | v | - * |<--x--> o <--z-->| - * | ^ | - * | | | - * | w | - * | | | - * | v | - * ----------------- - */ - Vector4 GetBoundingBox() const; - - /** - * @brief Callback when a handle is panned/moved, either selection handles or grab handle - * - * @param actor Handle of the selection or grab handle. - * @param gesture Data structure with the parameters of the gesture. - */ - void OnHandlePan(Actor actor, const PanGesture& gesture); - - // Selection Handles - - /** - * @brief Create a left and right selection handle and parent both to the provided actor - * @param[in] parent actor in which the handles should be added to. - */ - void CreateSelectionHandles( Actor parent ); - - /** - * @brief Remove selection handles from their parent - */ - void RemoveSelectionHandles(); - - /** - * @brief Get size of Selection handles - * - * @return size of a selection handle - */ - Vector3 GetSelectionHandleSize(); - - /** - * @brief Get position of Selection handle within text - * - * @return character position of a selection handle one - */ - std::size_t GetHandleOnePosition() const; - - /** - * @brief Get position of Selection handle within text - * - * @return character position of a selection handle two - */ - std::size_t GetHandleTwoPosition() const; - - /** - * @brief Position Selection a single handle at given positions within the text string. - * - * @param[in] selectionHandle handle to be positioned - * @param[in] position where to place handle - * @return Vector3 Position of handle as a coordinate. - */ - Vector3 PositionSelectionHandle( Actor selectionHandle, std::size_t position ); - - /** - * @brief Position Selection a single handle at given coordinates - * - * @param[in] selectionHandle handle to be positioned - * @param[in] actualPosition coordinates to position handle - * @param[in] position where to place handle - * @return Vector3 Position of handle as a coordinate. - */ - Vector3 PositionSelectionHandle( Actor selectionHandle, Vector3& actualPosition, std::size_t position ); - - /** - * @brief Make both selection handle visible or invisible - * @param[in] visible true to make visible, false to fine - */ - void SetSelectionHandlesVisibility( bool visible ); - - /** - * @brief Position Selection handles at given positions within the text string. - * - * @param[in] start where to place first handle - * @param[in] end where to place second handle - */ - void PositionSelectionHandles( std::size_t start, std::size_t end ); - - /** - * @brief Move selection handle by the given displacement. - * - * @param[in] selectionHandle Actor to move - * @param[in] actualSelectionHandlePosition actual current position of the handle in x y z - * @param[in] currentSelectionHandlePosition current position along the string - * @param[in] displacement the x y displacement - */ - Vector3 MoveSelectionHandle( Actor selectionHandle, - Vector3& actualSelectionHandlePosition, - std::size_t& currentSelectionHandlePosition, - const Vector2& displacement ); - - /* Grab Handle */ - - /** - * @brief Position GrabHandlewith depending on the the character in the text it should be placed at - * @param[in] positonInText the character position within the text the handle should be at - */ - void PositionGrabHandle( std::size_t positionInText ); - - /** - * @brief Move grab handle to the required position within the text - * - * @param[in] displacement Displacement of the grab handle in actor coordinates. - */ - void MoveGrabHandle( const Vector2& displacement ); - - /** - * @brief Show or hide the GrabHandle is visibility is true - * - * @param[in] visible flag to show or not show the grab handle - */ - void ShowGrabHandle( bool visible ); - - /** - * @brief Create the GrabHandle used to position cursor - * @param[in] targetParent the Actor to parent the GrabHandle - */ - void CreateGrabHandle( Actor targetParent ); - - /** - * @brief Set the image to be used as the cursor grab hander - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - */ - void SetGrabHandleImage( Image image ); - - /** - * @brief Toggle to enable the grab handle, used to position cursor when magnifier not being used. - * Default behaviour is to use the magnifier to position the cursor, enabling this prevents the magnifier from being shown. - * @param[in] toggle true to enable, false to disable grab handle - */ - void EnableGrabHandle(bool toggle); - - /** - * @brief Method to check if grab handle is enabled, if false then the magnifier will be used to position cursor. - * @return bool returns true is grab handle enabled. - */ - bool IsGrabHandleEnabled(); - - /* Cursor */ - - /** - * @brief Get the current Cursor position - * @return current cursor position - */ - std::size_t GetCurrentCursorPosition() const; - - /** - * @brief Set the Cursor position - * @param[in] the position the cursor should be set to - */ - void SetCurrentCursorPosition( std::size_t newCursorPosition ); - - /** - * @brief Set if the cursors are visible or not. - * @param[in] visible flag true for visible - */ - void SetCursorVisibility( bool visible ); - - /** - * @brief Display cursor - * @param[in] nthChar position in text string to display cursor - */ - void DrawCursor( const std::size_t nthChar = 0 ); - - /** - * Sets alternate cursor enable state - * @see SetCursorVisibility - * alternate cursor will only be visible if both SetCursorVisiblity - * and cursor enabled have been set to true. - */ - void SetAltCursorEnabled( bool enabled ); - - /** - * @brief Set the image to be used for the regular left to right cursor - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - * @param[in] border The nine patch border for the image. - */ - void SetCursorImage( Image image, const Vector4& border ); - - /** - * @brief Set the image to be used for the Right to Left cursor - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - * @param[in] border The nine patch border for the image. - */ - void SetRTLCursorImage( Image image, const Vector4& border ); - - /** - * @brief Creates a cursor from the supplied image and nine patch border. - * @param[in] cursorImage the image to be used for the cursor. - * @param[in] border the nine patch border corresponding to the supplied image. - * @paran[in] cursorName actor name for cursor - * @return the image actor to be used as the cursor. - */ - ImageActor CreateCursor( Image cursorImage, const Vector4& border, const std::string& cursorName ); - - /** - * @brief Creates a regular and Right-To-Left cursor and parents them to give target Actor - * @param[in] targetParent target Actor - */ - void CreateCursors( Actor targetParent ); - - /** - * @Brief Returns the cursor size at a given position in the text. - * @return Size the size of the cursor - */ - Size GetCursorSizeAt( std::size_t positionWithinTextToGetCursorSize ); - - /** - * @brief Start a timer to signal cursor to blink. - */ - void StartCursorBlinkTimer(); - - /** - * @brief Stop the timer signalling the cursor to blink. - */ - void StopCursorBlinkTimer(); - - /** - * @brief Callback when handle timer ticks. - * - * Cursor should become visible/invisible to simulate blinking. - * - * @return True if the timer should be keep running. - */ - bool OnCursorBlinkTimerTick(); - - /* Selection Highlight */ - - /** - * @brief Updates mesh data for selection highlight depending on handle positions and displays it. - */ - void ShowUpdatedHighlight(); - - /** - * @brief Creates the Highlight used for selection - * - * @param[in] parent target actor in which the handles should be added to. - */ - void CreateHighlight( Actor parent ); - - /** - * @brief Remove Highlight actor from it's parent - */ - void RemoveHighlight(); - - /** - * @brief Set the visibility of the Highlight - * - * @param[in] visibility True to show and False to hide. - */ - void HighlightVisibility( bool visiblility ); - - /* Boundary Property Notifications when handle exceed bounding box*/ - - /** - * @brief PropertyNotification Callback when left boundary exceeded so handle can be flipped. - * - * @param[in] source PropertyNotification - */ - void OnLeftBoundaryExceeded( PropertyNotification& source ); - /** - * @brief PropertyNotification Callback when within left boundary so handle can be flipped back. - * - * @param[in] source PropertyNotification - */ - void OnReturnToLeftBoundary( PropertyNotification& source ); - /** - * @brief PropertyNotification Callback when right boundary exceeded so handle can be flipped. - * - * @param[in] source PropertyNotification - */ - void OnRightBoundaryExceeded( PropertyNotification& source ); - /** - * @brief PropertyNotification Callback when within right boundary so handle can be flipped back. - * - * @param[in] source PropertyNotification - */ - void OnReturnToRightBoundary( PropertyNotification& source ); - - /** - * @brief PropertyNotification Callbacks for hiding handle one when it exceeds boundary. - * - * @param[in] source PropertyNotification - */ - void OnHandleOneLeavesBoundary( PropertyNotification& source ); - /** - * @brief PropertyNotification Callbacks for showing hidden handle one when returns within boundary - * - * @param[in] source PropertyNotification - */ - void OnHandleOneWithinBoundary( PropertyNotification& source ); - /** - * @brief PropertyNotification Callbacks for hiding handle two it when exceeds boundary. - * - * @param[in] source PropertyNotification - */ - void OnHandleTwoLeavesBoundary( PropertyNotification& source ); - /** - * @brief PropertyNotification Callbacks for showing hidden handle two when returns within boundary - * - * @param[in] source PropertyNotification - */ - void OnHandleTwoWithinBoundary( PropertyNotification& source ); - - /** - * @brief Set up property notifications on the position of the handles to facilitate flipping and hiding when at screen boundary. - */ - void SetUpHandlePropertyNotifications(); - - // Cut & Paste Pop-up - - /** - * @brief Calculate positioning of PopUp relative to handles - * @return Actual position of PopUp - */ - Vector3 PositionOfPopUpRelativeToSelectionHandles( ); - - /** - * @brief Calculate alternative position of PopUp relative to handles when can it not be displayed in the default upper position. - * @return Actual position of PopUp - */ - Vector3 AlternatePopUpPositionRelativeToSelectionHandles(); - - /** - * @brief Calculate positioning of PopUp relative to cursor - * @return Actual position of PopUp - */ - Vector3 PositionOfPopUpRelativeToCursor(); - - /** - * @brief Calculate alternative position of PopUp relative to cursor when can not be displayed in normal upper position. - * @return Actual position of PopUp - */ - Vector3 AlternatePopUpPositionRelativeToCursor(); - - /** - * @brief Calculate positioning of PopUp relative to GrabHandle - * @return Actual position of PopUp - */ - Vector3 PositionOfPopUpRelativeToGrabHandle(); - - /** - * @brief Show the PopUp in the provided target - * @param[in] target target actor in which the PopUp should be added to. - */ - void ShowPopUp( Actor target ); - - /** - * @brief Show PopUp in previously set Target. - * @pre Must have previously called ShopPopUp( Actor target ) otherwise PopUp will not be shown. - */ - void ShowPopUp(); - - /** - * @brief Create and Show Cut Copy Paste PopUp - */ - void ShowPopupCutCopyPaste(); - - /** - * @brief Hide PopUp - * @param[in] animate Animate or just hide instantly, default is true - * @param[in] signalFinished Signal when finished, default is true - */ - void HidePopUp( bool animate=true, bool signalFinished=true ); - - /** - * @brief Adds a popup option. - * @brief Creates popup frame if not already created. - * @param[in] name The unique name for this option. - * @param[in] caption The caption (label) for this option - * @param[in] icon the image icon to be displayed for this option - * @param[in] finalOption Flag to indicate that this is the final option. - * (set to true on the last option you add) - */ - void AddPopupOption(const std::string& name, const std::string& caption, const Image icon, bool finalOption = false); - - /** - * @brief Removes popup, and its options. - */ - void ClearPopup(); - - /** - * @brief PropertyNotification Callbacks for flipping PopUp when exceeds boundary. - * @param[in] source PropertyNotification - */ - void PopUpLeavesVerticalBoundary( PropertyNotification& source ); - - /** - * @brief Setup position notifications when PopUp exceeds boundary - */ - void SetUpPopUpPositionNotifications( ); - - /** - * @brief Callback for when a button is pressed in popup panel - * @param[in] button handle to the button pressed. - * @return bool consummation - */ - bool OnPopupButtonPressed( Toolkit::Button button ); - - // Decoration positioning during scrolling - - /** - * @brief Updates the position of the decorations when Text is scrolled. - * - * @param[in] textView Handle of the text-view. - * @param[in] scrollPosition The difference with the previous scroll position. - */ - void TextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ); - - /** - * @brief Creates and starts a timer to scroll the text when handles are close to the edges of the text-input. - * - * It only starts the timer if it's already created. - */ - void StartScrollTimer(); - - /** - * @brief Stops the timer used to scroll the text. - */ - void StopScrollTimer(); - - /** - * @brief Scroll Text according to handle position - * @param[in out] handlePosition handle position within character string - * @param[in] actual vector position of handle - * @return updated actual vector position of handle - */ - Vector3 ScrollRelativeToHandle( std::size_t& handlePosition, Vector3& actualHandlePosition ); - - /** - * @brief Callback called by the timer used to scroll the text. - * - * It calculates and sets a new scroll position. - */ - bool OnScrollTimerTick(); - - // Text Selection - - /** - * @brief Function to get Text selected between the 2 selection handles. - * @return StyledTextArray an array of - */ - MarkupProcessor::StyledTextArray GetSelectedText(); - -private: - - /** - * @brief Copy Constructor - * @param[in] decorator - * Undefined/Hidden. - */ - Decorator(const Decorator& decorator); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - Decorator& operator=(const Decorator& rhs); - -public: - - typedef Signal< bool( Toolkit::Button ) > PressedSignal; - typedef Signal< void () > CursorPositionedSignal; - /** - * @brief Signal emitted when the button is touched. - * This is relayed from the PopUp class. It enables the owner of the Decorator to act on the PopUp button press. - */ - PressedSignal& PopUpButtonPressedSignal(); - - /** - * @brief Signal emitted when the cursor is repositioned - * @param[in] cursor the new cursor position - */ - CursorPositionedSignal& CursorRePositionedSignal(); - -private: - - Vector4 mBoundingRectangleWorldCoordinates; - - TextViewCharacterPositioning& mTextViewCharacterPositioning; - - TextInputHandles mTextInputHandles; - - TextInputTextStyle& mTextStyle; - - Vector3 mSelectionHandleOneActualPosition; // Actual x y position of handle - Vector3 mSelectionHandleTwoActualPosition; // Actual x y position of handle - std::size_t mSelectionHandleOnePosition; // Position of handle along the string of text - std::size_t mSelectionHandleTwoPosition; // Position of handle along the string of text - - TextInputPopupNew mPopUpPanel; // PopUp used for Cut Cpoy and Paste - Actor mPopUpTarget; // Target Actor to parent PopUp - - Vector3 mActualGrabHandlePosition; // Actual position of grab handle, this might not be snapped to a character - std::size_t mGrabHandlePosition; // Position of grab handle along the string of text - Vector3 mCurrentHandlePosition; - - std::size_t mCursorPosition; // Current cursor position within the text string - ImageActor mCursor; // Cursor overlayed on Text to show where new text will be inserted - ImageActor mCursorRTL; // Right To Left Cursor overlayed on Text (where new RTL text would be inserted) - Animation mCursorAnimation; // Animation for cursor blinking. - Timer mCursorBlinkTimer; // Timer to signal cursor to blink - - Vector2 mScrollDisplacement; // How much to scroll by - Timer mScrollTimer; // Timer to scroll text over a period of time not all in one update. - - TextHighlight mTextHighlight; // Holds data required to construct the highlight - - PanGestureDetector mPanGestureDetector; - - PressedSignal mPopUpButtonPressedSignal; // Signal emitted when a button within the popup is pressed. - CursorPositionedSignal mCursorRePositionedSignal; // Signal emitted when a button when cursor position is changed. - - bool mCursorBlinkStatus:1; // \e true shows the cursor, \e false hides it. - bool mCursorVisibility:1; // Should cursor be visible - bool mCursorRTLEnabled:1; // Enable state of Alternate RTL Cursor (need to keep track of this as it's not always enabled) - bool mIsGrabHandleInScrollArea:1; // Whether the grab handle is inside the boundaries of the text-input. - bool mIsCursorInScrollArea:1; // Whether the cursor is inside the boundaries of the text-input. - bool mGrabHandleVisibility:1; // Should grab handle be visible - bool mGrabHandleEnabled:1; // Flag to enable the grab handle instead of the default magnifier. -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_DECORATOR_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-handles-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-handles-impl.cpp deleted file mode 100644 index aa5ca7d..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-handles-impl.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -using namespace Dali; - -namespace -{ -const char* const DEFAULT_SELECTION_HANDLE_ONE( DALI_IMAGE_DIR "text-input-selection-handle-left.png" ); -const char* const DEFAULT_SELECTION_HANDLE_TWO( DALI_IMAGE_DIR "text-input-selection-handle-right.png" ); -const char* const DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" ); -const char* const DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" ); - -const char* const DEFAULT_GRAB_HANDLE( DALI_IMAGE_DIR "insertpoint-icon.png" ); - -const Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SCALE( 1.5f, 1.5f, 1.0f ); -const Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SCALE( 1.5f, 2.0f, 1.0f ); - -const char* const SELECTION_GRAB_AREA_ONE( "SelectionHandleOneGrabArea"); -const char* const SELECTION_GRAB_AREA_TWO( "SelectionHandleTwoGrabArea"); -const char* const GRABHANDLE_GRAB_AREA( "GrabHandleGrabArea"); - -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "TEXT_INPUT_HANDLES" ); -#endif - -Actor CreateGrabArea( const std::string& name, const Vector3& relativeScale ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: CreateGrabArea\n" ); - - Actor handleGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move - handleGrabArea.SetName( name ); - handleGrabArea.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); - handleGrabArea.SetSizeModeFactor( relativeScale ); - handleGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - - return handleGrabArea; -} - -ImageActor CreateHandle( const Vector3& anchorPoint, const Image& handleImage, const std::string& name ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: CreateSelectionHandle\n" ); - - ImageActor selectionHandle = ImageActor::New( handleImage ); - selectionHandle.SetName( name ); - selectionHandle.SetAnchorPoint( anchorPoint ); - selectionHandle.SetDrawMode( DrawMode::OVERLAY ); // ensure handle above text - - return selectionHandle; -} -} - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -// Default constructor -TextInputHandles::TextInputHandles(): - mSelectionHandleOne(), - mSelectionHandleTwo(), - mSelectionHandleOneOffset( Vector3::ZERO ), - mSelectionHandleTwoOffset( Vector3::ZERO ), - mSelectionHandleOneCoordinatePosition( Vector3::ZERO ), - mSelectionHandleTwoCoordinatePosition( Vector3::ZERO ), - mSelectionHandleOneStringPosition( 0 ), - mSelectionHandleTwoStringPosition( 0 ), - mIsSelectionHandleOneFlipped( false ), - mIsSelectionHandleTwoFlipped( false ) -{ -} - -TextInputHandles::~TextInputHandles() -{ -} - -void TextInputHandles::CreateSelectionHandles() -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: CreateSelectionHandles\n" ); - - mSelectionHandleOneImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE ); - mSelectionHandleOneImagePressed = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE_PRESSED ); - mSelectionHandleOne = CreateHandle( AnchorPoint::TOP_RIGHT, mSelectionHandleOneImage, "SelectionHandleOne" ); - mIsSelectionHandleOneFlipped = false; - - mHandleOneGrabArea = CreateGrabArea( SELECTION_GRAB_AREA_ONE, DEFAULT_SELECTION_HANDLE_RELATIVE_SCALE ); - mSelectionHandleOne.Add( mHandleOneGrabArea ); - mHandleOneGrabArea.TouchedSignal().Connect(this, &TextInputHandles::OnSelectionHandleTouched); - -// mTapDetector.Attach( mHandleOneGrabArea ); - - mSelectionHandleTwoImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO ); - mSelectionHandleTwoImagePressed = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO_PRESSED ); - mSelectionHandleTwo = CreateHandle( AnchorPoint::TOP_LEFT, mSelectionHandleTwoImage, "SelectionHandleTwo" ); - mIsSelectionHandleTwoFlipped = false; - - mHandleTwoGrabArea = CreateGrabArea( SELECTION_GRAB_AREA_TWO, DEFAULT_SELECTION_HANDLE_RELATIVE_SCALE ); - mSelectionHandleTwo.Add( mHandleTwoGrabArea ); - mHandleTwoGrabArea.TouchedSignal().Connect(this, &TextInputHandles::OnSelectionHandleTouched); - - // mTapDetector.Attach( mHandleTwoGrabArea ); -} - -void TextInputHandles::DestorySelectionHandles() -{ - if ( mSelectionHandleOne && mSelectionHandleTwo) - { - mSelectionHandleOne.Unparent(); - mSelectionHandleTwo.Unparent(); - mSelectionHandleOneImagePressed.Reset(); - mSelectionHandleOneImage.Reset(); - mSelectionHandleTwoImagePressed.Reset(); - mSelectionHandleTwoImage.Reset(); - mSelectionHandleOne.Reset(); - mSelectionHandleTwo.Reset(); - } -} - -void TextInputHandles::SetSelectionHandleOneVisibility( bool visibility ) -{ - if ( mSelectionHandleOne ) - { - mSelectionHandleOne.SetVisible( visibility ); - } -} - -void TextInputHandles::SetSelectionHandleTwoVisibility( bool visibility ) -{ - if ( mSelectionHandleTwo ) - { - mSelectionHandleTwo.SetVisible( visibility ); - } -} - -void TextInputHandles::AttachSelectionHandlesToGivenPanGesture( PanGestureDetector& panGestureDetector ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: AttachSelectionHandlesToGivenPanGesture\n" ); - - panGestureDetector.Attach( mHandleOneGrabArea ); - panGestureDetector.Attach( mHandleTwoGrabArea ); -} - -void TextInputHandles::AttachSelectionHandlesToGivenTapDetector(TapGestureDetector& tapGestureDetector ) -{ - tapGestureDetector.Attach( mHandleOneGrabArea ); - tapGestureDetector.Attach( mHandleTwoGrabArea ); -} - -void TextInputHandles::AttachGrabHandleToGivenPanGesture( PanGestureDetector& panGestureDetector ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: AttachGrabHandleToGivenPanGesture\n" ); - - panGestureDetector.Attach( mGrabHandleGrabArea ); -} - -Actor TextInputHandles::GetSelectionHandleOne() -{ - return mSelectionHandleOne; -} - -Actor TextInputHandles::GetSelectionHandleTwo() -{ - return mSelectionHandleTwo; -} - -bool TextInputHandles::OnSelectionHandleTouched(Dali::Actor actor, const TouchEvent& touch) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: OnSelectionHandleTouched\n" ); - - Image pressedImage; - Image normalImage; - - ImageActor handleTouched = ImageActor::DownCast( actor.GetParent() ); // Hit actor would be the GrabArea hence get parent. - - if ( handleTouched == mSelectionHandleOne ) - { - pressedImage = mSelectionHandleOneImagePressed; - normalImage = mSelectionHandleOneImage; - } - else - { - pressedImage = mSelectionHandleTwoImagePressed; - normalImage = mSelectionHandleTwoImage; - } - - if (touch.GetPoint(0).state == TouchPoint::Down) - { - handleTouched.SetImage( pressedImage ); - } - else if (touch.GetPoint(0).state == TouchPoint::Up ) - { - handleTouched.SetImage( normalImage ); - } - return false; -} - -// Grab handle - -Actor TextInputHandles::GetGrabHandle() -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: GetGrabHandle\n" ); - - return mGrabHandle; -} - -void TextInputHandles::CreateGrabHandle() -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: CreateGrabHandle\n" ); - - if ( !mGrabHandle ) - { - if ( !mGrabHandleImage ) - { - mGrabHandleImage = ResourceImage::New( DEFAULT_GRAB_HANDLE ); - } - - mGrabHandle = CreateHandle( AnchorPoint::TOP_CENTER, mGrabHandleImage, "GrabHandle" ); - mGrabHandleGrabArea = CreateGrabArea( GRABHANDLE_GRAB_AREA, DEFAULT_GRAB_HANDLE_RELATIVE_SCALE ); - mGrabHandle.Add( mGrabHandleGrabArea ); - } -} - -void TextInputHandles::DestoryGrabHandle() -{ - if ( mGrabHandle ) - { - mGrabHandle.Unparent(); - mGrabHandleImage.Reset(); - mGrabHandle.Reset(); - } -} - -void TextInputHandles::SetGrabHandleImage( Dali::Image image ) -{ - if ( mGrabHandle ) - { - mGrabHandleImage = image; - mGrabHandle.SetImage( mGrabHandleImage ); - } -} - -void TextInputHandles::SetGrabHandleVisibility( bool visibility ) -{ - DALI_LOG_INFO(gLogFilter, Debug::Verbose, "TextInputHandles: SetGrabHandleVisibility (%s) \n", ( visibility )?"true":"false" ); - - if ( mGrabHandle ) - { - mGrabHandle.SetVisible( visibility ); - } -} - -} // Internal - -} // namespace Toolkit - -} // namespace Dali - diff --git a/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h b/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h deleted file mode 100644 index c5f9013..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-handles-impl.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__ - -/* - * Copyright (c) 2014 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 -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ -/** - * Class to create handles and alter their visualisation. - * Not responsible for positioning. - */ - -class TextInputHandles : public ConnectionTracker -{ - -public: - - /** - * Default constructor - */ - TextInputHandles(); - - /** - * Destructor - */ - ~TextInputHandles(); - - /** - * Create the selection handles - */ - void CreateSelectionHandles(); - - /** - * Un-parents the Selection Handles and resets their Image Actors - */ - void DestorySelectionHandles(); - - /** - * Set the Actor visibility on Selection Handle One - * @param[in] visibility visibility flag - */ - void SetSelectionHandleOneVisibility( bool visibility ); - - /** - * Set the Actor visibility on Selection Handle Two - * @param[in] visibility visibility flag - */ - void SetSelectionHandleTwoVisibility( bool visibility ); - - /** - * Attach the two selection handles to the pan gesture detector - * @param[in] panGestureDetector the PanGestureDetector to attach to - */ - void AttachSelectionHandlesToGivenPanGesture(PanGestureDetector& panGestureDetector ); - - /** - * Attach the two selection handles to the tap gesture detector - * @param[in] tapGestureDetector the TapGestureDetector to attach to - */ - void AttachSelectionHandlesToGivenTapDetector(TapGestureDetector& tapGestureDetector ); - - /** - * Attach the grab handle to the pan gesture detector - * @param[in] panGestureDetector the PanGestureDetector to attach to - */ - void AttachGrabHandleToGivenPanGesture( PanGestureDetector& panGestureDetector ); - - /** - * Get Selection handle one - * @return selection handle actor - */ - Actor GetSelectionHandleOne(); - - /** - * Get Selection handle two - * @return selection handle actor - */ - Actor GetSelectionHandleTwo(); - - /** - * Get the grab handle - * @return grab handle Actor - */ - Actor GetGrabHandle(); - - /** - * Create the grab handle that positions the cursor - * @param[in] image the image to be used. - */ - void CreateGrabHandle(); - - /** - * Removes and Resets GrabHandle - */ - void DestoryGrabHandle(); - - /** - * Set the image to be used as the cursor grab hander - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - */ - void SetGrabHandleImage( Dali::Image image ); - - /** - * Set the Actor visibility on the GrabHandle - * @param[in] visibility visibility flag - */ - void SetGrabHandleVisibility( bool visibility ); - - /* Touch Event Callbacks */ - - /** - * Callback on selection handle touched. - * Sets the image depending if handle in pressed or normal state - * @param[in] actor touched - * @param[in] touch touch event, used to determine if down or up event - */ - bool OnSelectionHandleTouched(Dali::Actor actor, const TouchEvent& touch); - -private: - - /** - * @brief Copy Constructor - * @param[in] handles - * Undefined/Hidden. - */ - TextInputHandles(const TextInputHandles& handles); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - TextInputHandles& operator=(const TextInputHandles& rhs); - -private: - - ImageActor mSelectionHandleOne; // First selection handle used for selecting text to cut&paste - ImageActor mSelectionHandleTwo; // Second selection handle used for selecting text to cut&paste - Actor mHandleOneGrabArea; // Invisible actor that receives pans events for the selection handle. - Actor mHandleTwoGrabArea; // Invisible actor that receives pans events for the selection handle. - - Image mSelectionHandleOneImage; // image used for selection handle one - Image mSelectionHandleOneImagePressed; // image used for selection handle one pressed state - Image mSelectionHandleTwoImage; // image used for selection handle two - Image mSelectionHandleTwoImagePressed; // image used for selection handle two pressed state - - Vector3 mSelectionHandleOneOffset; // Handle One's Offset - Vector3 mSelectionHandleTwoOffset; // Handle Two's Offset - Vector3 mSelectionHandleOneCoordinatePosition; // Actual x y z position of handle - Vector3 mSelectionHandleTwoCoordinatePosition; // Actual x y z position of handle - std::size_t mSelectionHandleOneStringPosition; // Position of handle along the string of text - std::size_t mSelectionHandleTwoStringPosition; // Position of handle along the string of text - - Image mGrabHandleImage; // Image to be used for grab handle - ImageActor mGrabHandle; // Handle used to move cursor for editing - Actor mGrabHandleGrabArea; // invisible actor that receives pans events for the grab handle. - - bool mIsSelectionHandleOneFlipped:1; // Flag to know whether the handle one is flipped or not. - bool mIsSelectionHandleTwoFlipped:1; // Flag to know whether the handle two is flipped or not. -}; - - -} // namespace Internal - - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_HANDLES_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-impl.cpp deleted file mode 100644 index c73804e..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-impl.cpp +++ /dev/null @@ -1,5298 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - -using namespace Dali; - -// Local Data -namespace -{ - -#if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXT_INPUT"); -#endif - -const std::size_t DEFAULT_MAX_SIZE( std::numeric_limits::max() ); // Max possible number -const std::size_t DEFAULT_NUMBER_OF_LINES_LIMIT( std::numeric_limits::max() ); // Max possible number -const Vector3 DEFAULT_SELECTION_HANDLE_SIZE( 51.0f, 79.0f, 0.0f ); // Selection cursor image size -const Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.5f, 2.0f, 1.0f ); -const Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f ); -const Vector4 LIGHTBLUE( 0.07f, 0.41f, 0.59f, 1.0f ); // Used for Selection highlight - -const char* DEFAULT_GRAB_HANDLE( DALI_IMAGE_DIR "insertpoint-icon.png" ); -const char* DEFAULT_SELECTION_HANDLE_ONE( DALI_IMAGE_DIR "text-input-selection-handle-left.png" ); -const char* DEFAULT_SELECTION_HANDLE_TWO( DALI_IMAGE_DIR "text-input-selection-handle-right.png" ); -const char* DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" ); -const char* DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" ); - -const std::size_t CURSOR_BLINK_INTERVAL = 500; ///< Cursor blink interval -const float CHARACTER_THRESHOLD( 2.5f ); ///< the threshold of a line. -const float DISPLAYED_HIGHLIGHT_Z_OFFSET( 0.1f ); ///< 1. Highlight rendered (z-offset). -const float DISPLAYED_TEXT_VIEW_Z_OFFSET( 0.2f ); ///< 2. Text rendered (z-offset). -const float UI_Z_OFFSET( 0.2f ); ///< 3. Text Selection Handles/Cursor z-offset. - -const Vector3 UI_OFFSET(0.0f, 0.0f, UI_Z_OFFSET); ///< Text Selection Handles/Cursor offset. -const Vector3 DEFAULT_HANDLE_ONE_OFFSET(0.0f, -5.0f, 0.0f); ///< Handle One's Offset -const Vector3 DEFAULT_HANDLE_TWO_OFFSET(0.0f, -5.0f, 0.0f); ///< Handle Two's Offset -const float TOP_HANDLE_TOP_OFFSET( 34.0f); ///< Offset between top handle and cutCopyPaste pop-up -const float BOTTOM_HANDLE_BOTTOM_OFFSET(34.0f); ///< Offset between bottom handle and cutCopyPaste pop-up -const float CURSOR_THICKNESS(4.0f); -const Degree CURSOR_ANGLE_OFFSET(2.0f); ///< Offset from the angle of italic angle. -const Vector4 DEFAULT_CURSOR_COLOR(1.0f, 1.0f, 1.0f, 1.0f); - -const char* const NEWLINE = "\n"; - -const TextStyle DEFAULT_TEXT_STYLE; - -const unsigned int SCROLL_TICK_INTERVAL = 50u; -const float SCROLL_THRESHOLD = 10.f; -const float SCROLL_SPEED = 15.f; - -/** - * Selection state enumeration (FSM) - */ -enum SelectionState -{ - SelectionNone, ///< Currently not encountered selected section. - SelectionStarted, ///< Encountered selected section - SelectionFinished ///< Finished selected section -}; - -std::size_t FindVisibleCharacterLeft( std::size_t cursorPosition, const Toolkit::TextView::CharacterLayoutInfoContainer& characterLayoutInfoTable ) -{ - for( Toolkit::TextView::CharacterLayoutInfoContainer::const_reverse_iterator it = characterLayoutInfoTable.rbegin() + characterLayoutInfoTable.size() - cursorPosition, endIt = characterLayoutInfoTable.rend(); - it != endIt; - ++it ) - { - if( ( *it ).mIsVisible ) - { - return --cursorPosition; - } - - --cursorPosition; - } - - return 0u; -} - -std::size_t FindVisibleCharacterRight( std::size_t cursorPosition, const Toolkit::TextView::CharacterLayoutInfoContainer& characterLayoutInfoTable ) -{ - for( Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator it = characterLayoutInfoTable.begin() + cursorPosition, endIt = characterLayoutInfoTable.end(); it < endIt; ++it ) - { - if( ( *it ).mIsVisible ) - { - return cursorPosition; - } - - ++cursorPosition; - } - - return cursorPosition; -} - -/** - * Whether the given position plus the cursor size offset is inside the given boundary. - * - * @param[in] position The given position. - * @param[in] cursorSize The cursor size. - * @param[in] controlSize The given boundary. - * - * @return whether the given position is inside the given boundary. - */ -bool IsPositionInsideBoundaries( const Vector3& position, const Size& cursorSize, const Vector3& controlSize ) -{ - return ( position.x >= -Math::MACHINE_EPSILON_1000 ) && - ( position.x <= controlSize.width + Math::MACHINE_EPSILON_1000 ) && - ( position.y - cursorSize.height >= -Math::MACHINE_EPSILON_1000 ) && - ( position.y <= controlSize.height + Math::MACHINE_EPSILON_1000 ); -} - -/** - * Splits a text in two halves. - * - * If the text's number of characters is odd, firstHalf has one more character. - * - * @param[in] text The text to be split. - * @param[out] firstHalf The first half of the text. - * @param[out] secondHalf The second half of the text. - */ -void SplitText( const Toolkit::MarkupProcessor::StyledTextArray& text, - Toolkit::MarkupProcessor::StyledTextArray& firstHalf, - Toolkit::MarkupProcessor::StyledTextArray& secondHalf ) -{ - firstHalf.clear(); - secondHalf.clear(); - - const std::size_t textLength = text.size(); - const std::size_t half = ( textLength / 2 ) + ( textLength % 2 ); - - firstHalf.insert( firstHalf.end(), text.begin(), text.begin() + half ); - secondHalf.insert( secondHalf.end(), text.begin() + half, text.end() ); -} - -} // end of namespace - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace // Unnamed namespace -{ - -BaseHandle Create() -{ - return Toolkit::TextInput::New(); -} - -// Setup properties, signals and actions using the type-registry. -DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextInput, Toolkit::Control, Create ) - -DALI_PROPERTY_REGISTRATION( TextInput, "highlight-color", VECTOR4, HIGHLIGHT_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-bg-color", VECTOR4, CUT_AND_PASTE_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-pressed-color", VECTOR4, CUT_AND_PASTE_PRESSED_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-border-color", VECTOR4, CUT_AND_PASTE_BORDER_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-icon-color", VECTOR4, CUT_AND_PASTE_ICON_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-icon-pressed-color", VECTOR4, CUT_AND_PASTE_ICON_PRESSED_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-text-color", VECTOR4, CUT_AND_PASTE_TEXT_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-and-paste-text-pressed-color", VECTOR4, CUT_AND_PASTE_TEXT_PRESSED_COLOR ) -DALI_PROPERTY_REGISTRATION( TextInput, "cut-button-position-priority", UNSIGNED_INTEGER, CUT_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "copy-button-position-priority", UNSIGNED_INTEGER, COPY_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "paste-button-position-priority", UNSIGNED_INTEGER, PASTE_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "select-button-position-priority", UNSIGNED_INTEGER, SELECT_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "select-all-button-position-priority", UNSIGNED_INTEGER, SELECT_ALL_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "clipboard-button-position-priority", UNSIGNED_INTEGER, CLIPBOARD_BUTTON_POSITION_PRIORITY ) -DALI_PROPERTY_REGISTRATION( TextInput, "popup-offset-from-text", VECTOR4, POP_UP_OFFSET_FROM_TEXT ) -DALI_PROPERTY_REGISTRATION( TextInput, "cursor-color", VECTOR4, CURSOR_COLOR ) - -DALI_SIGNAL_REGISTRATION( TextInput, "start-input", SIGNAL_START_INPUT ) -DALI_SIGNAL_REGISTRATION( TextInput, "end-input", SIGNAL_END_INPUT ) -DALI_SIGNAL_REGISTRATION( TextInput, "style-changed", SIGNAL_STYLE_CHANGED ) -DALI_SIGNAL_REGISTRATION( TextInput, "max-input-characters-reached", SIGNAL_MAX_INPUT_CHARACTERS_REACHED ) -DALI_SIGNAL_REGISTRATION( TextInput, "toolbar-displayed", SIGNAL_TOOLBAR_DISPLAYED ) -DALI_SIGNAL_REGISTRATION( TextInput, "text-exceed-boundaries", SIGNAL_TEXT_EXCEED_BOUNDARIES ) - -DALI_TYPE_REGISTRATION_END() - -} - -// [TextInput::HighlightInfo] ///////////////////////////////////////////////// - -void TextInput::HighlightInfo::AddQuad( float x1, float y1, float x2, float y2 ) -{ - QuadCoordinates quad(x1, y1, x2, y2); - mQuadList.push_back( quad ); -} - -void TextInput::HighlightInfo::Clamp2D(const Vector2& min, const Vector2& max) -{ - for(std::size_t i = 0;i < mQuadList.size(); i++) - { - QuadCoordinates& quad = mQuadList[i]; - - quad.min.Clamp(min, max); - quad.max.Clamp(min, max); - } // end for -} - -// [TextInput] //////////////////////////////////////////////////////////////// - -Dali::Toolkit::TextInput TextInput::New() -{ - // Create the implementation - TextInputPtr textInput(new TextInput()); - // Pass ownership to CustomActor via derived handle - Dali::Toolkit::TextInput handle(*textInput); - handle.SetName( "TextInput"); - - textInput->Initialize(); - return handle; -} - -TextInput::TextInput() -:Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ), - mState( StateEdit ), - mStyledText(), - mInputStyle(), - mLineHeight( 0.f ), - mDisplayedTextView(), - mStyledPlaceHolderText(), - mMaxStringLength( DEFAULT_MAX_SIZE ), - mNumberOflinesLimit( DEFAULT_NUMBER_OF_LINES_LIMIT ), - mCursorPosition( 0 ), - mActualGrabHandlePosition( 0.0f, 0.0f, 0.0f ), - mIsSelectionHandleOneFlipped( false ), - mIsSelectionHandleTwoFlipped( false ), - mSelectionHandleOneOffset( DEFAULT_HANDLE_ONE_OFFSET ), - mSelectionHandleTwoOffset( DEFAULT_HANDLE_TWO_OFFSET ), - mSelectionHandleOneActualPosition( 0.0f, 0.0f , 0.0f ), - mSelectionHandleTwoActualPosition( 0.0f, 0.0f , 0.0f ), - mSelectionHandleOnePosition( 0 ), - mSelectionHandleTwoPosition( 0 ), - mPreEditString(), - mPreEditStartPosition( 0 ), - mPreEditLength ( 0 ), - mNumberOfSurroundingCharactersDeleted( 0 ), - mTouchStartTime( 0 ), - mTextLayoutInfo(), - mCurrentCopySelecton(), - mPopupPanel(), - mScrollTimer(), - mScrollDisplacement(), - mCurrentHandlePosition(), - mCurrentSelectionId(), - mCurrentSelectionHandlePosition(), - mRequestedSelection( 0, 0 ), - mSelectionHandleFlipMargin( 0.0f, 0.0f, 0.0f, 0.0f ), - mBoundingRectangleWorldCoordinates( 0.0f, 0.0f, 0.0f, 0.0f ), - mClipboard(), - mMaterialColor( LIGHTBLUE ), - mPopupOffsetFromText ( Vector4( 0.0f, TOP_HANDLE_TOP_OFFSET, 0.0f, BOTTOM_HANDLE_BOTTOM_OFFSET ) ), - mOverrideAutomaticAlignment( false ), - mCursorRTLEnabled( false ), - mClosestCursorPositionEOL ( false ), - mCursorBlinkStatus( true ), - mCursorVisibility( false ), - mGrabHandleVisibility( false ), - mIsCursorInScrollArea( true ), - mIsGrabHandleInScrollArea( true ), - mEditModeActive( false ), - mEditOnTouch( true ), - mTextSelection( true ), - mExceedEnabled( true ), - mGrabHandleEnabled( true ), - mIsSelectionHandleFlipEnabled( true ), - mPreEditFlag( false ), - mIgnoreCommitFlag( false ), - mIgnoreFirstCommitFlag( false ), - mSelectingText( false ), - mPreserveCursorPosition( false ), - mSelectTextOnCommit( false ), - mUnderlinedPriorToPreEdit ( false ), - mCommitByKeyInput( false ), - mPlaceHolderSet( false ), - mMarkUpEnabled( false ) -{ - // Updates the line height accordingly with the input style. - UpdateLineHeight(); -} - -TextInput::~TextInput() -{ - StopCursorBlinkTimer(); -} - -// Public - -std::string TextInput::GetText() const -{ - std::string text; - - // Return text-view's text only if the text-input's text is not empty - // in order to not to return the placeholder text. - if( !mStyledText.empty() ) - { - text = mDisplayedTextView.GetText(); - } - - return text; -} - -std::string TextInput::GetMarkupText() const -{ - std::string markupString; - MarkupProcessor::GetMarkupString( mStyledText, markupString ); - - return markupString; -} - -void TextInput::ShowPlaceholderText( const MarkupProcessor::StyledTextArray& stylePlaceHolderText ) -{ - mDisplayedTextView.SetText( stylePlaceHolderText ); - mPlaceHolderSet = true; - mDisplayedTextView.SetScrollPosition( Vector2( 0.0f,0.0f ) ); -} - -void TextInput::SetPlaceholderText( const std::string& placeHolderText ) -{ - // Get the placeholder styled text array from the markup string. - MarkupProcessor::GetStyledTextArray( placeHolderText, mStyledPlaceHolderText, IsMarkupProcessingEnabled() ); - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } -} - -std::string TextInput::GetPlaceholderText() -{ - // Traverses the styled placeholder array getting only the text. - // Note that for some languages a 'character' could be represented by more than one 'char' - - std::string placeholderText; - for( MarkupProcessor::StyledTextArray::const_iterator it = mStyledPlaceHolderText.begin(), endIt = mStyledPlaceHolderText.end(); it != endIt; ++it ) - { - placeholderText.append( (*it).mText.GetText() ); - } - - return placeholderText ; -} - -void TextInput::SetInitialText(const std::string& initialText) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "SetInitialText string[%s]\n", initialText.c_str() ); - - if ( mPreEditFlag ) // If in the pre-edit state and text is being set then discard text being inserted. - { - mPreEditFlag = false; - mIgnoreCommitFlag = true; - } - - SetText( initialText ); - PreEditReset( false ); // Reset keyboard as text changed -} - -void TextInput::SetText(const std::string& initialText) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "SetText string[%s]\n", initialText.c_str() ); - - GetStyledTextArray( initialText, mStyledText, IsMarkupProcessingEnabled() ); - - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - mDisplayedTextView.SetText( mStyledText ); - mPlaceHolderSet = false; - } - - GetTextLayoutInfo(); - - mCursorPosition = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition( mCursorPosition ); - imfManager.SetSurroundingText( initialText ); - imfManager.NotifyCursorPosition(); - } - - if( IsScrollEnabled() ) - { - ScrollTextViewToMakeCursorVisible( Vector3( mTextLayoutInfo.mScrollOffset.x, mTextLayoutInfo.mScrollOffset.y, 0.f ) ); - } - - ShowGrabHandleAndSetVisibility( false ); - - RemoveHighlight(); - - DrawCursor(); - - EmitTextModified(); -} - -void TextInput::SetText( const MarkupProcessor::StyledTextArray& styleText ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "SetText markup text\n" ); - - mDisplayedTextView.SetText( styleText ); - mPlaceHolderSet = false; - - // If text alignment hasn't been manually set by application developer, then we - // automatically determine the alignment based on the content of the text i.e. what - // language the text begins with. - // TODO: This should determine different alignments for each line (broken by '\n') of text. - if(!mOverrideAutomaticAlignment) - { - // Determine bidi direction of first character (skipping past whitespace, numbers, and symbols) - bool leftToRight(true); - - if( !styleText.empty() ) - { - bool breakOut(false); - - for( MarkupProcessor::StyledTextArray::const_iterator textIter = styleText.begin(), textEndIter = styleText.end(); ( textIter != textEndIter ) && ( !breakOut ); ++textIter ) - { - const Text& text = textIter->mText; - - for( std::size_t i = 0; i < text.GetLength(); ++i ) - { - Character character( text[i] ); - if( character.GetCharacterDirection() != Character::Neutral ) - { - leftToRight = ( character.GetCharacterDirection() == Character::LeftToRight ); - breakOut = true; - break; - } - } - } - } - - // Based on this direction, either left or right align text if not manually set by application developer. - mDisplayedTextView.SetTextAlignment( static_cast( - ( leftToRight ? Toolkit::Alignment::HorizontalLeft : Toolkit::Alignment::HorizontalRight) | - Toolkit::Alignment::VerticalTop ) ); - mDisplayedTextView.SetLineJustification( leftToRight ? Toolkit::TextView::Left : Toolkit::TextView::Right); - } - - EmitTextModified(); -} - -void TextInput::SetMaxCharacterLength(std::size_t maxChars) -{ - mMaxStringLength = maxChars; -} - -void TextInput::SetNumberOfLinesLimit(std::size_t maxLines) -{ - DALI_ASSERT_DEBUG( maxLines > 0 ) - - if ( maxLines > 0) - { - mNumberOflinesLimit = maxLines; - } -} - -std::size_t TextInput::GetNumberOfLinesLimit() const -{ - return mNumberOflinesLimit; -} - -std::size_t TextInput::GetNumberOfCharacters() const -{ - return mStyledText.size(); -} - -// Styling -void TextInput::SetMaterialDiffuseColor( const Vector4& color ) -{ - mMaterialColor = color; -} - -const Vector4& TextInput::GetMaterialDiffuseColor() const -{ - return mMaterialColor; -} - -// Signals - -Toolkit::TextInput::InputSignalType& TextInput::InputStartedSignal() -{ - return mInputStartedSignal; -} - -Toolkit::TextInput::InputSignalType& TextInput::InputFinishedSignal() -{ - return mInputFinishedSignal; -} - -Toolkit::TextInput::InputSignalType& TextInput::CutAndPasteToolBarDisplayedSignal() -{ - return mCutAndPasteToolBarDisplayed; -} - -Toolkit::TextInput::StyleChangedSignalType& TextInput::StyleChangedSignal() -{ - return mStyleChangedSignal; -} - -Toolkit::TextInput::TextModifiedSignalType& TextInput::TextModifiedSignal() -{ - return mTextModifiedSignal; -} - -Toolkit::TextInput::MaxInputCharactersReachedSignalType& TextInput::MaxInputCharactersReachedSignal() -{ - return mMaxInputCharactersReachedSignal; -} - -Toolkit::TextInput::InputTextExceedBoundariesSignalType& TextInput::InputTextExceedBoundariesSignal() -{ - return mInputTextExceedBoundariesSignal; -} - -bool TextInput::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) -{ - Dali::BaseHandle handle( object ); - - bool connected( true ); - Toolkit::TextInput textInput = Toolkit::TextInput::DownCast( handle ); - - if( 0 == strcmp( signalName.c_str(), SIGNAL_START_INPUT ) ) - { - textInput.InputStartedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_END_INPUT ) ) - { - textInput.InputFinishedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_STYLE_CHANGED ) ) - { - textInput.StyleChangedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_MAX_INPUT_CHARACTERS_REACHED ) ) - { - textInput.MaxInputCharactersReachedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_TOOLBAR_DISPLAYED ) ) - { - textInput.CutAndPasteToolBarDisplayedSignal().Connect( tracker, functor ); - } - else if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_EXCEED_BOUNDARIES ) ) - { - textInput.InputTextExceedBoundariesSignal().Connect( tracker, functor ); - } - else - { - // signalName does not match any signal - connected = false; - } - - return connected; -} - -void TextInput::SetEditable(bool editMode, bool setCursorOnTouchPoint, const Vector2& touchPoint) -{ - if(editMode) - { - // update line height before calculate the actual position. - UpdateLineHeight(); - - if(!mEditModeActive) - { - if( setCursorOnTouchPoint ) - { - // Sets the cursor position for the given touch point. - ReturnClosestIndex( touchPoint, mCursorPosition ); - - // Creates the grab handle. - if( IsGrabHandleEnabled() ) - { - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition(mCursorPosition); - - CreateGrabHandle(); - - mActualGrabHandlePosition.x = cursorPosition.x; // Set grab handle to be at the cursor position - mActualGrabHandlePosition.y = cursorPosition.y; // Set grab handle to be at the cursor position - mGrabHandle.SetPosition( mActualGrabHandlePosition + UI_OFFSET ); - ShowGrabHandleAndSetVisibility( true ); - - // Scrolls the text-view if needed. - if( IsScrollEnabled() ) - { - ScrollTextViewToMakeCursorVisible( cursorPosition ); - } - } - } - else - { - mCursorPosition = mStyledText.size(); // Initially set cursor position to end of string. - } - } - - StartEditMode(); - } - else - { - EndEditMode(); - } -} - -bool TextInput::IsEditable() const -{ - return mEditModeActive; -} - -void TextInput::SetEditOnTouch( bool editOnTouch ) -{ - mEditOnTouch = editOnTouch; -} - -bool TextInput::IsEditOnTouch() const -{ - return mEditOnTouch; -} - -void TextInput::SetTextSelectable( bool textSelectable ) -{ - mTextSelection = textSelectable; -} - -bool TextInput::IsTextSelectable() const -{ - return mTextSelection; -} - -bool TextInput::IsTextSelected() const -{ - return false; -} - -void TextInput::DeSelectText() -{ - RemoveHighlight(); - HidePopup(); - CursorUpdate(); -} - -void TextInput::SetGrabHandleImage(Dali::Image image ) -{ - if (image) - { - CreateGrabHandle(image); - } -} - -void TextInput::SetCursorImage(Dali::Image image, const Vector4& border ) -{ - DALI_ASSERT_DEBUG ( image && "Create cursor image invalid") - - if ( image ) - { - mCursor.SetImage( image ); - mCursor.SetNinePatchBorder( border ); - } -} - -Vector3 TextInput::GetSelectionHandleSize() -{ - return DEFAULT_SELECTION_HANDLE_SIZE; -} - -void TextInput::SetRTLCursorImage(Dali::Image image, const Vector4& border ) -{ - DALI_ASSERT_DEBUG ( image && "Create cursor image invalid") - - if ( image ) - { - mCursorRTL.SetImage( image); - mCursorRTL.SetNinePatchBorder( border ); - } -} - -void TextInput::EnableGrabHandle(bool toggle) -{ - // enables grab handle with will in turn de-activate magnifier - mGrabHandleEnabled = toggle; -} - -bool TextInput::IsGrabHandleEnabled() -{ - // if false then magnifier will be shown instead. - return mGrabHandleEnabled; -} - -void TextInput::EnableSelectionHandleFlip( bool toggle ) -{ - // Deprecated function. To be removed. - mIsSelectionHandleFlipEnabled = toggle; -} - -bool TextInput::IsSelectionHandleFlipEnabled() -{ - // Deprecated function, To be removed. Returns true as handle flipping always enabled by default so handles do not exceed screen. - return true; -} - -void TextInput::SetSelectionHandleFlipMargin( const Vector4& margin ) -{ - // Deprecated function, now just stores margin for retreival, remove completely once depricated Public API removed. - Vector3 textInputSize = mDisplayedTextView.GetCurrentSize(); - const Vector4 flipBoundary( -margin.x, -margin.y, textInputSize.width + margin.z, textInputSize.height + margin.w ); - - mSelectionHandleFlipMargin = margin; -} - -void TextInput::SetBoundingRectangle( const Rect& boundingRectangle ) -{ - // Convert to world coordinates and store as a Vector4 to be compatiable with Property Notifications. - Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); - - const float originX = boundingRectangle.x - 0.5f * stageSize.width; - const float originY = boundingRectangle.y - 0.5f * stageSize.height; - - const Vector4 boundary( originX, - originY, - originX + boundingRectangle.width, - originY + boundingRectangle.height ); - - mBoundingRectangleWorldCoordinates = boundary; -} - -const Rect TextInput::GetBoundingRectangle() const -{ - Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); - - const float originX = mBoundingRectangleWorldCoordinates.x + 0.5f * stageSize.width; - const float originY = mBoundingRectangleWorldCoordinates.y + 0.5f * stageSize.height; - - RectboundingRect( originX, originY, mBoundingRectangleWorldCoordinates.z - mBoundingRectangleWorldCoordinates.x, mBoundingRectangleWorldCoordinates.w - mBoundingRectangleWorldCoordinates.y); - - return boundingRect; -} - -const Vector4& TextInput::GetSelectionHandleFlipMargin() -{ - return mSelectionHandleFlipMargin; -} - -void TextInput::SetTextColor( const Vector4& color ) -{ - mDisplayedTextView.SetColor( color ); -} - -void TextInput::SetActiveStyle( const TextStyle& style, const TextStyle::Mask mask ) -{ - if( style != mInputStyle ) - { - // different style. - bool emitSignal = false; - - // mask: modify style according to mask, if different emit signal. - const TextStyle oldInputStyle( mInputStyle ); - - // Copy the new style. - mInputStyle.Copy( style, mask ); - - // if style has changed, emit signal. - if( oldInputStyle != mInputStyle ) - { - emitSignal = true; - } - - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - // Changing font point size will require the cursor to be re-sized - DrawCursor(); - - if( emitSignal ) - { - EmitStyleChangedSignal(); - } - } -} - -void TextInput::ApplyStyle( const TextStyle& style, const TextStyle::Mask mask ) -{ - if ( IsTextSelected() ) - { - const std::size_t begin = std::min(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - const std::size_t end = std::max(mSelectionHandleOnePosition, mSelectionHandleTwoPosition) - 1; - - if( !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() ) - { - ApplyStyleToRange(style, mask, mTextLayoutInfo.mCharacterLogicalToVisualMap[begin], mTextLayoutInfo.mCharacterLogicalToVisualMap[end]); - } - - // Keeps the old style to be compared with the new one. - const TextStyle oldInputStyle( mInputStyle ); - - // Copy only those parameters from the style which are set in the mask. - mInputStyle.Copy( style, mask ); - - if( mInputStyle != oldInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } -} - -void TextInput::ApplyStyleToAll( const TextStyle& style, const TextStyle::Mask mask ) -{ - if( !mStyledText.empty() ) - { - ApplyStyleToRange( style, mask, 0, mStyledText.size() - 1 ); - } -} - -TextStyle TextInput::GetStyleAtCursor() const -{ - TextStyle style; - - if ( !mStyledText.empty() && ( mCursorPosition > 0 ) ) - { - DALI_ASSERT_DEBUG( ( 0 <= mCursorPosition-1 ) && ( mCursorPosition-1 < mStyledText.size() ) ); - style = mStyledText.at( mCursorPosition-1 ).mStyle; - } - else // No text. - { - style = mInputStyle; - - if ( mInputStyle.GetFontPointSize() < Math::MACHINE_EPSILON_1000 ) - { - Dali::Font defaultFont = Dali::Font::New(); - style.SetFontPointSize( PointSize( defaultFont.GetPointSize()) ); - } - } - - return style; -} - -TextStyle TextInput::GetStyleAt( std::size_t position ) const -{ - DALI_ASSERT_DEBUG( ( 0 <= position ) && ( position <= mStyledText.size() ) ); - - if( position >= mStyledText.size() ) - { - position = mStyledText.size() - 1; - } - - return mStyledText.at( position ).mStyle; -} - -void TextInput::SetTextAlignment( Toolkit::Alignment::Type align ) -{ - mDisplayedTextView.SetTextAlignment( align ); - mOverrideAutomaticAlignment = true; -} - -void TextInput::SetTextLineJustification( Toolkit::TextView::LineJustification justification ) -{ - mDisplayedTextView.SetLineJustification( justification ); - mOverrideAutomaticAlignment = true; -} - -void TextInput::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ) -{ - mDisplayedTextView.SetFadeBoundary( fadeBoundary ); -} - -const Toolkit::TextView::FadeBoundary& TextInput::GetFadeBoundary() const -{ - return mDisplayedTextView.GetFadeBoundary(); -} - -Toolkit::Alignment::Type TextInput::GetTextAlignment() const -{ - return mDisplayedTextView.GetTextAlignment(); -} - -void TextInput::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ) -{ - mDisplayedTextView.SetMultilinePolicy( policy ); -} - -Toolkit::TextView::MultilinePolicy TextInput::GetMultilinePolicy() const -{ - return mDisplayedTextView.GetMultilinePolicy(); -} - -void TextInput::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ) -{ - mDisplayedTextView.SetWidthExceedPolicy( policy ); -} - -Toolkit::TextView::ExceedPolicy TextInput::GetWidthExceedPolicy() const -{ - return mDisplayedTextView.GetWidthExceedPolicy(); -} - -void TextInput::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ) -{ - mDisplayedTextView.SetHeightExceedPolicy( policy ); -} - -Toolkit::TextView::ExceedPolicy TextInput::GetHeightExceedPolicy() const -{ - return mDisplayedTextView.GetHeightExceedPolicy(); -} - -void TextInput::SetExceedEnabled( bool enable ) -{ - mExceedEnabled = enable; -} - -bool TextInput::GetExceedEnabled() const -{ - return mExceedEnabled; -} - -void TextInput::SetBackground(Dali::Image image ) -{ - // TODO Should add this function and add public api to match. -} - -bool TextInput::OnTouchEvent(const TouchEvent& event) -{ - return false; -} - -bool TextInput::OnKeyEvent(const KeyEvent& event) -{ - switch( event.state ) - { - case KeyEvent::Down: - { - return OnKeyDownEvent(event); - } - break; - - case KeyEvent::Up: - { - return OnKeyUpEvent(event); - } - break; - - default: - { - return false; - } - break; - } -} - -void TextInput::OnKeyInputFocusGained() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, ">>OnKeyInputFocusGained\n" ); - - mEditModeActive = true; - - mActiveLayer.RaiseToTop(); // Ensure layer holding handles is on top - - mInputStyle = GetStyleAtCursor(); // Inherit style from cursor position - - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - // Connect the signals to use in text input. - VirtualKeyboard::StatusChangedSignal().Connect( this, &TextInput::KeyboardStatusChanged ); - VirtualKeyboard::LanguageChangedSignal().Connect( this, &TextInput::SetTextDirection ); - - // Set the text direction if empty and connect to the signal to ensure we change direction when the language changes. - SetTextDirection(); - - GetTextLayoutInfo(); - - DrawCursor(); - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - Toolkit::TextInput handle( GetOwner() ); - mInputStartedSignal.Emit( handle ); - - ImfManager imfManager = ImfManager::Get(); - - if ( imfManager ) - { - imfManager.EventReceivedSignal().Connect(this, &TextInput::ImfEventReceived); - - // Notify that the text editing start. - imfManager.Activate(); - - // When window gain lost focus, the imf manager is deactivated. Thus when window gain focus again, the imf manager must be activated. - imfManager.SetRestoreAfterFocusLost( true ); - - imfManager.SetCursorPosition( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - - mClipboard = Clipboard::Get(); // Store handle to clipboard - - // Now in edit mode we can accept string to paste from clipboard - ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() ); - if ( notifier ) - { - notifier.ContentSelectedSignal().Connect( this, &TextInput::OnClipboardTextSelected ); - } -} - -void TextInput::OnKeyInputFocusLost() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, ">>OnKeyInputFocusLost\n" ); - - if( mPreEditFlag ) - { - // If key input focus is lost, it removes the - // underline from the last pre-edit text. - RemovePreEditStyle(); - const std::size_t numberOfCharactersDeleted = DeletePreEdit(); - InsertAt( mPreEditString, mPreEditStartPosition, numberOfCharactersDeleted ); - EmitTextModified(); - } - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - // The text editing is finished. Therefore the imf manager don't have restore activation. - imfManager.SetRestoreAfterFocusLost( false ); - - // Notify that the text editing finish. - imfManager.Deactivate(); - - imfManager.EventReceivedSignal().Disconnect(this, &TextInput::ImfEventReceived); - } - // Disconnect signal used the text input. - VirtualKeyboard::LanguageChangedSignal().Disconnect( this, &TextInput::SetTextDirection ); - - Toolkit::TextInput handle( GetOwner() ); - mInputFinishedSignal.Emit( handle ); - mEditModeActive = false; - mPreEditFlag = false; - RemoveHighlight(); - SetCursorVisibility( false ); - StopCursorBlinkTimer(); - - ShowGrabHandleAndSetVisibility( false ); - - mClipboard.Reset(); - // No longer in edit mode so do not want to receive string from clipboard - ClipboardEventNotifier notifier( ClipboardEventNotifier::Get() ); - if ( notifier ) - { - notifier.ContentSelectedSignal().Disconnect( this, &TextInput::OnClipboardTextSelected ); - } - - Clipboard clipboard = Clipboard::Get(); - if ( clipboard ) - { - clipboard.HideClipboard(); - } -} - -void TextInput::OnControlStageConnection() -{ - Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); - - if ( mBoundingRectangleWorldCoordinates == Vector4::ZERO ) - { - SetBoundingRectangle( Rect( 0.0f, 0.0f, stageSize.width, stageSize.height )); - } -} - -void TextInput::CreateActiveLayer() -{ - Actor self = Self(); - mActiveLayer = Layer::New(); - mActiveLayer.SetName ( "ActiveLayerActor" ); - - mActiveLayer.SetAnchorPoint( AnchorPoint::CENTER); - mActiveLayer.SetParentOrigin( ParentOrigin::CENTER); - mActiveLayer.SetPositionInheritanceMode( USE_PARENT_POSITION ); - - self.Add( mActiveLayer ); - mActiveLayer.RaiseToTop(); -} - -void TextInput::OnInitialize() -{ - CreateTextViewActor(); - - SetUpTouchEvents(); - - // Create 2 cursors (standard LTR and RTL cursor for when text can be added at - // different positions depending on language) - mCursor = CreateCursor(DEFAULT_CURSOR_COLOR); - mCursorRTL = CreateCursor(DEFAULT_CURSOR_COLOR); - - Actor self = Self(); - self.Add( mCursor ); - self.Add( mCursorRTL ); - - mCursorVisibility = false; - - CreateActiveLayer(); // todo move this so layer only created when needed. - - // Assign names to image actors - mCursor.SetName("mainCursor"); - mCursorRTL.SetName("rtlCursor"); -} - -void TextInput::OnControlSizeSet(const Vector3& targetSize) -{ - mDisplayedTextView.SetSize( targetSize ); - GetTextLayoutInfo(); - mActiveLayer.SetSize(targetSize); -} - -void TextInput::OnRelayout( const Vector2& size, RelayoutContainer& container ) -{ - container.Add( mDisplayedTextView, size ); - container.Add( mPopupPanel.GetRootActor(), size ); - - GetTextLayoutInfo(); - - DrawCursor(); -} - -Vector3 TextInput::GetNaturalSize() -{ - Vector3 naturalSize = mDisplayedTextView.GetNaturalSize(); - - if( mEditModeActive && ( Vector3::ZERO == naturalSize ) ) - { - // If the natural is zero, it means there is no text. Let's return the cursor height as the natural height. - naturalSize.height = mLineHeight; - } - - return naturalSize; -} - -float TextInput::GetHeightForWidth( float width ) -{ - float height = mDisplayedTextView.GetHeightForWidth( width ); - - if( mEditModeActive && ( fabsf( height ) < Math::MACHINE_EPSILON_1000 ) ) - { - // If the height is zero, it means there is no text. Let's return the cursor height. - height = mLineHeight; - } - - return height; -} - -/*end of Virtual methods from parent*/ - -// Private Internal methods - -void TextInput::OnHandlePan(Actor actor, const PanGesture& gesture) -{ - switch (gesture.state) - { - case Gesture::Started: - // fall through so code not duplicated - case Gesture::Continuing: - { - if (actor == mGrabArea) - { - SetCursorVisibility( true ); - ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea ); - MoveGrabHandle( gesture.displacement ); - HidePopup(); // Do not show popup whilst handle is moving - } - else if (actor == mHandleOneGrabArea) - { - // the displacement in PanGesture is affected by the actor's rotation. - mSelectionHandleOneActualPosition.x += gesture.displacement.x * mSelectionHandleOne.GetCurrentScale().x; - mSelectionHandleOneActualPosition.y += gesture.displacement.y * mSelectionHandleOne.GetCurrentScale().y; - - MoveSelectionHandle( HandleOne, gesture.displacement ); - - mState = StateDraggingHandle; - HidePopup(); - } - else if (actor == mHandleTwoGrabArea) - { - // the displacement in PanGesture is affected by the actor's rotation. - mSelectionHandleTwoActualPosition.x += gesture.displacement.x * mSelectionHandleTwo.GetCurrentScale().x; - mSelectionHandleTwoActualPosition.y += gesture.displacement.y * mSelectionHandleTwo.GetCurrentScale().y; - - MoveSelectionHandle( HandleTwo, gesture.displacement ); - - mState = StateDraggingHandle; - HidePopup(); - } - } - break; - - case Gesture::Finished: - { - // Revert back to non-pressed selection handle images - if (actor == mGrabArea) - { - mActualGrabHandlePosition = MoveGrabHandle( gesture.displacement ); - SetCursorVisibility( true ); - SetUpPopupSelection(); - ShowPopup(); - } - if (actor == mHandleOneGrabArea) - { - // the displacement in PanGesture is affected by the actor's rotation. - mSelectionHandleOneActualPosition.x += gesture.displacement.x * mSelectionHandleOne.GetCurrentScale().x; - mSelectionHandleOneActualPosition.y += gesture.displacement.y * mSelectionHandleOne.GetCurrentScale().y; - - mSelectionHandleOneActualPosition = MoveSelectionHandle( HandleOne, gesture.displacement ); - - mSelectionHandleOne.SetImage( mSelectionHandleOneImage ); - mState = StateEdit; - ShowPopupCutCopyPaste(); - } - if (actor == mHandleTwoGrabArea) - { - // the displacement in PanGesture is affected by the actor's rotation. - mSelectionHandleTwoActualPosition.x += gesture.displacement.x * mSelectionHandleTwo.GetCurrentScale().x; - mSelectionHandleTwoActualPosition.y += gesture.displacement.y * mSelectionHandleTwo.GetCurrentScale().y; - - mSelectionHandleTwoActualPosition = MoveSelectionHandle( HandleTwo, gesture.displacement ); - - mSelectionHandleTwo.SetImage( mSelectionHandleTwoImage ); - mState = StateEdit; - ShowPopupCutCopyPaste(); - } - } - break; - default: - break; - } -} - -// Stop the flashing animation so easy to see when moved. -bool TextInput::OnPressDown(Dali::Actor actor, const TouchEvent& touch) -{ - if (touch.GetPoint(0).state == TouchPoint::Down) - { - SetCursorVisibility( true ); - StopCursorBlinkTimer(); - } - else if (touch.GetPoint(0).state == TouchPoint::Up) - { - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - } - return false; -} - -// selection handle one -bool TextInput::OnHandleOneTouched(Dali::Actor actor, const TouchEvent& touch) -{ - if (touch.GetPoint(0).state == TouchPoint::Down) - { - mSelectionHandleOne.SetImage( mSelectionHandleOneImagePressed ); - } - else if (touch.GetPoint(0).state == TouchPoint::Up) - { - mSelectionHandleOne.SetImage( mSelectionHandleOneImage ); - } - return false; -} - -// selection handle two -bool TextInput::OnHandleTwoTouched(Dali::Actor actor, const TouchEvent& touch) -{ - if (touch.GetPoint(0).state == TouchPoint::Down) - { - mSelectionHandleTwo.SetImage( mSelectionHandleTwoImagePressed ); - } - else if (touch.GetPoint(0).state == TouchPoint::Up) - { - mSelectionHandleTwo.SetImage( mSelectionHandleTwoImage ); - } - return false; -} - -void TextInput::OnDoubleTap(Dali::Actor actor, const Dali::TapGesture& tap) -{ - // If text exists then select nearest word. - if ( !mStyledText.empty()) - { - HidePopup(); - - ShowGrabHandleAndSetVisibility( false ); - - - if ( mPreEditFlag ) - { - // PreEdit will be committed here without needing a commit from IMF. Remove pre-edit underline and reset flags which - // converts the pre-edit word being displayed to a committed word. - if ( !mUnderlinedPriorToPreEdit ) - { - TextStyle style; - style.SetUnderline( false ); - ApplyStyleToRange( style, TextStyle::UNDERLINE , mPreEditStartPosition, mPreEditStartPosition + mPreEditLength -1 ); - } - mPreEditFlag = false; - mIgnoreCommitFlag = true; // Predictive word interrupted, text displayed will not change, no need to actually commit. - // Reset keyboard and set true so cursor position is preserved. Otherwise cursor position will that of the committed text not new tap location. - PreEditReset( false ); - } - mCursorPosition = 0; - - mTextLayoutInfo.mScrollOffset = mDisplayedTextView.GetScrollPosition(); - ReturnClosestIndex( tap.localPoint, mCursorPosition ); - - std::size_t start = 0; - std::size_t end = 0; - Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end ); - - mCursorPosition = end; // Ensure cursor is positioned at end of selected word - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - - if ( !mStyledText.at(end-1).mText[0].IsWhiteSpace() ) - { - SelectText( start, end ); - ShowPopupCutCopyPaste(); - } - else - { - RemoveHighlight( false ); // Remove highlight but do not auto hide popup - HidePopup( false ); // Hide popup with setting to do auto show. - SetUpPopupSelection( false ); // Set to false so if nearest word is whitespace it will not show cut button. - ShowPopup(); - } - } - else if ( mClipboard && mClipboard.NumberOfItems() ) - { - ShowPopupCutCopyPaste(); - } - - // If no text and clipboard empty then do nothing -} - -// TODO: Change the function name to be more general. -void TextInput::OnTextTap(Dali::Actor actor, const Dali::TapGesture& tap) -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "OnTap mPreEditFlag[%s] mEditOnTouch[%s] mEditModeActive[%s] ", (mPreEditFlag)?"true":"false" - , (mEditOnTouch)?"true":"false" - , (mEditModeActive)?"true":"false"); - - if( mHandleOneGrabArea == actor || mHandleTwoGrabArea == actor ) - { - return; - } - - if( mGrabArea == actor ) - { - if( mPopupPanel.GetState() == TextInputPopup::StateHidden || mPopupPanel.GetState() == TextInputPopup::StateHiding ) - { - SetUpPopupSelection(); - ShowPopup(); - } - - return; - } - - HidePopup(); - RemoveHighlight(); - - mTextLayoutInfo.mScrollOffset = mDisplayedTextView.GetScrollPosition(); - - // Initially don't create the grab handle. - bool createGrabHandle = false; - - if ( !mEditModeActive ) - { - // update line height before calculate the actual position. - UpdateLineHeight(); - - // Only start edit mode if TextInput configured to edit on touch - if ( mEditOnTouch ) - { - // Set the initial cursor position in the tap point. - ReturnClosestIndex(tap.localPoint, mCursorPosition ); - StartEditMode(); - } - } - else - { - // Show the keyboard if it was hidden. - if (!VirtualKeyboard::IsVisible()) - { - VirtualKeyboard::Show(); - } - - // Reset keyboard as tap event has occurred. - // Set true so cursor position is preserved. Otherwise cursor position will that of the committed text not new tap location. - PreEditReset( true ); - - GetTextLayoutInfo(); - - if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) // If string empty we do not need a grab handle. - { - // As already in edit mode, reposition cursor near tap and show grab handle for cursor, if grab handle not enabled then magnifier will be used instead. - - ReturnClosestIndex(tap.localPoint, mCursorPosition ); - - DALI_LOG_INFO( gLogFilter, Debug::General, "mCursorPosition[%u]", mCursorPosition ); - - // Notify keyboard so it can 're-capture' word for predictive text. - // As we have done a reset, is this required, expect IMF keyboard to request this information. - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - const TextStyle oldInputStyle( mInputStyle ); - - mInputStyle = GetStyleAtCursor(); // Inherit style from cursor position - - DrawCursor(); - - // Create the grab handle. - // Grab handle is created later. - createGrabHandle = true; - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } - } - - // Edit mode started after grab handle created to ensure the signal InputStarted is sent last. - // This is used to ensure if selecting text hides the grab handle then this code is run after grab handle is created, - // otherwise the Grab handle will be shown when selecting. - if ( createGrabHandle && IsGrabHandleEnabled() ) - { - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid ); - - if( altPositionValid ) - { - // Check which of the positions is the closest. - if( fabsf( altPosition.x - tap.localPoint.x ) < fabsf( cursorPosition.x - tap.localPoint.x ) ) - { - cursorPosition = altPosition; - } - } - - CreateGrabHandle(); - - mActualGrabHandlePosition.x = cursorPosition.x; // Set grab handle to be at the cursor position - mActualGrabHandlePosition.y = cursorPosition.y; // Set grab handle to be at the cursor position - mGrabHandle.SetPosition( mActualGrabHandlePosition + UI_OFFSET ); - ShowGrabHandleAndSetVisibility( mIsGrabHandleInScrollArea ); - - } -} - -void TextInput::OnLongPress(Dali::Actor actor, const Dali::LongPressGesture& longPress) -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "OnLongPress\n" ); - - // Ignore longpress if in selection mode already - - if(longPress.state == Dali::Gesture::Started) - { - // Start edit mode on long press - if ( !mEditModeActive ) - { - StartEditMode(); - } - - // If text exists then select nearest word. - if ( !mStyledText.empty()) - { - HidePopup(); - - ShowGrabHandleAndSetVisibility( false ); - - - if ( mPreEditFlag ) - { - // PreEdit will be committed here without needing a commit from IMF. Remove pre-edit underline and reset flags which - // converts the pre-edit word being displayed to a committed word. - if ( !mUnderlinedPriorToPreEdit ) - { - TextStyle style; - style.SetUnderline( false ); - ApplyStyleToRange( style, TextStyle::UNDERLINE , mPreEditStartPosition, mPreEditStartPosition + mPreEditLength -1 ); - } - mPreEditFlag = false; - mIgnoreCommitFlag = true; // Predictive word interrupted, text displayed will not change, no need to actually commit. - // Reset keyboard and set true so cursor position is preserved. Otherwise cursor position will that of the committed text not new tap location. - PreEditReset( false ); - } - mCursorPosition = 0; - - mTextLayoutInfo.mScrollOffset = mDisplayedTextView.GetScrollPosition(); - ReturnClosestIndex( longPress.localPoint, mCursorPosition ); - - std::size_t start = 0; - std::size_t end = 0; - Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end ); - - mCursorPosition = end; // Ensure cursor is positioned at end of selected word - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - - SelectText( start, end ); - } - - // if no text but clipboard has content then show paste option, if no text and clipboard empty then do nothing - if ( ( mClipboard && mClipboard.NumberOfItems() ) || !mStyledText.empty() ) - { - ShowPopupCutCopyPaste(); - } - } -} - -void TextInput::OnClipboardTextSelected( ClipboardEventNotifier& notifier ) -{ - const Text clipboardText( notifier.GetContent() ); - PasteText( clipboardText ); - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - ShowGrabHandleAndSetVisibility( false ); - - - HidePopup(); -} - -bool TextInput::OnPopupButtonPressed( Toolkit::Button button ) -{ - mPopupPanel.PressedSignal().Disconnect( this, &TextInput::OnPopupButtonPressed ); - - const std::string& name = button.GetName(); - - if(name == TextInputPopup::OPTION_SELECT_WORD) - { - std::size_t start = 0; - std::size_t end = 0; - Dali::Toolkit::Internal::TextProcessor::FindNearestWord( mStyledText, mCursorPosition, start, end ); - - SelectText( start, end ); - } - else if(name == TextInputPopup::OPTION_SELECT_ALL) - { - SetCursorVisibility(false); - StopCursorBlinkTimer(); - - std::size_t end = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); - std::size_t start = 0; - - SelectText( start, end ); - } - else if(name == TextInputPopup::OPTION_CUT) - { - bool ret = CopySelectedTextToClipboard(); - - if ( ret ) - { - DeleteHighlightedText( true ); - CursorUpdate(); - } - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - HidePopup(); - } - else if(name == TextInputPopup::OPTION_COPY) - { - CopySelectedTextToClipboard(); - - RemoveHighlight(); - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - HidePopup(); - } - else if(name == TextInputPopup::OPTION_PASTE) - { - const Text retrievedString( mClipboard.GetItem( 0 ) ); // currently can only get first item in clip board, index 0; - - PasteText(retrievedString); - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - ShowGrabHandleAndSetVisibility( false ); - - HidePopup(); - } - else if(name == TextInputPopup::OPTION_CLIPBOARD) - { - // In the case of clipboard being shown we do not want to show updated pop-up after hide animation completes - // Hence pass the false parameter for signalFinished. - HidePopup( true, false ); - mClipboard.ShowClipboard(); - } - - return false; -} - -bool TextInput::OnCursorBlinkTimerTick() -{ - // Cursor blinking - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus ); - if ( mCursorRTLEnabled ) - { - mCursorRTL.SetVisible( mCursorVisibility && mIsCursorInScrollArea && mCursorBlinkStatus ); - } - mCursorBlinkStatus = !mCursorBlinkStatus; - - return true; -} - -void TextInput::OnPopupHideFinished(TextInputPopup& popup) -{ - popup.HideFinishedSignal().Disconnect( this, &TextInput::OnPopupHideFinished ); - - // Change Popup menu to Cut/Copy/Paste if text has been selected. -} - -//FIXME this routine needs to be re-written as it contains too many branches. -bool TextInput::OnKeyDownEvent(const KeyEvent& event) -{ - std::string keyName = event.keyPressedName; - std::string keyString = event.keyPressed; - - DALI_LOG_INFO(gLogFilter, Debug::General, "OnKeyDownEvent keyName[%s] KeyString[%s]\n", keyName.c_str(), keyString.c_str() ); - - // Do not consume "Tab" and "Escape" keys. - if(keyName == "Tab" || keyName == "Escape") - { - // Escape key to end the edit mode - EndEditMode(); - - return false; - } - - HidePopup(); // If Pop-up shown then hides it as editing text. - - // Update Flag, indicates whether to update the text-input contents or not. - // Any key stroke that results in a visual change of the text-input should - // set this flag to true. - bool update(false); - - // Whether to scroll text to cursor position. - // Scroll is needed always the cursor is updated and after the pre-edit is received. - bool scroll = false; - - if (keyName == "Return") - { - if ( mNumberOflinesLimit > 1) // Prevents New line character / Return adding an extra line if limit set to 1 - { - bool preEditFlagPreviouslySet( mPreEditFlag ); - - // replaces highlighted text with new line - DeleteHighlightedText( false ); - - mCursorPosition = mCursorPosition + InsertAt( Text( NEWLINE ), mCursorPosition, 0 ); - - // If we are in pre-edit mode then pressing enter will cause a commit. But the commit string does not include the - // '\n' character so we need to ensure that the immediately following commit knows how it occurred. - if ( mPreEditFlag ) - { - mCommitByKeyInput = true; - } - - // If attempting to insert a new-line brings us out of PreEdit mode, then we should not ignore the next commit. - if ( preEditFlagPreviouslySet && !mPreEditFlag ) - { - mPreEditFlag = true; - mIgnoreCommitFlag = false; - } - EmitTextModified(); - update = true; - } - else - { - RemoveHighlight(); - } - } // Return - else if ( keyName == "space" ) - { - - mCursorPosition = mCursorPosition + InsertAt(Text(keyString), mCursorPosition, 0); - - // If we are in pre-edit mode then pressing the space-bar will cause a commit. But the commit string does not include the - // ' ' character so we need to ensure that the immediately following commit knows how it occurred. - if ( mPreEditFlag ) - { - mCommitByKeyInput = true; - } - EmitTextModified(); - update = true; - } // space - else if (keyName == "BackSpace") - { - { - if ( mCursorPosition > 0 ) - { - DeleteCharacter( mCursorPosition ); - update = true; - } - } - EmitTextModified(); - } // BackSpace - else if (keyName == "Right") - { - AdvanceCursor(); - RemoveHighlight(); - } - else if (keyName == "Left") - { - AdvanceCursor(true); - RemoveHighlight(); - } - else // event is a character - { - // Some text may be selected, hiding keyboard causes an empty keystring to be sent, we don't want to delete highlight in this case - if ( !keyString.empty() ) - { - // replaces highlighted text with new character - DeleteHighlightedText( false ); - - // Received key String - mCursorPosition += InsertAt( Text( keyString ), mCursorPosition, 0 ); - update = true; - EmitTextModified(); - } - } - - // If key event has resulted in a change in the text/cursor, then trigger a relayout of text - // as this is a costly operation. - if(update) - { - CursorUpdate(); - } - - if(update || scroll) - { - if( IsScrollEnabled() ) - { - // Calculates the new cursor position (in actor coordinates) - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition ); - - ScrollTextViewToMakeCursorVisible( cursorPosition ); - } - } - - return true; -} - -bool TextInput::OnKeyUpEvent(const KeyEvent& event) -{ - std::string keyName = event.keyPressedName; - std::string keyString = event.keyPressed; - - DALI_LOG_INFO(gLogFilter, Debug::General, "OnKeyUpEvent keyName[%s] KeyString[%s]\n", keyName.c_str(), keyString.c_str() ); - - // The selected text become deselected when the key code is DALI_KEY_BACK. - if( IsTextSelected() && ( keyName == "XF86Stop" || keyName == "XF86Send") ) - { - DeSelectText(); - return true; - } - - return false; -} - -void TextInput::ChooseRtlSelectionHandlePosition( const Vector3& cursorPositionOne, - const Vector3& cursorPositionTwo, - bool altPositionValidOne, - bool altPositionValidTwo, - const Vector3& altPositionOne, - const Vector3& altPositionTwo ) -{ - // TODO VCC Valid for one line. - // Try to place the selection handles. TODO think in something better. Probably need to know the direction of the paragraph. - if( cursorPositionOne != cursorPositionTwo ) - { - if( cursorPositionOne.x < cursorPositionTwo.x ) - { - mSelectionHandleOneActualPosition = cursorPositionOne; - mSelectionHandleTwoActualPosition = cursorPositionTwo; - } - else - { - mSelectionHandleOneActualPosition = cursorPositionTwo; - mSelectionHandleTwoActualPosition = cursorPositionOne; - } - } - else - { - mSelectionHandleOneActualPosition = cursorPositionOne; - if( altPositionValidOne ) - { - if( altPositionOne.x < mSelectionHandleOneActualPosition.x ) - { - mSelectionHandleOneActualPosition = altPositionOne; - } - } - if( altPositionValidTwo ) - { - if( altPositionTwo.x < mSelectionHandleOneActualPosition.x ) - { - mSelectionHandleOneActualPosition = altPositionTwo; - } - } - - mSelectionHandleTwoActualPosition = cursorPositionTwo; - if( altPositionValidTwo ) - { - if( altPositionTwo.x > mSelectionHandleTwoActualPosition.x ) - { - mSelectionHandleTwoActualPosition = altPositionTwo; - } - } - if( altPositionValidOne ) - { - if( altPositionOne.x > mSelectionHandleTwoActualPosition.x ) - { - mSelectionHandleTwoActualPosition = altPositionOne; - } - } - } -} - -void TextInput::OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ) -{ - // Updates the stored scroll position. - mTextLayoutInfo.mScrollOffset = textView.GetScrollPosition(); - - const Vector3& controlSize = GetControlSize(); - Size cursorSize( CURSOR_THICKNESS, 0.f ); - - // Updates the cursor and grab handle position and visibility. - if( mGrabHandle || mCursor ) - { - cursorSize.height = GetRowRectFromCharacterPosition( mCursorPosition ).height; - - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid ); - - if( altPositionValid ) - { - // Check which of the positions is the closest. - if( fabsf( altPosition.x - mActualGrabHandlePosition.x ) < fabsf( cursorPosition.x - mActualGrabHandlePosition.x ) ) - { - cursorPosition = altPosition; - } - } - - mIsCursorInScrollArea = mIsGrabHandleInScrollArea = IsPositionInsideBoundaries( cursorPosition, cursorSize, controlSize ); - - mActualGrabHandlePosition = cursorPosition.GetVectorXY(); - - if( mGrabHandle ) - { - ShowGrabHandle( mGrabHandleVisibility && mIsGrabHandleInScrollArea ); - mGrabHandle.SetPosition( mActualGrabHandlePosition + UI_OFFSET ); - } - - if( mCursor ) - { - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea ); - mCursor.SetPosition( mActualGrabHandlePosition + UI_OFFSET ); - } - } - - // Updates the selection handles and highlighted text position and visibility. - if( mSelectionHandleOne && mSelectionHandleTwo ) - { - Vector3 altPositionOne; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValidOne; // Alternate cursor validity flag. - bool directionRTLOne; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition, directionRTLOne, altPositionOne, altPositionValidOne ); - - Vector3 altPositionTwo; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValidTwo; // Alternate cursor validity flag. - bool directionRTLTwo; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition, directionRTLTwo, altPositionTwo, altPositionValidTwo ); - - // VCC TODO: This method is a hack for one line. - ChooseRtlSelectionHandlePosition( cursorPositionOne, - cursorPositionTwo, - altPositionValidOne, - altPositionValidTwo, - altPositionOne, - altPositionTwo ); - - cursorSize.height = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + mSelectionHandleOnePosition ) ).mSize.height; - const bool isSelectionHandleOneVisible = IsPositionInsideBoundaries( cursorPositionOne, cursorSize, controlSize ); - cursorSize.height = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + mSelectionHandleTwoPosition ) ).mSize.height; - const bool isSelectionHandleTwoVisible = IsPositionInsideBoundaries( cursorPositionTwo, cursorSize, controlSize ); - - mSelectionHandleOne.SetVisible( isSelectionHandleOneVisible ); - mSelectionHandleTwo.SetVisible( isSelectionHandleTwoVisible ); - mSelectionHandleOne.SetPosition( mSelectionHandleOneActualPosition + UI_OFFSET + mSelectionHandleOneOffset ); - mSelectionHandleTwo.SetPosition( mSelectionHandleTwoActualPosition + UI_OFFSET + mSelectionHandleTwoOffset ); - - } -} - -void TextInput::ScrollTextViewToMakeCursorVisible( const Vector3& cursorPosition ) -{ - // Scroll the text to make the cursor visible. - const Size cursorSize( CURSOR_THICKNESS, - GetRowRectFromCharacterPosition( mCursorPosition ).height ); - - // Need to scroll the text to make the cursor visible and to cover the whole text-input area. - - const Vector3& controlSize = GetControlSize(); - - // Calculates the new scroll position. - Vector2 scrollOffset = mTextLayoutInfo.mScrollOffset; - if( ( cursorPosition.x < 0.f ) || ( cursorPosition.x > controlSize.width ) ) - { - scrollOffset.x += cursorPosition.x; - } - - if( cursorPosition.y - cursorSize.height < 0.f || cursorPosition.y > controlSize.height ) - { - scrollOffset.y += cursorPosition.y; - } - - // Sets the new scroll position. - SetScrollPosition( Vector2::ZERO ); // TODO: need to reset to the zero position in order to make the scroll trim to work. - SetScrollPosition( scrollOffset ); -} - -void TextInput::StartScrollTimer() -{ - if( !mScrollTimer ) - { - mScrollTimer = Timer::New( SCROLL_TICK_INTERVAL ); - mScrollTimer.TickSignal().Connect( this, &TextInput::OnScrollTimerTick ); - } - - if( !mScrollTimer.IsRunning() ) - { - mScrollTimer.Start(); - } -} - -void TextInput::StopScrollTimer() -{ - if( mScrollTimer ) - { - mScrollTimer.Stop(); - } -} - -bool TextInput::OnScrollTimerTick() -{ - // TODO: need to set the new style accordingly the new handle position. - - if( !( mGrabHandleVisibility && mGrabHandle ) && !( mSelectionHandleOne && mSelectionHandleTwo ) ) - { - // nothing to do if all handles are invisible or doesn't exist. - return true; - } - - // Text scrolling - - // Choose between the grab handle or the selection handles. - Vector3& actualHandlePosition = ( mGrabHandleVisibility && mGrabHandle ) ? mActualGrabHandlePosition : ( mCurrentSelectionId == HandleOne ) ? mSelectionHandleOneActualPosition : mSelectionHandleTwoActualPosition; - std::size_t& handlePosition = ( mGrabHandleVisibility && mGrabHandle ) ? mCursorPosition : ( mCurrentSelectionId == HandleOne ) ? mSelectionHandleOnePosition : mSelectionHandleTwoPosition; - Vector3& currentHandlePosition = ( mGrabHandleVisibility && mGrabHandle ) ? mCurrentHandlePosition : mCurrentSelectionHandlePosition; - - std::size_t newCursorPosition = 0; - ReturnClosestIndex( actualHandlePosition.GetVectorXY(), newCursorPosition ); - - // Whether the handle's position is different of the previous one and in the case of the selection handle, - // the new selection handle's position needs to be different of the other one. - const bool differentSelectionHandles = ( mGrabHandleVisibility && mGrabHandle ) ? newCursorPosition != handlePosition : - ( mCurrentSelectionId == HandleOne ) ? ( newCursorPosition != handlePosition ) && ( newCursorPosition != mSelectionHandleTwoPosition ) : - ( newCursorPosition != handlePosition ) && ( newCursorPosition != mSelectionHandleOnePosition ); - - if( differentSelectionHandles ) - { - handlePosition = newCursorPosition; - - const Vector3 actualPosition = GetActualPositionFromCharacterPosition( newCursorPosition ); - - Vector2 scrollDelta = ( actualPosition - currentHandlePosition ).GetVectorXY(); - - Vector2 scrollPosition = mDisplayedTextView.GetScrollPosition(); - scrollPosition += scrollDelta; - SetScrollPosition( scrollPosition ); - - if( mDisplayedTextView.IsScrollPositionTrimmed() ) - { - StopScrollTimer(); - } - - currentHandlePosition = GetActualPositionFromCharacterPosition( newCursorPosition ).GetVectorXY(); - } - - actualHandlePosition.x += mScrollDisplacement.x; - actualHandlePosition.y += mScrollDisplacement.y; - - return true; -} - -// Public Internal Methods (public for testing purpose) - -void TextInput::SetUpTouchEvents() -{ - if ( !mTapDetector ) - { - mTapDetector = TapGestureDetector::New(); - // Attach the actors and connect the signal - mTapDetector.Attach(Self()); - - // As contains children which may register for tap the default control detector is not used. - mTapDetector.DetectedSignal().Connect(this, &TextInput::OnTextTap); - } - - if ( !mDoubleTapDetector ) - { - mDoubleTapDetector = TapGestureDetector::New( 2 ); - mDoubleTapDetector.DetectedSignal().Connect(this, &TextInput::OnDoubleTap); - - // Only attach and detach the actor to the double tap detector when we enter/leave edit mode - // so that we do not, unnecessarily, have a double tap request all the time - } - - if ( !mPanGestureDetector ) - { - mPanGestureDetector = PanGestureDetector::New(); - mPanGestureDetector.DetectedSignal().Connect(this, &TextInput::OnHandlePan); - } - - if ( !mLongPressDetector ) - { - mLongPressDetector = LongPressGestureDetector::New(); - mLongPressDetector.DetectedSignal().Connect(this, &TextInput::OnLongPress); - mLongPressDetector.Attach(Self()); - } -} - -void TextInput::CreateTextViewActor() -{ - mDisplayedTextView = Toolkit::TextView::New(); - mDisplayedTextView.SetName( "DisplayedTextView "); - mDisplayedTextView.SetMarkupProcessingEnabled( mMarkUpEnabled ); - mDisplayedTextView.SetParentOrigin(ParentOrigin::TOP_LEFT); - mDisplayedTextView.SetAnchorPoint(AnchorPoint::TOP_LEFT); - mDisplayedTextView.SetMultilinePolicy(Toolkit::TextView::SplitByWord); - mDisplayedTextView.SetWidthExceedPolicy( Toolkit::TextView::Original ); - mDisplayedTextView.SetHeightExceedPolicy( Toolkit::TextView::Original ); - mDisplayedTextView.SetLineJustification( Toolkit::TextView::Left ); - mDisplayedTextView.SetTextAlignment( static_cast( Toolkit::Alignment::HorizontalLeft | Toolkit::Alignment::VerticalTop ) ); - mDisplayedTextView.SetPosition( Vector3( 0.0f, 0.0f, DISPLAYED_TEXT_VIEW_Z_OFFSET ) ); - - mDisplayedTextView.ScrolledSignal().Connect( this, &TextInput::OnTextViewScrolled ); - - Self().Add( mDisplayedTextView ); -} - -// Start a timer to initiate, used by the cursor to blink. -void TextInput::StartCursorBlinkTimer() -{ - if ( !mCursorBlinkTimer ) - { - mCursorBlinkTimer = Timer::New( CURSOR_BLINK_INTERVAL ); - mCursorBlinkTimer.TickSignal().Connect( this, &TextInput::OnCursorBlinkTimerTick ); - } - - if ( !mCursorBlinkTimer.IsRunning() ) - { - mCursorBlinkTimer.Start(); - } -} - -// Start a timer to initiate, used by the cursor to blink. -void TextInput::StopCursorBlinkTimer() -{ - if ( mCursorBlinkTimer ) - { - mCursorBlinkTimer.Stop(); - } -} - -void TextInput::StartEditMode() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "TextInput StartEditMode mEditModeActive[%s]\n", (mEditModeActive)?"true":"false" ); - - if(!mEditModeActive) - { - SetKeyInputFocus(); - } - - if ( mDoubleTapDetector ) - { - mDoubleTapDetector.Attach( Self() ); - } -} - -void TextInput::EndEditMode() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "TextInput EndEditMode mEditModeActive[%s]\n", (mEditModeActive)?"true":"false" ); - - ClearKeyInputFocus(); - - if ( mDoubleTapDetector ) - { - mDoubleTapDetector.Detach( Self() ); - } -} - -void TextInput::ApplyPreEditStyle( std::size_t preEditStartPosition, std::size_t preEditStringLength ) -{ - if ( mPreEditFlag && ( preEditStringLength > 0 ) ) - { - mUnderlinedPriorToPreEdit = mInputStyle.IsUnderlineEnabled(); - TextStyle style; - style.SetUnderline( true ); - ApplyStyleToRange( style, TextStyle::UNDERLINE , preEditStartPosition, preEditStartPosition + preEditStringLength -1 ); - } -} - -void TextInput::RemovePreEditStyle() -{ - if ( !mUnderlinedPriorToPreEdit ) - { - TextStyle style; - style.SetUnderline( false ); - SetActiveStyle( style, TextStyle::UNDERLINE ); - } -} - -// IMF related methods - - -ImfManager::ImfCallbackData TextInput::ImfEventReceived( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent ) -{ - bool update( false ); - bool preeditResetRequired ( false ); - - if (imfEvent.eventName != ImfManager::GETSURROUNDING ) - { - HidePopup(); // If Pop-up shown then hides it as editing text. - } - - switch ( imfEvent.eventName ) - { - case ImfManager::PREEDIT: - { - mIgnoreFirstCommitFlag = false; - - // Some text may be selected, hiding keyboard causes an empty predictive string to be sent, we don't want to delete highlight in this case - - preeditResetRequired = PreEditReceived( imfEvent.predictiveString, imfEvent.cursorOffset ); - - if( IsScrollEnabled() ) - { - // Calculates the new cursor position (in actor coordinates) - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition ); - ScrollTextViewToMakeCursorVisible( cursorPosition ); - } - - update = true; - - break; - } - case ImfManager::COMMIT: - { - if( mIgnoreFirstCommitFlag ) - { - // Do not commit in this case when keyboard sends a commit when shows for the first time (work-around for imf keyboard). - mIgnoreFirstCommitFlag = false; - } - else - { - // A Commit message is a word that has been accepted, it may have been a pre-edit word previously but now commited. - - // Some text may be selected, hiding keyboard causes an empty predictive string to be sent, we don't want to delete highlight in this case - - // A PreEditReset can cause a commit message to be sent, the Ignore Commit flag is used in scenarios where the word is - // not needed, one such scenario is when the pre-edit word is too long to fit. - if ( !mIgnoreCommitFlag ) - { - update = CommitReceived( imfEvent.predictiveString ); - } - else - { - mIgnoreCommitFlag = false; // reset ignore flag so next commit is acted upon. - } - } - - if( update ) - { - if( IsScrollEnabled() ) - { - // Calculates the new cursor position (in actor coordinates) - const Vector3 cursorPosition = GetActualPositionFromCharacterPosition( mCursorPosition ); - - ScrollTextViewToMakeCursorVisible( cursorPosition ); - } - } - break; - } - case ImfManager::DELETESURROUNDING: - { - DALI_LOG_INFO( gLogFilter, Debug::General, "ImfEventReceived - delete surrounding mPreEditFlag[%s] cursor offset[%d] characters to delete[%d] position to delete[%u] \n", - (mPreEditFlag)?"true":"false", imfEvent.cursorOffset, imfEvent.numberOfChars, static_cast( mCursorPosition+imfEvent.cursorOffset) ); - - mPreEditFlag = false; - - std::size_t toDelete = 0; - std::size_t numberOfCharacters = 0; - - { - if( static_cast(std::abs( imfEvent.cursorOffset )) < mCursorPosition ) - { - toDelete = mCursorPosition + imfEvent.cursorOffset; - } - if( toDelete + imfEvent.numberOfChars > mStyledText.size() ) - { - numberOfCharacters = mStyledText.size() - toDelete; - } - else - { - numberOfCharacters = imfEvent.numberOfChars; - } - } - DALI_LOG_INFO( gLogFilter, Debug::General, "ImfEventReceived - deleteSurrounding pre-delete range mCursorPosition[%u] \n", mCursorPosition); - DeleteRange( toDelete, numberOfCharacters ); - - mCursorPosition = toDelete; - mNumberOfSurroundingCharactersDeleted = numberOfCharacters; - - EmitTextModified(); - - DALI_LOG_INFO( gLogFilter, Debug::General, "ImfEventReceived - deleteSurrounding post-delete range mCursorPosition[%u] \n", mCursorPosition); - break; - } - case ImfManager::GETSURROUNDING: - { - // If text is selected/highlighted and surrounding text received we do not want the keyboard to store the word at cursor and return it as a predictive word along with - // the next key pressed. Instead the Select function sets the cursor position and surrounding text. - if (! ( false || mSelectingText ) ) - { - std::string text( GetText() ); - DALI_LOG_INFO( gLogFilter, Debug::General, "OnKey - surrounding text - set text [%s] and cursor[%u] \n", text.c_str(), mCursorPosition ); - - imfManager.SetCursorPosition( mCursorPosition ); - imfManager.SetSurroundingText( text ); - } - - if( 0 != mNumberOfSurroundingCharactersDeleted ) - { - mDisplayedTextView.RemoveTextFrom( mCursorPosition, mNumberOfSurroundingCharactersDeleted ); - mNumberOfSurroundingCharactersDeleted = 0; - - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - } - break; - } - case ImfManager::VOID: - { - DALI_ASSERT_DEBUG( false ); - } - } // end switch - - ImfManager::ImfCallbackData callbackData( update, mCursorPosition, GetText(), preeditResetRequired ); - - return callbackData; -} - -bool TextInput::PreEditReceived(const std::string& keyString, std::size_t cursorOffset ) -{ - mPreserveCursorPosition = false; // As in pre-edit state we should have the cursor at the end of the word displayed not last touch position. - - DALI_LOG_INFO(gLogFilter, Debug::General, ">>PreEditReceived preserveCursorPos[%d] mCursorPos[%d] mPreEditFlag[%d]\n", - mPreserveCursorPosition, mCursorPosition, mPreEditFlag ); - - bool preeditResetRequest ( false ); - - if( mPreEditFlag ) // Already in pre-edit state. - { - if( mStyledText.size() >= mMaxStringLength ) - { - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived styledTextSize >= mMaxStringLength \n"); - // Cannot fit these characters into field, clear pre-edit. - if ( !mUnderlinedPriorToPreEdit ) - { - TextStyle style; - style.SetUnderline( false ); - ApplyStyleToRange( style, TextStyle::UNDERLINE , mPreEditStartPosition, mPreEditStartPosition + mPreEditLength -1 ); - } - mIgnoreCommitFlag = true; - preeditResetRequest = false; // this will reset the keyboard's predictive suggestions. - mPreEditFlag = false; - EmitMaxInputCharactersReachedSignal(); - } - else - { - // delete existing pre-edit string - const std::size_t numberOfCharactersToReplace = DeletePreEdit(); - - // Store new pre-edit string - mPreEditString.SetText( keyString ); - - if ( keyString.empty() ) - { - mPreEditFlag = false; - mCursorPosition = mPreEditStartPosition; - - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - mDisplayedTextView.RemoveTextFrom( mPreEditStartPosition, numberOfCharactersToReplace ); - } - - GetTextLayoutInfo(); - EmitTextModified(); - } - else - { - // Insert new pre-edit string. InsertAt updates the size and position table. - mPreEditLength = InsertAt( mPreEditString, mPreEditStartPosition, numberOfCharactersToReplace ); - // If word was too long to be inserted then cursorOffset would be out of range as keyboard assumes there is not limit. Hence use of std::min. - mCursorPosition = mPreEditStartPosition + std::min( cursorOffset, mPreEditLength ); - ApplyPreEditStyle( mPreEditStartPosition, mPreEditLength ); - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived mCursorPosition[%u] \n", mCursorPosition); - EmitTextModified(); - } - // cursor update to keyboard is not done here as the keyboard knows the cursor position and provides the 'cursorOffset'. - DrawCursor(); - } - } - else // mPreEditFlag not set - { - if ( !keyString.empty() ) // Imf can send an empty pre-edit followed by Backspace instead of a commit. - { - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived Initial Pre-Edit string \n"); - // new pre-edit so move into pre-edit state by setting flag - mPreEditFlag = true; - mPreEditString.SetText( keyString ); // store new pre-edit string - mPreEditStartPosition = mCursorPosition; // store starting cursor position of pre-edit so know where to re-start from - mPreEditLength = InsertAt( mPreEditString, mPreEditStartPosition, 0 ); - // If word was too long to be inserted then cursorOffset would be out of range as keyboard assumes there is not limit. Hence use of std::min. - mCursorPosition = mPreEditStartPosition + std::min( cursorOffset, mPreEditLength ); - ApplyPreEditStyle( mPreEditStartPosition, mPreEditLength ); - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived mCursorPosition[%u] mPreEditStartPosition[%u]\n", mCursorPosition, mPreEditStartPosition); - // cursor update to keyboard is not done here as the keyboard knows the cursor position and provides the 'cursorOffset'. - DrawCursor(); - EmitTextModified(); - } - else - { - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReceived with empty keyString\n"); - } - } - - return preeditResetRequest; -} - -bool TextInput::CommitReceived(const std::string& keyString ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, ">>CommitReceived preserveCursorPos[%d] mPreEditStartPosition [%d] mCursorPos[%d] mPreEditFlag[%d] mIgnoreCommitFlag[%s]\n", - mPreserveCursorPosition, mPreEditStartPosition, mCursorPosition, mPreEditFlag, (mIgnoreCommitFlag)?"true":"false" ); - - bool update( false ); - - RemovePreEditStyle(); - - const std::size_t styledTextSize( mStyledText.size() ); - if( styledTextSize >= mMaxStringLength ) - { - // Cannot fit these characters into field, clear pre-edit. - if ( mPreEditFlag ) - { - mIgnoreCommitFlag = true; - mPreEditFlag = false; - } - EmitMaxInputCharactersReachedSignal(); - } - else - { - if( mPreEditFlag ) - { - // delete existing pre-edit string - const std::size_t numberOfCharactersToReplace = DeletePreEdit(); - mPreEditFlag = false; - - DALI_LOG_INFO(gLogFilter, Debug::General, "CommitReceived mPreserveCursorPosition[%s] mPreEditStartPosition[%u]\n", - (mPreserveCursorPosition)?"true":"false", mPreEditStartPosition ); - - if ( mPreserveCursorPosition ) // PreEditReset has been called triggering this commit. - { - // No need to update cursor position as Cursor location given by touch. - InsertAt( Text( keyString ), mPreEditStartPosition, numberOfCharactersToReplace ); - mPreserveCursorPosition = false; - } - else - { - // Cursor not set by touch so needs to be re-positioned to input more text - mCursorPosition = mPreEditStartPosition + InsertAt( Text(keyString), mPreEditStartPosition, numberOfCharactersToReplace ); // update cursor position as InsertAt, re-draw cursor with this - - // If a space or enter caused the commit then our string is one longer than the string given to us by the commit key. - if ( mCommitByKeyInput ) - { - mCursorPosition = std::min ( mCursorPosition + 1, mStyledText.size() ); - mCommitByKeyInput = false; - } - } - - EmitTextModified(); - - if ( mSelectTextOnCommit ) - { - SelectText(mRequestedSelection.mStartOfSelection, mRequestedSelection.mEndOfSelection ); - } - - update = true; - } - else // mPreEditFlag not set - { - if ( !mIgnoreCommitFlag ) // Check if this commit should be ignored. - { - if( mStyledText.empty() && mPlaceHolderSet ) - { - // If the styled text is empty and the placeholder text is set, it needs to be cleared. - mDisplayedTextView.SetText( "" ); - mNumberOfSurroundingCharactersDeleted = 0; - mPlaceHolderSet = false; - } - mCursorPosition = mCursorPosition + InsertAt( Text( keyString ), mCursorPosition, mNumberOfSurroundingCharactersDeleted ); - update = true; - mNumberOfSurroundingCharactersDeleted = 0; - EmitTextModified(); - } - else - { - mIgnoreCommitFlag = false; // Reset flag so future commits will not be ignored. - } - } - } - - mSelectTextOnCommit = false; - - DALI_LOG_INFO(gLogFilter, Debug::General, "CommitReceived << mCursorPos[%d] mPreEditFlag[%d] update[%s] \n", - mCursorPosition, mPreEditFlag, (update)?"true":"false" ); - - return update; -} - -// End of IMF related methods - -std::size_t TextInput::DeletePreEdit() -{ - DALI_LOG_INFO(gLogFilter, Debug::General, ">>DeletePreEdit mPreEditFlag[%s] \n", (mPreEditFlag)?"true":"false"); - - DALI_ASSERT_DEBUG( mPreEditFlag ); - - const std::size_t preEditStringLength = mPreEditString.GetLength(); - const std::size_t styledTextSize = mStyledText.size(); - - std::size_t endPosition = mPreEditStartPosition + preEditStringLength; - - // Prevents erase items outside mStyledText bounds. - if( mPreEditStartPosition > styledTextSize ) - { - DALI_ASSERT_DEBUG( !"TextInput::DeletePreEdit. mPreEditStartPosition > mStyledText.size()" ); - mPreEditStartPosition = styledTextSize; - } - - if( ( endPosition > styledTextSize ) || ( endPosition < mPreEditStartPosition ) ) - { - DALI_ASSERT_DEBUG( !"TextInput::DeletePreEdit. ( endPosition > mStyledText.size() ) || ( endPosition < mPreEditStartPosition )" ); - endPosition = styledTextSize; - } - - mStyledText.erase( mStyledText.begin() + mPreEditStartPosition, mStyledText.begin() + endPosition ); - - // DeletePreEdit() doesn't remove characters from the text-view because may be followed by an InsertAt() which inserts characters, - // in that case, the Insert should use the returned number of deleted characters and replace the text which helps the text-view to - // reuse glyphs. - // In case DeletePreEdit() is not followed by an InsertAt() characters must be deleted after this call. - - return preEditStringLength; -} - -void TextInput::PreEditReset( bool preserveCursorPosition ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "PreEditReset preserveCursorPos[%d] mCursorPos[%d] \n", - preserveCursorPosition, mCursorPosition); - - // Store flag to indicate that we do not want to lose the cursor position as the reset may have occurred due to touch event moving the cursor. - mPreserveCursorPosition = preserveCursorPosition; - - // Reset incase we are in a pre-edit state. - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.Reset(); // Will trigger a commit message - } -} - -void TextInput::CursorUpdate() -{ - DrawCursor(); - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - std::string text( GetText() ); - imfManager.SetSurroundingText( text ); // Notifying IMF of a cursor change triggers a surrounding text request so updating it now. - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } -} - -/* Delete highlighted characters redisplay*/ -void TextInput::DeleteHighlightedText( bool inheritStyle ) -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "DeleteHighlightedText handlePosOne[%u] handlePosTwo[%u]\n", mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - -} - -void TextInput::DeleteRange( const std::size_t start, const std::size_t ncharacters ) -{ - DALI_ASSERT_DEBUG( start <= mStyledText.size() ); - DALI_ASSERT_DEBUG( !mStyledText.empty() ); - - DALI_LOG_INFO(gLogFilter, Debug::General, ">>DeleteRange pre mStyledText[%s] mPreEditFlag[%s] \n", GetText().c_str(), (mPreEditFlag)?"true":"false"); - - - if ( ( !mStyledText.empty()) && ( ( start + ncharacters ) <= mStyledText.size() ) ) - { - MarkupProcessor::StyledTextArray::iterator itStart = mStyledText.begin() + start; - MarkupProcessor::StyledTextArray::iterator itEnd = mStyledText.begin() + start + ncharacters; - - mStyledText.erase(itStart, itEnd); - - // update the selection handles if they are visible. - - // Set text is not called here as currently it can not process the set text from deletion and then the set text from the in-coming pre-edit. - } - - DALI_LOG_INFO(gLogFilter, Debug::General, "DeleteRange<< post mStyledText[%s] mPreEditFlag[%s] \n", GetText().c_str(), (mPreEditFlag)?"true":"false"); - - // Although mStyledText has been set to a new text string we no longer re-draw the text or notify the cursor change. - // This is a performance decision as the use of this function often means the text is being replaced or just deleted. - // Mean we do not re-draw the text more than we have too. -} - -/* Delete character at current cursor position and redisplay*/ -void TextInput::DeleteCharacter( std::size_t positionToDelete ) -{ - // Ensure positionToDelete is not out of bounds. - DALI_ASSERT_DEBUG( positionToDelete <= mStyledText.size() ); - DALI_ASSERT_DEBUG( !mStyledText.empty() ); - DALI_ASSERT_DEBUG( positionToDelete > 0 ); - - DALI_LOG_INFO(gLogFilter, Debug::General, "DeleteCharacter positionToDelete[%u]", positionToDelete ); - - - if ( ( !mStyledText.empty()) && ( positionToDelete > 0 ) && positionToDelete <= mStyledText.size() ) // don't try to delete if no characters left of cursor - { - MarkupProcessor::StyledTextArray::iterator it = mStyledText.begin() + positionToDelete - 1; - - // Get the styled text of the character to be deleted as it may be needed if - // the "exceed the text-input's boundaries" option is disabled. - const MarkupProcessor::StyledText styledCharacterToDelete( *it ); - - mStyledText.erase(it); // erase the character left of positionToDelete - - if( mStyledText.empty() ) - { - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - mDisplayedTextView.RemoveTextFrom( positionToDelete - 1, 1 ); - - const Character characterToDelete = styledCharacterToDelete.mText[0]; - - // It may happen than after removing a white space or a new line character, - // two words merge, this new word could be big enough to not fit in its - // current line, so moved to the next one, and make some part of the text to - // exceed the text-input's boundary. - if( !mExceedEnabled ) - { - if( characterToDelete.IsWhiteSpace() || characterToDelete.IsNewLine() ) - { - // Get the new text layout after removing one character. - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - - // Get text-input's size. - const Vector3& size = GetControlSize(); - - if( ( mTextLayoutInfo.mTextSize.width > size.width ) || - ( mTextLayoutInfo.mTextSize.height > size.height ) ) - { - MarkupProcessor::StyledTextArray array; - array.push_back( styledCharacterToDelete ); - mDisplayedTextView.InsertTextAt( positionToDelete - 1, array ); - - mStyledText.insert( mStyledText.begin() + ( positionToDelete - 1 ), styledCharacterToDelete ); - } - } - } - } - GetTextLayoutInfo(); - - ShowGrabHandleAndSetVisibility( false ); - - mCursorPosition = positionToDelete -1; - - const TextStyle oldInputStyle( mInputStyle ); - - mInputStyle = GetStyleAtCursor(); // Inherit style from cursor position - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } -} - -/*Insert new character into the string and (optionally) redisplay text-input*/ -std::size_t TextInput::InsertAt( const Text& newText, const std::size_t insertionPosition, const std::size_t numberOfCharactersToReplace ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "InsertAt insertionPosition[%u]\n", insertionPosition ); - - // Ensure insertionPosition is not out of bounds. - DALI_ASSERT_ALWAYS( insertionPosition <= mStyledText.size() ); - - bool textExceedsMaximunNumberOfCharacters = false; - bool textExceedsBoundary = false; - std::size_t insertedStringLength = DoInsertAt( newText, insertionPosition, numberOfCharactersToReplace, textExceedsMaximunNumberOfCharacters, textExceedsBoundary ); - - ShowGrabHandleAndSetVisibility( false ); - - if( textExceedsMaximunNumberOfCharacters || textExceedsBoundary ) - { - if( mPreEditFlag ) - { - mIgnoreCommitFlag = true; - mPreEditFlag = false; - // A PreEditReset( false ) should be triggered from here if the keyboards predictive suggestions must be cleared. - // Although can not directly call PreEditReset() as it will cause a recursive emit loop. - } - - if( textExceedsMaximunNumberOfCharacters ) - { - EmitMaxInputCharactersReachedSignal(); - } - - if( textExceedsBoundary ) - { - EmitInputTextExceedsBoundariesSignal(); - PreEditReset( false ); - } - } - - return insertedStringLength; -} - -ImageActor TextInput::CreateCursor( const Vector4& color) -{ - ImageActor cursor; - cursor = CreateSolidColorActor(color); - cursor.SetName( "Cursor" ); - - cursor.SetParentOrigin(ParentOrigin::TOP_LEFT); - cursor.SetAnchorPoint(AnchorPoint::BOTTOM_LEFT); - cursor.SetVisible(false); - - return cursor; -} - -void TextInput::AdvanceCursor(bool reverse, std::size_t places) -{ - // As cursor is not moving due to grab handle, handle should be hidden. - ShowGrabHandleAndSetVisibility( false ); - - bool cursorPositionChanged = false; - if (reverse) - { - if ( mCursorPosition >= places ) - { - mCursorPosition = mCursorPosition - places; - cursorPositionChanged = true; - } - } - else - { - if ((mCursorPosition + places) <= mStyledText.size()) - { - mCursorPosition = mCursorPosition + places; - cursorPositionChanged = true; - } - } - - if( cursorPositionChanged ) - { - const std::size_t cursorPositionForStyle = ( 0 == mCursorPosition ? 0 : mCursorPosition - 1 ); - - const TextStyle oldInputStyle( mInputStyle ); - mInputStyle = GetStyleAt( cursorPositionForStyle ); // Inherit style from selected position. - - DrawCursor(); - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - } -} - -void TextInput::DrawCursor() -{ - const Size rowRect = GetRowRectFromCharacterPosition( mCursorPosition ); - - // Get height of cursor and set its size - Size size( CURSOR_THICKNESS, 0.0f ); - if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) - { - size.height = rowRect.height; - } - else - { - // Measure Font so know how big text will be if no initial text to measure. - size.height = mLineHeight; - } - - mCursor.SetSize(size); - - // If the character is italic then the cursor also tilts. - mCursor.SetOrientation( mInputStyle.IsItalicsEnabled() ? Degree( mInputStyle.GetItalicsAngle() - CURSOR_ANGLE_OFFSET ) : Degree( 0.f ), Vector3::ZAXIS ); - - DALI_ASSERT_DEBUG( mCursorPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ); - - if( ( mCursorPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) ) - { - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 position = GetActualPositionFromCharacterPosition( mCursorPosition, directionRTL, altPosition, altPositionValid ); - - SetAltCursorEnabled( altPositionValid ); - - if( !altPositionValid ) - { - mCursor.SetPosition( position + UI_OFFSET ); - } - else - { - size.height *= 0.5f; - mCursor.SetSize(size); - mCursor.SetPosition( position + UI_OFFSET - Vector3( 0.0f, directionRTL ? 0.0f : size.height, 0.0f ) ); - - // TODO: change this cursor pos, to be the one where the cursor is sourced from. - size.height = rowRect.height * 0.5f; - mCursorRTL.SetSize(size); - mCursorRTL.SetPosition( altPosition + UI_OFFSET - Vector3( 0.0f, directionRTL ? size.height : 0.0f, 0.0f ) ); - } - - if( IsScrollEnabled() ) - { - // Whether cursor and grab handle are inside the boundaries of the text-input when text scroll is enabled. - mIsCursorInScrollArea = mIsGrabHandleInScrollArea = IsPositionInsideBoundaries( position, size, GetControlSize() ); - } - } // EditMode -} - -void TextInput::SetAltCursorEnabled( bool enabled ) -{ - mCursorRTLEnabled = enabled; - mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled ); -} - -void TextInput::SetCursorVisibility( bool visible ) -{ - mCursorVisibility = visible; - mCursor.SetVisible( mCursorVisibility && mIsCursorInScrollArea ); - mCursorRTL.SetVisible( mCursorVisibility && mCursorRTLEnabled ); -} - -void TextInput::CreateGrabHandle( Dali::Image image ) -{ - if ( !mGrabHandle ) - { - if ( !image ) - { - mGrabHandleImage = ResourceImage::New(DEFAULT_GRAB_HANDLE); - } - else - { - mGrabHandleImage = image; - } - - mGrabHandle = ImageActor::New(mGrabHandleImage); - mGrabHandle.SetParentOrigin(ParentOrigin::TOP_LEFT); - mGrabHandle.SetAnchorPoint(AnchorPoint::TOP_CENTER); - - mGrabHandle.SetDrawMode(DrawMode::OVERLAY); - - ShowGrabHandleAndSetVisibility( false ); - - CreateGrabArea( mGrabHandle ); - - mActiveLayer.Add(mGrabHandle); - } -} - -void TextInput::CreateGrabArea( Actor& parent ) -{ - mGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move - mGrabArea.SetName( "GrabArea" ); - mGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - mGrabArea.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); - mGrabArea.SetSizeModeFactor( DEFAULT_GRAB_HANDLE_RELATIVE_SIZE ); - mGrabArea.TouchedSignal().Connect(this,&TextInput::OnPressDown); - mTapDetector.Attach( mGrabArea ); - mPanGestureDetector.Attach( mGrabArea ); - mLongPressDetector.Attach( mGrabArea ); - - parent.Add(mGrabArea); -} - -Vector3 TextInput::MoveGrabHandle( const Vector2& displacement ) -{ - Vector3 actualHandlePosition; - - if (mGrabHandle) - { - mActualGrabHandlePosition.x += displacement.x; - mActualGrabHandlePosition.y += displacement.y; - - // Grab handle should jump to the nearest character and take cursor with it - std::size_t newCursorPosition = 0; - ReturnClosestIndex( mActualGrabHandlePosition.GetVectorXY(), newCursorPosition ); - - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - actualHandlePosition = GetActualPositionFromCharacterPosition( newCursorPosition, directionRTL, altPosition, altPositionValid ); - - if( altPositionValid ) - { - // Check which of the positions is the closest. - if( fabsf( altPosition.x - mActualGrabHandlePosition.x ) < fabsf( actualHandlePosition.x - mActualGrabHandlePosition.x ) ) - { - actualHandlePosition = altPosition; - } - } - - bool handleVisible = true; - - if( IsScrollEnabled() ) - { - const Vector3 controlSize = GetControlSize(); - const Size cursorSize = GetRowRectFromCharacterPosition( newCursorPosition ); - // Scrolls the text if the handle is not in a visible position - handleVisible = IsPositionInsideBoundaries( actualHandlePosition, - cursorSize, - controlSize ); - - if( handleVisible ) - { - StopScrollTimer(); - mCurrentHandlePosition = actualHandlePosition; - mScrollDisplacement = Vector2::ZERO; - } - else - { - if( ( actualHandlePosition.x < SCROLL_THRESHOLD ) && ( displacement.x <= 0.f ) ) - { - mScrollDisplacement.x = -SCROLL_SPEED; - } - else if( ( actualHandlePosition.x > controlSize.width - SCROLL_THRESHOLD ) && ( displacement.x >= 0.f ) ) - { - mScrollDisplacement.x = SCROLL_SPEED; - } - if( ( actualHandlePosition.y < SCROLL_THRESHOLD ) && ( displacement.y <= 0.f ) ) - { - mScrollDisplacement.y = -SCROLL_SPEED; - } - else if( ( actualHandlePosition.y > controlSize.height - SCROLL_THRESHOLD ) && ( displacement.y >= 0.f ) ) - { - mScrollDisplacement.y = SCROLL_SPEED; - } - StartScrollTimer(); - } - } - - if( handleVisible && // Only redraw cursor and do updates if position changed - ( newCursorPosition != mCursorPosition ) ) // and the new position is visible (if scroll is not enabled, it's always true). - { - mCursorPosition = newCursorPosition; - - mGrabHandle.SetPosition( actualHandlePosition + UI_OFFSET ); - - const TextStyle oldInputStyle( mInputStyle ); - - mInputStyle = GetStyleAtCursor(); //Inherit style from cursor position - - CursorUpdate(); // Let keyboard know the new cursor position so can 're-capture' for prediction. - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } - } - - return actualHandlePosition; -} - -void TextInput::ShowGrabHandle( bool visible ) -{ - if ( IsGrabHandleEnabled() ) - { - if( mGrabHandle ) - { - mGrabHandle.SetVisible( mGrabHandleVisibility ); - } - StartMonitoringStageForTouch(); - } -} - -void TextInput::ShowGrabHandleAndSetVisibility( bool visible ) -{ - mGrabHandleVisibility = visible; - ShowGrabHandle( visible ); -} - -// Callbacks connected to be Property notifications for Boundary checking. - -void TextInput::OnLeftBoundaryExceeded(PropertyNotification& source) -{ - mIsSelectionHandleOneFlipped = true; - mSelectionHandleOne.SetScale( -1.0f, 1.0f, 1.0f ); - mSelectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_LEFT); -} - -void TextInput::OnReturnToLeftBoundary(PropertyNotification& source) -{ - mIsSelectionHandleOneFlipped = false; - mSelectionHandleOne.SetScale( 1.0f, 1.0f, 1.0f ); - mSelectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_RIGHT); -} - -void TextInput::OnRightBoundaryExceeded(PropertyNotification& source) -{ - mIsSelectionHandleTwoFlipped = true; - mSelectionHandleTwo.SetScale( -1.0f, 1.0f, 1.0f ); - mSelectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_RIGHT); -} - -void TextInput::OnReturnToRightBoundary(PropertyNotification& source) -{ - mIsSelectionHandleTwoFlipped = false; - mSelectionHandleTwo.SetScale( 1.0f, 1.0f, 1.0f ); - mSelectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_LEFT); -} - -// todo change PropertyNotification signal definition to include Actor. Hence won't need duplicate functions. -void TextInput::OnHandleOneLeavesBoundary( PropertyNotification& source) -{ - mSelectionHandleOne.SetOpacity(0.0f); -} - -void TextInput::OnHandleOneWithinBoundary(PropertyNotification& source) -{ - mSelectionHandleOne.SetOpacity(1.0f); -} - -void TextInput::OnHandleTwoLeavesBoundary( PropertyNotification& source) -{ - mSelectionHandleTwo.SetOpacity(0.0f); -} - -void TextInput::OnHandleTwoWithinBoundary(PropertyNotification& source) -{ - mSelectionHandleTwo.SetOpacity(1.0f); -} - -// End of Callbacks connected to be Property notifications for Boundary checking. - -void TextInput::SetUpHandlePropertyNotifications() -{ - /* Property notifications for handles exceeding the boundary and returning back within boundary */ - - Vector3 handlesize = GetSelectionHandleSize(); - - // Exceeding horizontal boundary - PropertyNotification leftNotification = mSelectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.x + handlesize.x) ); - leftNotification.NotifySignal().Connect( this, &TextInput::OnLeftBoundaryExceeded ); - - PropertyNotification rightNotification = mSelectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.z - handlesize.x ) ); - rightNotification.NotifySignal().Connect( this, &TextInput::OnRightBoundaryExceeded ); - - // Within horizontal boundary - PropertyNotification leftLeaveNotification = mSelectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, GreaterThanCondition( mBoundingRectangleWorldCoordinates.x + 2*handlesize.x ) ); - leftLeaveNotification.NotifySignal().Connect( this, &TextInput::OnReturnToLeftBoundary ); - - PropertyNotification rightLeaveNotification = mSelectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_X, LessThanCondition( mBoundingRectangleWorldCoordinates.z - 2*handlesize.x ) ); - rightLeaveNotification.NotifySignal().Connect( this, &TextInput::OnReturnToRightBoundary ); - - // Exceeding vertical boundary - PropertyNotification verticalExceedNotificationOne = mSelectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalExceedNotificationOne.NotifySignal().Connect( this, &TextInput::OnHandleOneLeavesBoundary ); - - PropertyNotification verticalExceedNotificationTwo = mSelectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - OutsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalExceedNotificationTwo.NotifySignal().Connect( this, &TextInput::OnHandleTwoLeavesBoundary ); - - // Within vertical boundary - PropertyNotification verticalWithinNotificationOne = mSelectionHandleOne.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalWithinNotificationOne.NotifySignal().Connect( this, &TextInput::OnHandleOneWithinBoundary ); - - PropertyNotification verticalWithinNotificationTwo = mSelectionHandleTwo.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, - InsideCondition( mBoundingRectangleWorldCoordinates.y + handlesize.y, - mBoundingRectangleWorldCoordinates.w - handlesize.y ) ); - verticalWithinNotificationTwo.NotifySignal().Connect( this, &TextInput::OnHandleTwoWithinBoundary ); -} - -void TextInput::CreateSelectionHandles( std::size_t start, std::size_t end, Dali::Image handleOneImage, Dali::Image handleTwoImage ) -{ - mSelectionHandleOnePosition = start; - mSelectionHandleTwoPosition = end; - - if ( !mSelectionHandleOne ) - { - // create normal and pressed images - mSelectionHandleOneImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE ); - mSelectionHandleOneImagePressed = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE_PRESSED ); - - mSelectionHandleOne = ImageActor::New( mSelectionHandleOneImage ); - mSelectionHandleOne.SetName("SelectionHandleOne"); - mSelectionHandleOne.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mSelectionHandleOne.SetAnchorPoint( AnchorPoint::TOP_RIGHT ); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text. - mIsSelectionHandleOneFlipped = false; - mSelectionHandleOne.SetDrawMode( DrawMode::OVERLAY ); // ensure grab handle above text - - mHandleOneGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move - mHandleOneGrabArea.SetName("SelectionHandleOneGrabArea"); - - mHandleOneGrabArea.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); - mHandleOneGrabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); - mHandleOneGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - - mTapDetector.Attach( mHandleOneGrabArea ); - mPanGestureDetector.Attach( mHandleOneGrabArea ); - - mHandleOneGrabArea.TouchedSignal().Connect(this,&TextInput::OnHandleOneTouched); - - mSelectionHandleOne.Add( mHandleOneGrabArea ); - mActiveLayer.Add( mSelectionHandleOne ); - } - - if ( !mSelectionHandleTwo ) - { - // create normal and pressed images - mSelectionHandleTwoImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO ); - mSelectionHandleTwoImagePressed = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO_PRESSED ); - - mSelectionHandleTwo = ImageActor::New( mSelectionHandleTwoImage ); - mSelectionHandleTwo.SetName("SelectionHandleTwo"); - mSelectionHandleTwo.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mSelectionHandleTwo.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - mIsSelectionHandleTwoFlipped = false; - mSelectionHandleTwo.SetDrawMode(DrawMode::OVERLAY); // ensure grab handle above text - - mHandleTwoGrabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move - mHandleTwoGrabArea.SetName("SelectionHandleTwoGrabArea"); - mHandleTwoGrabArea.SetSizeMode( SIZE_RELATIVE_TO_PARENT ); - mHandleTwoGrabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); - mHandleTwoGrabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - - mTapDetector.Attach( mHandleTwoGrabArea ); - mPanGestureDetector.Attach( mHandleTwoGrabArea ); - - mHandleTwoGrabArea.TouchedSignal().Connect(this, &TextInput::OnHandleTwoTouched); - - mSelectionHandleTwo.Add( mHandleTwoGrabArea ); - - mActiveLayer.Add( mSelectionHandleTwo ); - } - - SetUpHandlePropertyNotifications(); - - // update table as text may have changed. - GetTextLayoutInfo(); - - Vector3 altPositionOne; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValidOne; // Alternate cursor validity flag. - bool directionRTLOne; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPositionOne = GetActualPositionFromCharacterPosition( mSelectionHandleOnePosition, directionRTLOne, altPositionOne, altPositionValidOne ); - - Vector3 altPositionTwo; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValidTwo; // Alternate cursor validity flag. - bool directionRTLTwo; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - Vector3 cursorPositionTwo = GetActualPositionFromCharacterPosition( mSelectionHandleTwoPosition, directionRTLTwo, altPositionTwo, altPositionValidTwo ); - - // VCC TODO: This method is a hack for one line. - ChooseRtlSelectionHandlePosition( cursorPositionOne, - cursorPositionTwo, - altPositionValidOne, - altPositionValidTwo, - altPositionOne, - altPositionTwo ); - - mSelectionHandleOne.SetPosition( mSelectionHandleOneActualPosition + UI_OFFSET + mSelectionHandleOneOffset ); - mSelectionHandleTwo.SetPosition( mSelectionHandleTwoActualPosition + UI_OFFSET + mSelectionHandleTwoOffset ); - - // Calculates and set the visibility if the scroll mode is enabled. - bool isSelectionHandleOneVisible = true; - bool isSelectionHandleTwoVisible = true; - if( IsScrollEnabled() ) - { - const Vector3& controlSize( GetControlSize() ); - isSelectionHandleOneVisible = IsPositionInsideBoundaries( mSelectionHandleOneActualPosition, Size::ZERO, controlSize ); - isSelectionHandleTwoVisible = IsPositionInsideBoundaries( mSelectionHandleTwoActualPosition, Size::ZERO, controlSize ); - mSelectionHandleOne.SetVisible( isSelectionHandleOneVisible ); - mSelectionHandleTwo.SetVisible( isSelectionHandleTwoVisible ); - } - - CreateHighlight(); // function will only create highlight if not already created. -} - -Vector3 TextInput::MoveSelectionHandle( SelectionHandleId handleId, const Vector2& displacement ) -{ - Vector3 actualHandlePosition; - - if ( mSelectionHandleOne && mSelectionHandleTwo ) - { - const Vector3& controlSize = GetControlSize(); - - Size cursorSize( CURSOR_THICKNESS, 0.f ); - - // Get a reference of the wanted selection handle (handle one or two). - Vector3& actualSelectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleOneActualPosition : mSelectionHandleTwoActualPosition; - - // Get a reference for the current position of the handle and a copy of its pair - std::size_t& currentSelectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleOnePosition : mSelectionHandleTwoPosition; - const std::size_t pairSelectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleTwoPosition : mSelectionHandleOnePosition; - - // Get a handle of the selection handle actor - ImageActor selectionHandleActor = ( handleId == HandleOne ) ? mSelectionHandleOne : mSelectionHandleTwo; - - // Selection handles should jump to the nearest character - std::size_t newHandlePosition = 0; - ReturnClosestIndex( actualSelectionHandlePosition.GetVectorXY(), newHandlePosition ); - - Vector3 altPosition; // Alternate (i.e. opposite direction) cursor position. - bool altPositionValid; // Alternate cursor validity flag. - bool directionRTL; // Need to know direction of primary cursor (in case we have 2 cursors and need to show them differently) - actualHandlePosition = GetActualPositionFromCharacterPosition( newHandlePosition, directionRTL, altPosition, altPositionValid ); - if( altPositionValid ) - { - // Check which of the positions is the closest. - if( fabsf( altPosition.x - actualSelectionHandlePosition.x ) < fabsf( actualHandlePosition.x - actualSelectionHandlePosition.x ) ) - { - actualHandlePosition = altPosition; - } - } - - bool handleVisible = true; - - if( IsScrollEnabled() ) - { - mCurrentSelectionId = handleId; - - cursorSize.height = GetRowRectFromCharacterPosition( newHandlePosition ).height; - // Restricts the movement of the grab handle inside the boundaries of the text-input. - handleVisible = IsPositionInsideBoundaries( actualHandlePosition, - cursorSize, - controlSize ); - - if( handleVisible ) - { - StopScrollTimer(); - mCurrentSelectionHandlePosition = actualHandlePosition; - mScrollDisplacement = Vector2::ZERO; - } - else - { - if( ( actualHandlePosition.x < SCROLL_THRESHOLD ) && ( displacement.x <= 0.f ) ) - { - mScrollDisplacement.x = -SCROLL_SPEED; - } - else if( ( actualHandlePosition.x > controlSize.width - SCROLL_THRESHOLD ) && ( displacement.x >= 0.f ) ) - { - mScrollDisplacement.x = SCROLL_SPEED; - } - if( ( actualHandlePosition.y < SCROLL_THRESHOLD ) && ( displacement.y <= 0.f ) ) - { - mScrollDisplacement.y = -SCROLL_SPEED; - } - else if( ( actualHandlePosition.y > controlSize.height - SCROLL_THRESHOLD ) && ( displacement.y >= 0.f ) ) - { - mScrollDisplacement.y = SCROLL_SPEED; - } - StartScrollTimer(); - } - } - - if ( handleVisible && // Ensure the handle is visible. - ( newHandlePosition != pairSelectionHandlePosition ) && // Ensure handle one is not the same position as handle two. - ( newHandlePosition != currentSelectionHandlePosition ) ) // Ensure the handle has moved. - { - currentSelectionHandlePosition = newHandlePosition; - - Vector3 selectionHandleOffset = ( handleId == HandleOne ) ? mSelectionHandleOneOffset : mSelectionHandleTwoOffset; - selectionHandleActor.SetPosition( actualHandlePosition + UI_OFFSET + selectionHandleOffset ); - - UpdateHighlight(); - - if ( handleId == HandleOne ) - { - const TextStyle oldInputStyle( mInputStyle ); - - // Set Active Style to that of first character in selection - if( mSelectionHandleOnePosition < mStyledText.size() ) - { - mInputStyle = ( mStyledText.at( mSelectionHandleOnePosition ) ).mStyle; - } - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - } - } - } - - return actualHandlePosition; // Returns Handle position passed in if new value not assigned. -} - -void TextInput::SetSelectionHandlePosition(SelectionHandleId handleId) -{ - const std::size_t selectionHandlePosition = ( handleId == HandleOne ) ? mSelectionHandleOnePosition : mSelectionHandleTwoPosition; - ImageActor selectionHandleActor = ( handleId == HandleOne ) ? mSelectionHandleOne : mSelectionHandleTwo; - - if ( selectionHandleActor ) - { - const Vector3 actualHandlePosition = GetActualPositionFromCharacterPosition( selectionHandlePosition ); - Vector3 selectionHandleOffset = ( handleId == HandleOne ) ? mSelectionHandleOneOffset : mSelectionHandleTwoOffset; - selectionHandleActor.SetPosition( actualHandlePosition + UI_OFFSET + selectionHandleOffset ); - - if( IsScrollEnabled() ) - { - const Size cursorSize( CURSOR_THICKNESS, - GetRowRectFromCharacterPosition( selectionHandlePosition ).height ); - selectionHandleActor.SetVisible( IsPositionInsideBoundaries( actualHandlePosition, - cursorSize, - GetControlSize() ) ); - } - } -} - -void TextInput::GetVisualTextSelection( std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection ) -{ - selectedVisualText.resize( mTextLayoutInfo.mCharacterLogicalToVisualMap.size(), false ); - - // VCC Set true/false in logical order. TODO : It needs to be checked. - - if( startSelection > endSelection ) - { - std::swap( startSelection, endSelection ); - } - std::size_t index = 0u; - for( std::vector::iterator it = selectedVisualText.begin(), endIt = selectedVisualText.end(); it != endIt; ++it, ++index ) - { - if( ( index < startSelection ) || ( endSelection <= index ) ) - { - *it = false; - } - else - { - *it = true; - } - } -} - -// Calculate the dimensions of the quads they will make the highlight mesh -TextInput::HighlightInfo TextInput::CalculateHighlightInfo() -{ - // At the moment there is no public API to modify the block alignment option. - - mNewHighlightInfo.mQuadList.clear(); // clear last quad information. - - if ( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() && !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() ) - { - Toolkit::TextView::CharacterLayoutInfoContainer::iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin(); - Toolkit::TextView::CharacterLayoutInfoContainer::iterator end = mTextLayoutInfo.mCharacterLayoutInfoTable.end(); - - // Get vector of flags representing characters that are selected (true) vs unselected (false). - std::vector selectedVisualText; - GetVisualTextSelection( selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - std::vector::iterator selectedIt = selectedVisualText.begin(); - std::vector::iterator selectedEndIt = selectedVisualText.end(); - - SelectionState selectionState = SelectionNone; ///< Current selection status of cursor over entire text. - float rowLeft = 0.0f; - float rowRight = 0.0f; - // Keep track of the TextView's min/max extents. Should be able to query this from TextView. - float maxRowLeft = std::numeric_limits::max(); - float maxRowRight = 0.0f; - - Toolkit::TextView::CharacterLayoutInfoContainer::iterator lastIt = it; - - // Scan through entire text. - while(it != end) - { - // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection. - - Toolkit::TextView::CharacterLayoutInfo& charInfo(*it); - bool charSelected = false; - if( selectedIt != selectedEndIt ) - { - charSelected = *selectedIt++; - } - - if( selectionState == SelectionNone ) - { - if( charSelected ) - { - selectionState = SelectionStarted; - rowLeft = charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x; - rowRight = rowLeft + charInfo.mSize.width; - } - } - else if( selectionState == SelectionStarted ) - { - // break selection on: - // 1. new line causing selection break. (\n or wordwrap) - // 2. character not selected. - if( !charSelected || - ( charInfo.mPosition.y - lastIt->mPosition.y > CHARACTER_THRESHOLD ) ) - { - // finished selection. - // TODO: TextView should have a table of visual rows, and each character a reference to the row - // that it resides on. That way this enumeration is not necessary. - Vector2 min, max; - if(lastIt->mIsNewParagraphChar) - { - // If the last character is a new line, then to get the row rect, we need to scan from the character before the new line. - lastIt = std::max( mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), lastIt - 1 ); - } - const Size rowSize( GetRowRectFromCharacterPosition( lastIt - mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), min, max ) ); - maxRowLeft = std::min(maxRowLeft, min.x); - maxRowRight = std::max(maxRowRight, max.x); - float rowBottom = lastIt->mPosition.y - mTextLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - - // Still selected, and block-align mode then set rowRight to max, so it can be clamped afterwards - if(charSelected) - { - rowRight = std::numeric_limits::max(); - } - mNewHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - - selectionState = SelectionNone; - - // Still selected? start a new selection - if( charSelected ) - { - // if block-align mode then set rowLeft to min, so it can be clamped afterwards - rowLeft = 0.0f; - rowRight = ( charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width; - selectionState = SelectionStarted; - } - } - else - { - // build up highlight(s) with this selection data. - rowLeft = std::min( charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x, rowLeft ); - rowRight = std::max( ( charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width, rowRight ); - } - } - - lastIt = it++; - } - - // If reached end, and still on selection, then close selection. - if(it == end) - { - if(selectionState == SelectionStarted) - { - // finished selection. - Vector2 min, max; - if(lastIt->mIsNewParagraphChar) - { - lastIt = std::max( mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), lastIt - 1 ); - } - const Size rowSize( GetRowRectFromCharacterPosition( lastIt - mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), min, max ) ); - maxRowLeft = std::min(maxRowLeft, min.x); - maxRowRight = std::max(maxRowRight, max.x); - float rowBottom = lastIt->mPosition.y - mTextLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - mNewHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - } - } - - // Get the top left and bottom right corners. - const Toolkit::TextView::CharacterLayoutInfo& firstCharacter( *mTextLayoutInfo.mCharacterLayoutInfoTable.begin() ); - const Vector2 topLeft( maxRowLeft, firstCharacter.mPosition.y - firstCharacter.mSize.height ); - const Vector2 bottomRight( topLeft.x + mTextLayoutInfo.mTextSize.width, topLeft.y + mTextLayoutInfo.mTextSize.height ); - - // Clamp quads so they appear to clip to borders of the whole text. - mNewHighlightInfo.Clamp2D( topLeft, bottomRight ); - - // For block-align align Further Clamp quads to max left and right extents - // BlockAlign: Will adjust highlight to block: - // i.e. - // H[ello] (top row right = max of all rows right) - // [--this-] (middle rows' left = min of all rows left, middle rows' right = max of all rows right) - // [is some] (middle rows' left = min of all rows left, middle rows' right = max of all rows right) - // [text] (bottom row left = min of all rows left) - // (common in SMS messaging selection) - // - // As opposed to the default which is tight text highlighting. - // H[ello] - // [this] - // [is some] - // [text] - // (common in regular text editors/web browser selection) - mNewHighlightInfo.Clamp2D( Vector2(maxRowLeft, topLeft.y), Vector2(maxRowRight, bottomRight.y ) ); - - // Finally clamp quads again so they don't exceed the boundry of the control. - const Vector3& controlSize = GetControlSize(); - mNewHighlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) ); - } // end if - - return mNewHighlightInfo; -} - -// VCC TODO: two methods are not needed. this one is a quick hack to fix PLMs. Should implement one which support both directions. -// This method creates one quad per character so different selection boxes for a mix of LTR and RTL languages are created. -TextInput::HighlightInfo TextInput::CalculateHighlightInfoRtl() -{ - // At the moment there is no public API to modify the block alignment option. - - mNewHighlightInfo.mQuadList.clear(); // clear last quad information. - - if ( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() && !mTextLayoutInfo.mCharacterLogicalToVisualMap.empty() ) - { - Toolkit::TextView::CharacterLayoutInfoContainer::iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin(); - Toolkit::TextView::CharacterLayoutInfoContainer::iterator end = mTextLayoutInfo.mCharacterLayoutInfoTable.end(); - - // Get vector of flags representing characters that are selected (true) vs unselected (false). - std::vector selectedVisualText; - GetVisualTextSelection( selectedVisualText, mSelectionHandleOnePosition, mSelectionHandleTwoPosition ); - std::vector::iterator selectedIt = selectedVisualText.begin(); - std::vector::iterator selectedEndIt = selectedVisualText.end(); - - // SelectionState selectionState = SelectionNone; ///< Current selection status of cursor over entire text. - float rowLeft = 0.0f; - float rowRight = 0.0f; - - // VCC TODO this is valid for one line. - Vector2 min, max; - const Size rowSize = GetRowRectFromCharacterPosition( 0, min, max ); - - // Scan through entire text. - while(it != end) - { - // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection. - - Toolkit::TextView::CharacterLayoutInfo& charInfo(*it); - bool charSelected = false; - if( selectedIt != selectedEndIt ) - { - charSelected = *selectedIt++; - } - - if( charSelected ) - { - rowLeft = charInfo.mPosition.x - mTextLayoutInfo.mScrollOffset.x; - rowRight = rowLeft + charInfo.mSize.width; - - float rowBottom = charInfo.mPosition.y - mTextLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - mNewHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - } - - ++it; - } - - // Finally clamp quads again so they don't exceed the boundry of the control. - const Vector3& controlSize = GetControlSize(); - mNewHighlightInfo.Clamp2D( Vector2::ZERO, Vector2(controlSize.x, controlSize.y) ); - } // end if - - return mNewHighlightInfo; -} - -void TextInput::UpdateHighlight() -{ -// Construct a Mesh with a texture to be used as the highlight 'box' for selected text -// -// Example scenarios where mesh is made from 3, 1, 2, 2 ,3 or 3 quads. -// -// [ TOP ] [ TOP ] [TOP ] [ TOP ] [ TOP ] [ TOP ] -// [ MIDDLE ] [BOTTOM] [BOTTOM] [ MIDDLE ] [ MIDDLE ] -// [ BOTTOM] [ MIDDLE ] [ MIDDLE ] -// [BOTTOM] [ MIDDLE ] -// [BOTTOM] -// -// Each quad is created as 2 triangles. -// Middle is just 1 quad regardless of its size. -// -// (0,0) (0,0) -// 0* *2 0* *2 -// TOP TOP -// 3* *1 3* *1 -// 4* *1 4* *6 -// MIDDLE BOTTOM -// 6* *5 7* *5 -// 6* *8 -// BOTTOM -// 9* *7 -// - -} - -void TextInput::ClearPopup() -{ - mPopupPanel.Clear(); -} - -void TextInput::AddPopupOptions() -{ - mPopupPanel.AddPopupOptions(); -} - -void TextInput::SetPopupPosition( const Vector3& position, const Vector2& alternativePosition ) -{ - const Vector3& visiblePopUpSize = mPopupPanel.GetVisibileSize(); - - Vector3 clampedPosition ( position ); - Vector3 tailOffsetPosition ( position ); - - float xOffSet( 0.0f ); - - Actor self = Self(); - const Vector3 textViewTopLeftWorldPosition = self.GetCurrentWorldPosition() - self.GetCurrentSize()*0.5f; - - const float popUpLeft = textViewTopLeftWorldPosition.x + position.x - visiblePopUpSize.width*0.5f; - const float popUpTop = textViewTopLeftWorldPosition.y + position.y - visiblePopUpSize.height; - - // Clamp to left or right or of boundary - if( popUpLeft < mBoundingRectangleWorldCoordinates.x ) - { - xOffSet = mBoundingRectangleWorldCoordinates.x - popUpLeft ; - } - else if ( popUpLeft + visiblePopUpSize.width > mBoundingRectangleWorldCoordinates.z ) - { - xOffSet = mBoundingRectangleWorldCoordinates.z - ( popUpLeft + visiblePopUpSize.width ); - } - - clampedPosition.x = position.x + xOffSet; - tailOffsetPosition.x = -xOffSet; - - // Check if top left of PopUp outside of top bounding rectangle, if so then flip to lower position. - bool flipTail( false ); - - if ( popUpTop < mBoundingRectangleWorldCoordinates.y ) - { - clampedPosition.y = alternativePosition.y + visiblePopUpSize.height; - flipTail = true; - } - - mPopupPanel.GetRootActor().SetPosition( clampedPosition ); - mPopupPanel.SetTailPosition( tailOffsetPosition, flipTail ); -} - -void TextInput::HidePopup(bool animate, bool signalFinished ) -{ - if ( ( mPopupPanel.GetState() == TextInputPopup::StateShowing ) || ( mPopupPanel.GetState() == TextInputPopup::StateShown ) ) - { - mPopupPanel.Hide( animate ); - - if( animate && signalFinished ) - { - mPopupPanel.HideFinishedSignal().Connect( this, &TextInput::OnPopupHideFinished ); - } - } -} - -void TextInput::ShowPopup( bool animate ) -{ - Vector3 position; - Vector2 alternativePopupPosition; - - if(false && mState == StateEdit) - { - Vector3 topHandle; - Vector3 bottomHandle; // referring to the bottom most point of the handle or the bottom line of selection. - Size rowSize; - // When text is selected, show popup above top handle (and text), or below bottom handle. - // topHandle: referring to the top most point of the handle or the top line of selection. - if ( mSelectionHandleTwoActualPosition.y > mSelectionHandleOneActualPosition.y ) - { - topHandle = mSelectionHandleOneActualPosition; - bottomHandle = mSelectionHandleTwoActualPosition; - rowSize= GetRowRectFromCharacterPosition( mSelectionHandleOnePosition ); - } - else - { - topHandle = mSelectionHandleTwoActualPosition; - bottomHandle = mSelectionHandleOneActualPosition; - rowSize = GetRowRectFromCharacterPosition( mSelectionHandleTwoPosition ); - } - topHandle.y += -mPopupOffsetFromText.y - rowSize.height; - position = Vector3(topHandle.x, topHandle.y, 0.0f); - - float xPosition = ( fabsf( topHandle.x - bottomHandle.x ) )*0.5f + std::min( mSelectionHandleOneActualPosition.x , mSelectionHandleTwoActualPosition.x ); - - position.x = xPosition; - - // Alternative position if no upper space - bottomHandle.y += GetSelectionHandleSize().y + mPopupOffsetFromText.w; - alternativePopupPosition = Vector2 ( position.x, bottomHandle.y ); - } - else - { - // When no text is selected, show popup at world position of grab handle or cursor - position = GetActualPositionFromCharacterPosition( mCursorPosition ); - const Size rowSize = GetRowRectFromCharacterPosition( mCursorPosition ); - position.y -= ( mPopupOffsetFromText.y + rowSize.height ); - // if can't be positioned above, then position below row. - alternativePopupPosition = Vector2( position.x, position.y ); // default if no grab handle - if ( mGrabHandle ) - { - // If grab handle enabled then position pop-up below the grab handle. - alternativePopupPosition.y = rowSize.height + mGrabHandle.GetCurrentSize().height + mPopupOffsetFromText.w +50.0f; - } - } - - SetPopupPosition( position, alternativePopupPosition ); - - // Show popup - mPopupPanel.Show( Self(), animate ); - StartMonitoringStageForTouch(); - - mPopupPanel.PressedSignal().Connect( this, &TextInput::OnPopupButtonPressed ); -} - -void TextInput::ShowPopupCutCopyPaste() -{ - ClearPopup(); - - mPopupPanel.CreateOrderedListOfOptions(); // todo Move this so only run when order has changed - // Check the selected text is whole text or not. - if( IsTextSelected() && ( mStyledText.size() != GetSelectedText().size() ) ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelectAll, true ); - } - - if ( !mStyledText.empty() && IsTextSelected() ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCopy, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, true ); - } - - if( mClipboard && mClipboard.NumberOfItems() ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsPaste, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsClipboard, true ); - } - - AddPopupOptions(); - - mPopupPanel.Hide(false); - ShowPopup(); -} - -void TextInput::SetUpPopupSelection( bool showCutButton ) -{ - ClearPopup(); - mPopupPanel.CreateOrderedListOfOptions(); // todo Move this so only run when order has changed - // If no text exists then don't offer to select - if ( !mStyledText.empty() ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelectAll, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsSelect, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsCut, ( showCutButton && IsTextSelected() ) ); - } - // if clipboard has valid contents then offer paste option - if( mClipboard && mClipboard.NumberOfItems() ) - { - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsPaste, true ); - mPopupPanel.TogglePopupButtonOnOff( TextInputPopup::ButtonsClipboard, true ); - } - - AddPopupOptions(); - - mPopupPanel.Hide(false); -} - -bool TextInput::ReturnClosestIndex(const Vector2& source, std::size_t& closestIndex ) -{ - bool found = false; - closestIndex = 0; - - std::vector matchedCharacters; - bool lastRightToLeftChar(false); /// RTL state of previous character encountered (character on the left of touch point) - bool rightToLeftChar(false); /// RTL state of current character encountered (character on the right of touch point) - float glyphIntersection(0.0f); /// Glyph intersection, the point between the two nearest characters touched. - - const Vector2 sourceScrollOffset( source + mTextLayoutInfo.mScrollOffset ); - - if ( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) - { - float closestYdifference = std::numeric_limits::max(); - std::size_t lineOffset = 0; /// Keep track of position of the first character on the matched line of interest. - std::size_t numberOfMatchedCharacters = 0; - - // 1. Find closest character line to y part of source, create vector of all entries in that Y position - // TODO: There should be an easy call to enumerate through each visual line, instead of each character on all visual lines. - - for( std::vector::const_iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin(), endIt = mTextLayoutInfo.mCharacterLayoutInfoTable.end(); it != endIt; ++it ) - { - const Toolkit::TextView::CharacterLayoutInfo& info( *it ); - float baselinePosition = info.mPosition.y - info.mDescender; - - if( info.mIsVisible ) - { - // store difference between source y point and the y position of the current character - float currentYdifference = fabsf( sourceScrollOffset.y - ( baselinePosition ) ); - - if( currentYdifference < closestYdifference ) - { - // closest so far; store this difference and clear previous matchedCharacters as no longer closest - lineOffset = it - mTextLayoutInfo.mCharacterLayoutInfoTable.begin(); - closestYdifference = currentYdifference; - matchedCharacters.clear(); - numberOfMatchedCharacters = 0; // reset count - } - - // add all characters that are on the same Y axis (within the CHARACTER_THRESHOLD) to the matched array. - if( fabsf( closestYdifference - currentYdifference ) < CHARACTER_THRESHOLD ) - { - // ignore new line character. - if( !info.mIsNewParagraphChar ) - { - matchedCharacters.push_back( info ); - numberOfMatchedCharacters++; - } - } - } - } // End of loop checking each character's y position in the character layout table - - // Check if last character is a newline, if it is - // then need pretend there is an imaginary line afterwards, - // and check if user is touching below previous line. - const Toolkit::TextView::CharacterLayoutInfo& lastInfo( mTextLayoutInfo.mCharacterLayoutInfoTable[mTextLayoutInfo.mCharacterLayoutInfoTable.size() - 1] ); - - if( ( lastInfo.mIsVisible ) && ( lastInfo.mIsNewParagraphChar ) && ( sourceScrollOffset.y > lastInfo.mPosition.y ) ) - { - closestIndex = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); - } - else - { - // 2 Iterate through matching list of y positions and find closest matching X position. - - bool matched( false ); - - // Traverse the characters in the visual order. VCC TODO: check for more than one line. - std::size_t visualIndex = 0u; - const std::size_t matchedCharactersSize = matchedCharacters.size(); - for( ; visualIndex < matchedCharactersSize; ++visualIndex ) - { - const Toolkit::TextView::CharacterLayoutInfo& info( *( matchedCharacters.begin() + mTextLayoutInfo.mCharacterVisualToLogicalMap[visualIndex] ) ); - - if( info.mIsVisible ) - { - // stop when on left side of character's center. - const float characterMidPointPosition = info.mPosition.x + ( info.mSize.width * 0.5f ) ; - if( sourceScrollOffset.x < characterMidPointPosition ) - { - if(info.mIsRightToLeftCharacter) - { - rightToLeftChar = true; - } - glyphIntersection = info.mPosition.x; - matched = true; - break; - } - - lastRightToLeftChar = info.mIsRightToLeftCharacter; - } - } - - if( visualIndex == matchedCharactersSize ) - { - rightToLeftChar = lastRightToLeftChar; - } - - closestIndex = lineOffset + visualIndex; - - mClosestCursorPositionEOL = false; // reset - if( ( visualIndex == matchedCharactersSize ) && !matched ) - { - mClosestCursorPositionEOL = true; // Reached end of matched characters in closest line but no match so cursor should be after last character. - } - - // For RTL characters, need to adjust closestIndex by 1 (as the inequality above would be reverse) - if( rightToLeftChar && lastRightToLeftChar ) - { - --closestIndex; // (-1 = numeric_limits::max()) - } - } - } - - // closestIndex is the visual index, need to convert it to the logical index - if( !mTextLayoutInfo.mCharacterVisualToLogicalMap.empty() ) - { - if( closestIndex < mTextLayoutInfo.mCharacterVisualToLogicalMap.size() ) - { - // Checks for situations where user is touching between LTR and RTL - // characters. To identify if the user means the end of a LTR string - // or the beginning of an RTL string, and vice versa. - if( closestIndex > 0 ) - { - if( rightToLeftChar && !lastRightToLeftChar ) - { - // [LTR] [RTL] - // |..|..| - // AAA BBB - // A: In this touch range, the user is indicating that they wish to place - // the cursor at the end of the LTR text. - // B: In this touch range, the user is indicating that they wish to place - // the cursor at the end of the RTL text. - - // Result of touching A area: - // [.....LTR]|[RTL......]+ - // - // |: primary cursor (for typing LTR chars) - // +: secondary cursor (for typing RTL chars) - - // Result of touching B area: - // [.....LTR]+[RTL......]| - // - // |: primary cursor (for typing RTL chars) - // +: secondary cursor (for typing LTR chars) - - if( sourceScrollOffset.x < glyphIntersection ) - { - --closestIndex; - } - } - else if( !rightToLeftChar && lastRightToLeftChar ) - { - if( sourceScrollOffset.x < glyphIntersection ) - { - --closestIndex; - } - } - } - - closestIndex = mTextLayoutInfo.mCharacterVisualToLogicalMap[closestIndex]; - // If user touched a left-side of RTL char, and the character on the left was an LTR then position logical cursor - // one further ahead - if( rightToLeftChar && !lastRightToLeftChar ) - { - ++closestIndex; - } - } - else if( closestIndex == std::numeric_limits::max() ) // -1 RTL (after last arabic character on line) - { - closestIndex = mTextLayoutInfo.mCharacterVisualToLogicalMap.size(); - } - else if( mTextLayoutInfo.mCharacterLayoutInfoTable[ mTextLayoutInfo.mCharacterVisualToLogicalMap[ closestIndex - 1 ] ].mIsRightToLeftCharacter ) // size() LTR (after last european character on line) - { - closestIndex = 0; - } - } - - return found; -} - -float TextInput::GetLineJustificationPosition() const -{ - const Vector3& size = mDisplayedTextView.GetCurrentSize(); - Toolkit::Alignment::Type alignment = mDisplayedTextView.GetTextAlignment(); - float alignmentOffset = 0.f; - - // Work out cursor 'x' position when there are any character accordingly with the text view alignment settings. - if( alignment & Toolkit::Alignment::HorizontalLeft ) - { - alignmentOffset = 0.f; - } - else if( alignment & Toolkit::Alignment::HorizontalCenter ) - { - alignmentOffset = 0.5f * ( size.width - mTextLayoutInfo.mTextSize.width ); - } - else if( alignment & Toolkit::Alignment::HorizontalRight ) - { - alignmentOffset = size.width - mTextLayoutInfo.mTextSize.width; - } - - Toolkit::TextView::LineJustification justification = mDisplayedTextView.GetLineJustification(); - float justificationOffset = 0.f; - - switch( justification ) - { - case Toolkit::TextView::Left: - { - justificationOffset = 0.f; - break; - } - case Toolkit::TextView::Center: - { - justificationOffset = 0.5f * mTextLayoutInfo.mTextSize.width; - break; - } - case Toolkit::TextView::Right: - { - justificationOffset = mTextLayoutInfo.mTextSize.width; - break; - } - case Toolkit::TextView::Justified: - { - justificationOffset = 0.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( false ); - } - } // end switch - - return alignmentOffset + justificationOffset; -} - -Vector3 TextInput::PositionCursorAfterWordWrap( std::size_t characterPosition ) const -{ - /* Word wrap occurs automatically in TextView when the exceed policy moves a word to the next line when not enough space on current. - A newline character is not inserted in this case */ - - Vector3 cursorPosition; - - Toolkit::TextView::CharacterLayoutInfo currentCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - - bool noWrap = true; - - if( characterPosition > 0u ) - { - Toolkit::TextView::CharacterLayoutInfo previousCharInfo = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition - 1u ]; - - // If previous character on a different line then use current characters position - if( fabsf( (currentCharInfo.mPosition.y - currentCharInfo.mDescender ) - ( previousCharInfo.mPosition.y - previousCharInfo.mDescender) ) > Math::MACHINE_EPSILON_1000 ) - { - // VCC TODO: PositionCursorAfterWordWrap currently doesn't work for multiline. Need to check this branch. - if ( mClosestCursorPositionEOL ) - { - cursorPosition = Vector3( previousCharInfo.mPosition.x + previousCharInfo.mSize.width, previousCharInfo.mPosition.y, previousCharInfo.mPosition.z ) ; - } - else - { - cursorPosition = Vector3( currentCharInfo.mPosition ); - } - - noWrap = false; - } - } - - if( noWrap ) - { - // If the character is left to right, the position is the character's position plus its width. - const float ltrOffset = !currentCharInfo.mIsRightToLeftCharacter ? currentCharInfo.mSize.width : 0.f; - - cursorPosition.x = currentCharInfo.mPosition.x + ltrOffset; - cursorPosition.y = currentCharInfo.mPosition.y; - } - - return cursorPosition; -} - -Vector3 TextInput::GetActualPositionFromCharacterPosition( std::size_t characterPosition ) const -{ - bool direction = false; - Vector3 alternatePosition; - bool alternatePositionValid = false; - - return GetActualPositionFromCharacterPosition( characterPosition, direction, alternatePosition, alternatePositionValid ); -} - -Vector3 TextInput::GetActualPositionFromCharacterPosition( std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const -{ - DALI_ASSERT_DEBUG( ( mTextLayoutInfo.mCharacterLayoutInfoTable.size() == mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ) && - ( mTextLayoutInfo.mCharacterLayoutInfoTable.size() == mTextLayoutInfo.mCharacterVisualToLogicalMap.size() ) && - "TextInput::GetActualPositionFromCharacterPosition. All layout tables must have the same size." ); - - Vector3 cursorPosition( 0.f, 0.f, 0.f ); - - alternatePositionValid = false; - directionRTL = false; - - if( !mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) - { - if( characterPosition == 0u ) - { - // When the cursor position is at the beginning, it should be at the start of the current character. - // If the current character is LTR, then the start is on the right side of the glyph. - // If the current character is RTL, then the start is on the left side of the glyph. - - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() ) ).mIsVisible ) - { - characterPosition = FindVisibleCharacter( Right, 0u ); - } - - const Toolkit::TextView::CharacterLayoutInfo& info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - const float rtlOffset = info.mIsRightToLeftCharacter ? info.mSize.width : 0.0f; - - cursorPosition.x = info.mPosition.x + rtlOffset; - cursorPosition.y = info.mPosition.y; - directionRTL = info.mIsRightToLeftCharacter; - } - else if( characterPosition > 0u ) - { - // Get the direction of the paragraph. - const std::size_t startCharacterPosition = GetRowStartFromCharacterPosition( characterPosition ); - const bool isParagraphRightToLeft = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + startCharacterPosition ) ).mIsRightToLeftCharacter; - - // When cursor is not at beginning, consider possibility of - // showing 2 cursors. (whereas at beginning we only ever show one cursor) - - // Cursor position should be the end of the last character. - // If the last character is LTR, then the end is on the right side of the glyph. - // If the last character is RTL, then the end is on the left side of the glyph. - - --characterPosition; - - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + characterPosition ) ).mIsVisible ) - { - characterPosition = FindVisibleCharacter( Left, characterPosition ); - } - - Toolkit::TextView::CharacterLayoutInfo info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - if( ( characterPosition > 0u ) && info.mIsNewParagraphChar && !IsScrollEnabled() ) - { - // VCC TODO : check for a new paragraph character. - - // Prevents the cursor to exceed the boundary if the last visible character is a 'new line character' and the scroll is not enabled. - const Vector3& size = GetControlSize(); - - if( info.mPosition.y + info.mSize.height - mDisplayedTextView.GetLineHeightOffset() > size.height ) - { - --characterPosition; - } - info = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - } - - if( !info.mIsNewParagraphChar ) - { - cursorPosition = PositionCursorAfterWordWrap( characterPosition ); // Get position of cursor/handles taking in account auto word wrap. - } - else - { - // VCC TODO : check for a new paragraph character. - - // When cursor points to first character on new line, position cursor at the start of this glyph. - if( characterPosition < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) - { - const Toolkit::TextView::CharacterLayoutInfo& infoNext = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterPosition ]; - const float start( infoNext.mIsRightToLeftCharacter ? infoNext.mSize.width : 0.0f ); - - cursorPosition.x = infoNext.mPosition.x + start; - cursorPosition.y = infoNext.mPosition.y; - } - else - { - // If cursor points to the end of text, then can only position - // cursor where the new line starts based on the line-justification position. - cursorPosition.x = GetLineJustificationPosition(); - - if( characterPosition == mTextLayoutInfo.mCharacterLogicalToVisualMap.size() ) - { - // If this is after the last character, then we can assume that the new cursor - // should be exactly one row below the current row. - - const Size rowRect = GetRowRectFromCharacterPosition( characterPosition - 1u ); - cursorPosition.y = info.mPosition.y + rowRect.height; - } - else - { - // If this is not after last character, then we can use this row's height. - // should be exactly one row below the current row. - - const Size rowRect = GetRowRectFromCharacterPosition( characterPosition ); - cursorPosition.y = info.mPosition.y + rowRect.height; - } - } - } - - directionRTL = info.mIsRightToLeftCharacter; - - if( 1u < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) - { - // 1. When the cursor is neither at the beginning or the end, - // we can show multiple cursors under situations when the cursor is - // between RTL and LTR text... - if( characterPosition + 1u < mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) - { - std::size_t characterAltPosition = characterPosition + 1u; - - const Toolkit::TextView::CharacterLayoutInfo& infoAlt = mTextLayoutInfo.mCharacterLayoutInfoTable[ characterAltPosition ]; - - if(!info.mIsRightToLeftCharacter && infoAlt.mIsRightToLeftCharacter) - { - // Stuation occurs when cursor is at the end of English text (LTR) and beginning of Arabic (RTL) - // Text: [...LTR...]|[...RTL...] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - alternatePosition.x = infoAlt.mPosition.x + infoAlt.mSize.width; - alternatePosition.y = infoAlt.mPosition.y; - alternatePositionValid = true; - } - else if(info.mIsRightToLeftCharacter && !infoAlt.mIsRightToLeftCharacter) - { - // Situation occurs when cursor is at end of the Arabic text (LTR) and beginning of English (RTL) - // Text: |[...RTL...] [...LTR....] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - alternatePosition.x = infoAlt.mPosition.x; - alternatePosition.y = infoAlt.mPosition.y; - alternatePositionValid = true; - } - } - else - { - // 2. When the cursor is at the end of the text, - // and we have multi-directional text, - // we can also consider showing mulitple cursors. - // The rule here is: - // If first and last characters on row are different - // Directions, then two cursors need to be displayed. - - if( info.mIsRightToLeftCharacter != isParagraphRightToLeft ) - { - // The last character's direction is differernt than the first one of current paragraph. - - // Get first - const Toolkit::TextView::CharacterLayoutInfo& infoStart= mTextLayoutInfo.mCharacterLayoutInfoTable[ GetFirstCharacterWithSameDirection( characterPosition ) ]; - - if(info.mIsRightToLeftCharacter) - { - // For text Starting as LTR and ending as RTL. End cursor position is as follows: - // Text: [...LTR...]|[...RTL...] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text, this cursor - // should be at the end of the given line. - - alternatePosition.x = infoStart.mPosition.x + infoStart.mSize.width; - alternatePosition.y = infoStart.mPosition.y; - alternatePositionValid = true; - } - else if(!info.mIsRightToLeftCharacter) // starting RTL - { - // For text Starting as RTL and ending as LTR. End cursor position is as follows: - // Text: |[...RTL...] [...LTR....] - // Cursor pos: ^ - // Alternate cursor pos: ^ - // In which case we need to display an alternate cursor for the RTL text. - - alternatePosition.x = infoStart.mPosition.x; - alternatePosition.y = infoStart.mPosition.y; - alternatePositionValid = true; - } - } - } - } - } // characterPosition > 0 - } - else - { - // If the character table is void, place the cursor accordingly the text alignment. - const Vector3& size = GetControlSize(); - - Toolkit::Alignment::Type alignment = mDisplayedTextView.GetTextAlignment(); - float alignmentOffset = 0.f; - - // Work out cursor 'x' position when there are any character accordingly with the text view alignment settings. - if( alignment & Toolkit::Alignment::HorizontalLeft ) - { - alignmentOffset = 0.f; - } - else if( alignment & Toolkit::Alignment::HorizontalCenter ) - { - alignmentOffset = 0.5f * ( size.width ); - } - else if( alignment & Toolkit::Alignment::HorizontalRight ) - { - alignmentOffset = size.width; - } - - // Work out cursor 'x' position when there are any character accordingly with the text view alignment settings. - cursorPosition.x = alignmentOffset; - - // Work out cursor 'y' position when there are any character accordingly with the text view alignment settings. - if( alignment & Toolkit::Alignment::VerticalTop ) - { - cursorPosition.y = mLineHeight; - } - else if( alignment & Toolkit::Alignment::VerticalCenter ) - { - cursorPosition.y = 0.5f * ( size.height + mLineHeight ); - } - else if( alignment & Toolkit::Alignment::VerticalBottom ) - { - cursorPosition.y = size.height; - } - } - - cursorPosition.x -= mTextLayoutInfo.mScrollOffset.x; - cursorPosition.y -= mTextLayoutInfo.mScrollOffset.y; - - if( alternatePositionValid ) - { - alternatePosition.x -= mTextLayoutInfo.mScrollOffset.x; - alternatePosition.y -= mTextLayoutInfo.mScrollOffset.y; - } - - return cursorPosition; -} - -std::size_t TextInput::GetRowStartFromCharacterPosition( std::size_t logicalPosition ) const -{ - // scan string from current position to beginning of current line to note direction of line - while( logicalPosition ) - { - logicalPosition--; - if( mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsNewParagraphChar ) - { - logicalPosition++; - break; - } - } - - return logicalPosition; -} - -std::size_t TextInput::GetFirstCharacterWithSameDirection( std::size_t logicalPosition ) const -{ - const bool isRightToLeft = mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsRightToLeftCharacter; - - while( logicalPosition ) - { - logicalPosition--; - if( isRightToLeft != mTextLayoutInfo.mCharacterLayoutInfoTable[logicalPosition].mIsRightToLeftCharacter ) - { - logicalPosition++; - break; - } - } - - return logicalPosition; -} - -Size TextInput::GetRowRectFromCharacterPosition(std::size_t characterPosition) const -{ - Vector2 min, max; - - return GetRowRectFromCharacterPosition( characterPosition, min, max ); -} - -Size TextInput::GetRowRectFromCharacterPosition( std::size_t characterPosition, Vector2& min, Vector2& max ) const -{ - // if we have no text content, then return position 0,0 with width 0, and height the same as cursor height. - if( mTextLayoutInfo.mCharacterLayoutInfoTable.empty() ) - { - min = Vector2::ZERO; - max = Vector2(0.0f, mLineHeight); - return max; - } - - DALI_ASSERT_DEBUG( characterPosition <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() ); - - // Initializes the min and max position. - const std::size_t initialPosition = ( characterPosition == mTextLayoutInfo.mCharacterLayoutInfoTable.size() ) ? characterPosition - 1u : characterPosition; - min = ( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + initialPosition ) ).mPosition.GetVectorXY(); - max = min; - - bool found = false; - // 1) Find the line where the character is laid-out. - for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineIt = mTextLayoutInfo.mLines.begin(), lineEndIt = mTextLayoutInfo.mLines.end(); - !found && ( lineIt != mTextLayoutInfo.mLines.end() ); - ++lineIt ) - { - const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineIt ); - - // Index within the whole text to the last character of the current line. - std::size_t lastCharacterOfLine = 0u; - - Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineNextIt = lineIt + 1u; - if( lineNextIt != lineEndIt ) - { - lastCharacterOfLine = (*lineNextIt).mCharacterGlobalIndex - 1u; - } - else - { - lastCharacterOfLine = mTextLayoutInfo.mCharacterLayoutInfoTable.size() - 1u; - } - - // Check if the given chracter position is within the line. - if( ( lineInfo.mCharacterGlobalIndex <= initialPosition ) && ( initialPosition <= lastCharacterOfLine ) ) - { - // 2) Get the row rect of all laid-out characters on the line. - - // Need to scan all characters of the line because they are in the logical position. - for( Toolkit::TextView::CharacterLayoutInfoContainer::const_iterator it = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + lineInfo.mCharacterGlobalIndex, - endIt = mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + lastCharacterOfLine + 1u; - it != endIt; - ++it ) - { - const Toolkit::TextView::CharacterLayoutInfo& characterInfo( *it ); - - min.x = std::min( min.x, characterInfo.mPosition.x ); - min.y = std::min( min.y, characterInfo.mPosition.y ); - max.x = std::max( max.x, characterInfo.mPosition.x + characterInfo.mSize.width ); - max.y = std::max( max.y, characterInfo.mPosition.y + characterInfo.mSize.height ); - } - - found = true; - } - } - - return Size( max.x - min.x, max.y - min.y ); -} - -bool TextInput::WasTouchedCheck( const Actor& touchedActor ) const -{ - Actor popUpPanel = mPopupPanel.GetRootActor(); - - if ( ( touchedActor == Self() ) || ( touchedActor == popUpPanel ) ) - { - return true; - } - else - { - Dali::Actor parent( touchedActor.GetParent() ); - - if ( parent ) - { - return WasTouchedCheck( parent ); - } - } - - return false; -} - -void TextInput::StartMonitoringStageForTouch() -{ - Stage stage = Stage::GetCurrent(); - stage.TouchedSignal().Connect( this, &TextInput::OnStageTouched ); -} - -void TextInput::EndMonitoringStageForTouch() -{ - Stage stage = Stage::GetCurrent(); - stage.TouchedSignal().Disconnect( this, &TextInput::OnStageTouched ); -} - -void TextInput::OnStageTouched(const TouchEvent& event) -{ - if( event.GetPointCount() > 0 ) - { - if ( TouchPoint::Down == event.GetPoint(0).state ) - { - const Actor touchedActor(event.GetPoint(0).hitActor); - - bool popUpShown( false ); - - if ( ( mPopupPanel.GetState() == TextInputPopup::StateShowing ) || ( mPopupPanel.GetState() == TextInputPopup::StateShown ) ) - { - popUpShown = true; - } - - bool textInputTouched = (touchedActor && WasTouchedCheck( touchedActor )); - - if ( ( false || popUpShown ) && !textInputTouched ) - { - EndMonitoringStageForTouch(); - HidePopup( true, false ); - } - - if ( ( IsGrabHandleEnabled() && mGrabHandle ) && !textInputTouched ) - { - EndMonitoringStageForTouch(); - ShowGrabHandleAndSetVisibility( false ); - } - } - } -} - -void TextInput::SelectText(std::size_t start, std::size_t end) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "SelectText mEditModeActive[%s] grabHandle[%s] start[%u] end[%u] size[%u]\n", mEditModeActive?"true":"false", - IsGrabHandleEnabled()?"true":"false", - start, end, mTextLayoutInfo.mCharacterLayoutInfoTable.size() ); - DALI_ASSERT_ALWAYS( start <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() && "TextInput::SelectText start out of max range" ); - DALI_ASSERT_ALWAYS( end <= mTextLayoutInfo.mCharacterLayoutInfoTable.size() && "TextInput::SelectText end out of max range" ); - - StartMonitoringStageForTouch(); - - if ( mEditModeActive ) // Only allow text selection when in edit mode - { - // When replacing highlighted text keyboard should ignore current word at cursor hence notify keyboard that the cursor is at the start of the highlight. - mSelectingText = true; - - std::size_t selectionStartPosition = std::min( start, end ); - - // Hide grab handle when selecting. - ShowGrabHandleAndSetVisibility( false ); - - if( start != end ) // something to select - { - SetCursorVisibility( false ); - StopCursorBlinkTimer(); - - CreateSelectionHandles(start, end); - UpdateHighlight(); - - const TextStyle oldInputStyle( mInputStyle ); - mInputStyle = GetStyleAt( selectionStartPosition ); // Inherit style from selected position. - - if( oldInputStyle != mInputStyle ) - { - // Updates the line height accordingly with the input style. - UpdateLineHeight(); - - EmitStyleChangedSignal(); - } - - HidePopup(); - } - - mSelectingText = false; - } -} - -MarkupProcessor::StyledTextArray TextInput::GetSelectedText() -{ - MarkupProcessor::StyledTextArray currentSelectedText; - - if ( IsTextSelected() ) - { - MarkupProcessor::StyledTextArray::iterator it = mStyledText.begin() + std::min(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - MarkupProcessor::StyledTextArray::iterator end = mStyledText.begin() + std::max(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - - for(; it != end; ++it) - { - MarkupProcessor::StyledText& styledText( *it ); - currentSelectedText.push_back( styledText ); - } - } - return currentSelectedText; -} - -void TextInput::ApplyStyleToRange(const TextStyle& style, const TextStyle::Mask mask, const std::size_t begin, const std::size_t end) -{ - const std::size_t beginIndex = std::min( begin, end ); - const std::size_t endIndex = std::max( begin, end ); - - // Apply the style - MarkupProcessor::SetTextStyleToRange( mStyledText, style, mask, beginIndex, endIndex ); - - // Create a styled text array used to replace the text into the text-view. - MarkupProcessor::StyledTextArray text; - text.insert( text.begin(), mStyledText.begin() + beginIndex, mStyledText.begin() + endIndex + 1 ); - - mDisplayedTextView.ReplaceTextFromTo( beginIndex, ( endIndex - beginIndex ) + 1, text ); - GetTextLayoutInfo(); - - if( IsScrollEnabled() ) - { - // Need to set the scroll position as the text's size may have changed. - ScrollTextViewToMakeCursorVisible( Vector3( mTextLayoutInfo.mScrollOffset.x, mTextLayoutInfo.mScrollOffset.y, 0.f ) ); - } - - ShowGrabHandleAndSetVisibility( false ); - - DrawCursor(); - - UpdateHighlight(); - - // Set Handle positioning as the new style may have repositioned the characters. - SetSelectionHandlePosition(HandleOne); - SetSelectionHandlePosition(HandleTwo); -} - -void TextInput::KeyboardStatusChanged(bool keyboardShown) -{ - // Just hide the grab handle when keyboard is hidden. - if (!keyboardShown ) - { - ShowGrabHandleAndSetVisibility( false ); - - // If the keyboard is not now being shown, then hide the popup panel - mPopupPanel.Hide( true ); - } -} - -// Removes highlight and resumes edit mode state -void TextInput::RemoveHighlight( bool hidePopup ) -{ - DALI_LOG_INFO(gLogFilter, Debug::General, "RemoveHighlight\n"); - - if ( false ) - { - if ( mSelectionHandleOne ) - { - mActiveLayer.Remove( mSelectionHandleOne ); - mSelectionHandleOne.Reset(); - mSelectionHandleOneOffset.x = 0.0f; - } - if ( mSelectionHandleTwo ) - { - mActiveLayer.Remove( mSelectionHandleTwo ); - mSelectionHandleTwo.Reset(); - mSelectionHandleTwoOffset.x = 0.0f; - } - - mNewHighlightInfo.mQuadList.clear(); - - - SetCursorVisibility( true ); - StartCursorBlinkTimer(); - - // NOTE: We cannot dereference mHighlightMesh, due - // to a bug in how the scene-graph MeshRenderer uses the Mesh data incorrectly. - - if ( hidePopup ) - { - HidePopup(); - } - } - - mSelectionHandleOnePosition = 0; - mSelectionHandleTwoPosition = 0; -} - -void TextInput::CreateHighlight() -{ -} - - -bool TextInput::CopySelectedTextToClipboard() -{ - mCurrentCopySelecton.clear(); - - mCurrentCopySelecton = GetSelectedText(); - - std::string stringToStore; - - /* Create a StyledTextArray from the selected region so can use the MarkUpProcessor to produce - * a marked up string. - */ - MarkupProcessor::StyledTextArray selectedText(mCurrentCopySelecton.begin(),mCurrentCopySelecton.end()); - MarkupProcessor::GetPlainString( selectedText, stringToStore ); - - bool success = mClipboard.SetItem( stringToStore ); - return success; -} - -void TextInput::PasteText( const Text& text ) -{ - // Update Flag, indicates whether to update the text-input contents or not. - // Any key stroke that results in a visual change of the text-input should - // set this flag to true. - bool update = false; - if( false ) - { - /* if highlighted, delete entire text, and position cursor at start of deleted text. */ - mCursorPosition = std::min(mSelectionHandleOnePosition, mSelectionHandleTwoPosition); - - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - DeleteHighlightedText( true ); - update = true; - } - - bool textExceedsMaximunNumberOfCharacters = false; - bool textExceedsBoundary = false; - - std::size_t insertedStringLength = DoInsertAt( text, mCursorPosition, 0, textExceedsMaximunNumberOfCharacters, textExceedsBoundary ); - - mCursorPosition += insertedStringLength; - ImfManager imfManager = ImfManager::Get(); - if ( imfManager ) - { - imfManager.SetCursorPosition ( mCursorPosition ); - imfManager.NotifyCursorPosition(); - } - - update = update || ( insertedStringLength > 0 ); - if( update ) - { - CursorUpdate(); - EmitTextModified(); - } - - if( insertedStringLength < text.GetLength() ) - { - EmitMaxInputCharactersReachedSignal(); - } - - if( textExceedsBoundary ) - { - EmitInputTextExceedsBoundariesSignal(); - } -} - -void TextInput::SetTextDirection() -{ - // Put the cursor to the right if we are empty and an RTL language is being used. - if ( mStyledText.empty() ) - { - VirtualKeyboard::TextDirection direction( VirtualKeyboard::GetTextDirection() ); - - // Get the current text alignment preserving the vertical alignment. Also preserve the horizontal center - // alignment as we do not want to set the text direction if we've been asked to be in the center. - // - // TODO: Should split SetTextAlignment into two APIs to better handle this (sometimes apps just want to - // set vertical alignment but are being forced to set the horizontal alignment as well with the - // current API. - int alignment( mDisplayedTextView.GetTextAlignment() & - ( Toolkit::Alignment::VerticalTop | - Toolkit::Alignment::VerticalCenter | - Toolkit::Alignment::VerticalBottom | - Toolkit::Alignment::HorizontalCenter ) ); - Toolkit::TextView::LineJustification justification( mDisplayedTextView.GetLineJustification() ); - - // If our alignment is in the center, then do not change. - if ( !( alignment & Toolkit::Alignment::HorizontalCenter ) ) - { - alignment |= ( direction == VirtualKeyboard::LeftToRight ) ? Toolkit::Alignment::HorizontalLeft : Toolkit::Alignment::HorizontalRight; - } - - // If our justification is in the center, then do not change. - if ( justification != Toolkit::TextView::Center ) - { - justification = ( direction == VirtualKeyboard::LeftToRight ) ? Toolkit::TextView::Left : Toolkit::TextView::Right; - } - - mDisplayedTextView.SetTextAlignment( static_cast(alignment) ); - mDisplayedTextView.SetLineJustification( justification ); - } -} - -void TextInput::UpdateLineHeight() -{ - Dali::Font font = Dali::Font::New( FontParameters( mInputStyle.GetFontName(), mInputStyle.GetFontStyle(), mInputStyle.GetFontPointSize() ) ); - mLineHeight = font.GetLineHeight(); - - // If the height exceed policy is shrink or exceed the boundaries of the text-input is not allowed, then modify the line height is needed. - - const bool shrink = mDisplayedTextView && ( Toolkit::TextView::ShrinkToFit == mDisplayedTextView.GetHeightExceedPolicy() ) && mStyledText.empty(); - - if( !mExceedEnabled || shrink ) - { - mLineHeight = std::min( mLineHeight, GetControlSize().height ); - } -} - -std::size_t TextInput::FindVisibleCharacter( FindVisibleCharacterDirection direction , std::size_t cursorPosition ) const -{ - // VCC check if we need do this in the visual order ... - std::size_t position = 0u; - - const std::size_t tableSize = mTextLayoutInfo.mCharacterLayoutInfoTable.size(); - - switch( direction ) - { - case Left: - { - position = FindVisibleCharacterLeft( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + ( tableSize == position ? position - 1u : position ) ) ).mIsVisible ) - { - position = FindVisibleCharacterRight( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - } - break; - } - case Right: - { - position = FindVisibleCharacterRight( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - if( !( *( mTextLayoutInfo.mCharacterLayoutInfoTable.begin() + ( tableSize == position ? position - 1u : position ) ) ).mIsVisible ) - { - position = FindVisibleCharacterLeft( cursorPosition, mTextLayoutInfo.mCharacterLayoutInfoTable ); - } - break; - } - case ByEnd: - { - position = FindVisibleCharacterLeft( 0u, mTextLayoutInfo.mCharacterLayoutInfoTable ); - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextInput::FindVisibleCharacter() Unknown direction." ); - } - } - - return position; -} - -void TextInput::SetSortModifier( float depthOffset ) -{ - if(mDisplayedTextView) - { - mDisplayedTextView.SetSortModifier(depthOffset); - } -} - -void TextInput::SetSnapshotModeEnabled( bool enable ) -{ - if(mDisplayedTextView) - { - mDisplayedTextView.SetSnapshotModeEnabled( enable ); - } -} - -bool TextInput::IsSnapshotModeEnabled() const -{ - bool snapshotEnabled = false; - - if(mDisplayedTextView) - { - snapshotEnabled = mDisplayedTextView.IsSnapshotModeEnabled(); - } - - return snapshotEnabled; -} - -void TextInput::SetMarkupProcessingEnabled( bool enable ) -{ - mMarkUpEnabled = enable; -} - -bool TextInput::IsMarkupProcessingEnabled() const -{ - return mMarkUpEnabled; -} - -void TextInput::SetScrollEnabled( bool enable ) -{ - if( mDisplayedTextView ) - { - mDisplayedTextView.SetScrollEnabled( enable ); - } - - if( !enable ) - { - // Don't set cursor's and handle's visibility to false if they are outside the - // boundaries of the text-input. - mIsCursorInScrollArea = true; - mIsGrabHandleInScrollArea = true; - if( mSelectionHandleOne && mSelectionHandleTwo ) - { - mSelectionHandleOne.SetVisible( true ); - mSelectionHandleTwo.SetVisible( true ); - - } - } -} - -bool TextInput::IsScrollEnabled() const -{ - bool scrollEnabled = false; - - if( mDisplayedTextView ) - { - scrollEnabled = mDisplayedTextView.IsScrollEnabled(); - } - - return scrollEnabled; -} - -void TextInput::SetScrollPosition( const Vector2& position ) -{ - if( mDisplayedTextView ) - { - mDisplayedTextView.SetScrollPosition( position ); - } -} - -Vector2 TextInput::GetScrollPosition() const -{ - Vector2 scrollPosition; - - if( mDisplayedTextView ) - { - scrollPosition = mDisplayedTextView.GetScrollPosition(); - } - - return scrollPosition; -} - -std::size_t TextInput::DoInsertAt( const Text& text, const std::size_t position, const std::size_t numberOfCharactersToReplace, bool& textExceedsMaximunNumberOfCharacters, bool& textExceedsBoundary ) -{ - // determine number of characters that we can write to style text buffer, this is the insertStringLength - std::size_t insertedStringLength = std::min( text.GetLength(), mMaxStringLength - mStyledText.size() ); - textExceedsMaximunNumberOfCharacters = insertedStringLength < text.GetLength(); - - // Add style to the new input text. - MarkupProcessor::StyledTextArray textToInsert; - for( std::size_t i = 0; i < insertedStringLength; ++i ) - { - const MarkupProcessor::StyledText newStyledCharacter( text[i], mInputStyle ); - textToInsert.push_back( newStyledCharacter ); - } - - //Insert text to the TextView. - const bool emptyTextView = mStyledText.empty(); - if( emptyTextView && mPlaceHolderSet ) - { - // There is no text set so call to TextView::SetText() is needed in order to clear the placeholder text. - mDisplayedTextView.SetText( textToInsert ); - } - else - { - if( 0 == numberOfCharactersToReplace ) - { - mDisplayedTextView.InsertTextAt( position, textToInsert ); - } - else - { - mDisplayedTextView.ReplaceTextFromTo( position, numberOfCharactersToReplace, textToInsert ); - } - } - mPlaceHolderSet = false; - - if( textToInsert.empty() ) - { - // If no text has been inserted, GetTextLayoutInfo() need to be called to check whether mStyledText has some text. - GetTextLayoutInfo(); - } - else - { - // GetTextLayoutInfo() can't be used here as mStyledText is not updated yet. - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - } - - textExceedsBoundary = false; - - if( !mExceedEnabled ) - { - const Vector3& size = GetControlSize(); - - if( ( mTextLayoutInfo.mTextSize.width > size.width ) || ( mTextLayoutInfo.mTextSize.height > size.height ) ) - { - // If new text does not fit within TextView - mDisplayedTextView.RemoveTextFrom( position, insertedStringLength ); - // previously inserted text has been removed. Call GetTextLayoutInfo() to check whether mStyledText has some text. - GetTextLayoutInfo(); - textExceedsBoundary = true; - insertedStringLength = 0; - } - - if( textExceedsBoundary ) - { - // Add the part of the text which fits on the text-input. - - // Split the text which doesn't fit in two halves. - MarkupProcessor::StyledTextArray firstHalf; - MarkupProcessor::StyledTextArray secondHalf; - SplitText( textToInsert, firstHalf, secondHalf ); - - // Clear text. This text will be filled with the text inserted. - textToInsert.clear(); - - // Where to insert the text. - std::size_t positionToInsert = position; - - bool end = text.GetLength() <= 1; - while( !end ) - { - // Insert text and check ... - const std::size_t textLength = firstHalf.size(); - mDisplayedTextView.InsertTextAt( positionToInsert, firstHalf ); - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - - if( ( mTextLayoutInfo.mTextSize.width > size.width ) || ( mTextLayoutInfo.mTextSize.height > size.height ) ) - { - // Inserted text doesn't fit. - - // Remove inserted text - mDisplayedTextView.RemoveTextFrom( positionToInsert, textLength ); - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - - // The iteration finishes when only one character doesn't fit. - end = textLength <= 1; - - if( !end ) - { - // Prepare next two halves for next iteration. - MarkupProcessor::StyledTextArray copyText = firstHalf; - SplitText( copyText, firstHalf, secondHalf ); - } - } - else - { - // Text fits. - - // store text to be inserted in mStyledText. - textToInsert.insert( textToInsert.end(), firstHalf.begin(), firstHalf.end() ); - - // Increase the inserted characters counter. - insertedStringLength += textLength; - - // Prepare next two halves for next iteration. - MarkupProcessor::StyledTextArray copyText = secondHalf; - SplitText( copyText, firstHalf, secondHalf ); - - // Update where next text has to be inserted - positionToInsert += textLength; - } - } - } - } - - if( textToInsert.empty() && emptyTextView ) - { - // No character has been added and the text-view was empty. - // Show the placeholder text. - ShowPlaceholderText( mStyledPlaceHolderText ); - } - else - { - MarkupProcessor::StyledTextArray::iterator it = mStyledText.begin() + position; - mStyledText.insert( it, textToInsert.begin(), textToInsert.end() ); - mPlaceHolderSet = false; - } - - return insertedStringLength; -} - -void TextInput::GetTextLayoutInfo() -{ - if( mStyledText.empty() ) - { - // The text-input has no text, clear the text-view's layout info. - mTextLayoutInfo = Toolkit::TextView::TextLayoutInfo(); - } - else - { - if( mDisplayedTextView ) - { - mDisplayedTextView.GetTextLayoutInfo( mTextLayoutInfo ); - } - else - { - // There is no text-view. - mTextLayoutInfo = Toolkit::TextView::TextLayoutInfo(); - } - } -} - -void TextInput::SetOffsetFromText( const Vector4& offset ) -{ - mPopupOffsetFromText = offset; -} - -const Vector4& TextInput::GetOffsetFromText() const -{ - return mPopupOffsetFromText; -} - -void TextInput::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value ) -{ - Toolkit::TextInput textInput = Toolkit::TextInput::DownCast( Dali::BaseHandle( object ) ); - - if ( textInput ) - { - TextInput& textInputImpl( GetImpl( textInput ) ); - - switch ( propertyIndex ) - { - case Toolkit::TextInput::Property::HIGHLIGHT_COLOR: - { - textInputImpl.SetMaterialDiffuseColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_PRESSED_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupPressedColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_BORDER_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupBorderColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_ICON_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupIconColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_ICON_PRESSED_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupIconPressedColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_TEXT_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupTextColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_TEXT_PRESSED_COLOR: - { - textInputImpl.mPopupPanel.SetCutPastePopupTextPressedColor( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CUT_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsCut, value.Get() ); - break; - } - case Toolkit::TextInput::Property::COPY_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsCopy, value.Get() ); - break; - } - case Toolkit::TextInput::Property::PASTE_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsPaste, value.Get() ); - break; - } - case Toolkit::TextInput::Property::SELECT_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsSelect, value.Get() ); - break; - } - case Toolkit::TextInput::Property::SELECT_ALL_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsSelectAll, value.Get() ); - break; - } - case Toolkit::TextInput::Property::CLIPBOARD_BUTTON_POSITION_PRIORITY: - { - textInputImpl.mPopupPanel.SetButtonPriorityPosition( TextInputPopup::ButtonsClipboard, value.Get() ); - break; - } - case Toolkit::TextInput::Property::POP_UP_OFFSET_FROM_TEXT: - { - textInputImpl.SetOffsetFromText( value.Get< Vector4 >() ); - break; - } - case Toolkit::TextInput::Property::CURSOR_COLOR: - { - textInputImpl.mCursor.SetColor( value.Get< Vector4 >() ); - break; - } - } - } -} - -Property::Value TextInput::GetProperty( BaseObject* object, Property::Index propertyIndex ) -{ - Property::Value value; - - Toolkit::TextInput textInput = Toolkit::TextInput::DownCast( Dali::BaseHandle( object ) ); - - if ( textInput ) - { - TextInput& textInputImpl( GetImpl( textInput ) ); - - switch ( propertyIndex ) - { - case Toolkit::TextInput::Property::HIGHLIGHT_COLOR: - { - value = textInputImpl.GetMaterialDiffuseColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_PRESSED_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupPressedColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_BORDER_COLOR : - { - value = textInputImpl.mPopupPanel.GetCutPastePopupBorderColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_ICON_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupIconColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_ICON_PRESSED_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupIconPressedColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_TEXT_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupTextColor(); - break; - } - case Toolkit::TextInput::Property::CUT_AND_PASTE_TEXT_PRESSED_COLOR: - { - value = textInputImpl.mPopupPanel.GetCutPastePopupTextPressedColor(); - break; - } - case Toolkit::TextInput::Property::CUT_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsCut ); - break; - } - case Toolkit::TextInput::Property::COPY_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsCopy ); - break; - } - case Toolkit::TextInput::Property::PASTE_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsPaste ); - break; - } - case Toolkit::TextInput::Property::SELECT_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsSelect ); - break; - } - case Toolkit::TextInput::Property::SELECT_ALL_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsSelectAll ); - break; - } - case Toolkit::TextInput::Property::CLIPBOARD_BUTTON_POSITION_PRIORITY: - { - value = textInputImpl.mPopupPanel.GetButtonPriorityPosition( TextInputPopup::ButtonsClipboard ); - break; - } - case Toolkit::TextInput::Property::POP_UP_OFFSET_FROM_TEXT: - { - value = textInputImpl.GetOffsetFromText(); - break; - } - case Toolkit::TextInput::Property::CURSOR_COLOR: - { - value = textInputImpl.mCursor.GetCurrentColor(); - } - } - } - return value; -} - -void TextInput::EmitStyleChangedSignal() -{ - // emit signal if input style changes. - Toolkit::TextInput handle( GetOwner() ); - mStyleChangedSignal.Emit( handle, mInputStyle ); -} - -void TextInput::EmitTextModified() -{ - // emit signal when text changes. - Toolkit::TextInput handle( GetOwner() ); - mTextModifiedSignal.Emit( handle ); -} - - -void TextInput::EmitMaxInputCharactersReachedSignal() -{ - // emit signal if max characters is reached during text input. - DALI_LOG_INFO(gLogFilter, Debug::General, "EmitMaxInputCharactersReachedSignal \n"); - - Toolkit::TextInput handle( GetOwner() ); - mMaxInputCharactersReachedSignal.Emit( handle ); -} - -void TextInput::EmitInputTextExceedsBoundariesSignal() -{ - // Emit a signal when the input text exceeds the boundaries of the text input. - - Toolkit::TextInput handle( GetOwner() ); - mInputTextExceedBoundariesSignal.Emit( handle ); -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-input/text-input-impl.h b/dali-toolkit/internal/controls/text-input/text-input-impl.h deleted file mode 100644 index 6dfe840..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-impl.h +++ /dev/null @@ -1,1563 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_H__ - -/* - * Copyright (c) 2014 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 -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class TextInput; -class TextView; - -typedef IntrusivePtr TextInputPtr; - -class TextInput : public Control -{ -public: - - /** - * Create a new TextInput - * @return instrusive ptr to a TextInput - */ - static Dali::Toolkit::TextInput New(); - - /** - * @copydoc Toolkit::TextInput::GetText - */ - std::string GetText() const; - - /** - * @copydoc Toolkit::TextInput::GetMarkupText() - */ - std::string GetMarkupText() const; - - /** - * @copydoc Toolkit::TextInput::SetPlaceholderText - */ - void SetPlaceholderText( const std::string& placeHolderText ); - - /** - * @copydoc Toolkit::TextInput::SetPlaceholderText - */ - std::string GetPlaceholderText(); - - /** - * @copydoc Toolkit::TextInput::SetInitialText - */ - void SetInitialText(const std::string& initialText); - - /** - * set the text to be displayed in text-input, will overwrite any existing text. - * can be used to clear the text-input by passing an empty string. - * @param [in] initialText text to be initially displayed - */ - void SetText(const std::string& initialText); - - /** - * @copydoc Toolkit::TextInput::SetMaxCharacterLength - */ - void SetMaxCharacterLength(std::size_t maxChars); - - /** - * @copydoc Toolkit::TextInput::SetNumberOfLinesLimit - */ - void SetNumberOfLinesLimit(std::size_t maxLines); - - /** - * @copydoc Toolkit::TextInput::GetNumberOfLinesLimit - */ - std::size_t GetNumberOfLinesLimit() const; - - /** - * @copydoc Toolkit::TextInput::GetFont - */ - Font GetFont() const; - - /** - * @copydoc Toolkit::TextInput::SetFont - */ - void SetFont(Font font); - - /** - * @copydoc Toolkit::TextInput::InputStartedSignal() - */ - Toolkit::TextInput::InputSignalType& InputStartedSignal(); - - /** - * @copydoc Toolkit::TextInput::InputFinishedSignal() - */ - Toolkit::TextInput::InputSignalType& InputFinishedSignal(); - - /** - * @copydoc Toolkit::TextInput::CutAndPasteToolBarDisplayedSignal() - */ - Toolkit::TextInput::InputSignalType& CutAndPasteToolBarDisplayedSignal(); - - /** - * @copydoc Toolkit::TextInput::StyleChangedSignal() - */ - Toolkit::TextInput::StyleChangedSignalType& StyleChangedSignal(); - - /** - * @copydoc Toolkit::TextInput::TextModifiedSignal() - */ - Toolkit::TextInput::TextModifiedSignalType& TextModifiedSignal(); - - /** - * @copydoc Toolkit::TextInput::MaxInputCharactersReachedSignal() - */ - Toolkit::TextInput::MaxInputCharactersReachedSignalType& MaxInputCharactersReachedSignal(); - - /** - * @copydoc Toolkit::TextInput::InputTextExceedBoundariesSignal() - */ - Toolkit::TextInput::InputTextExceedBoundariesSignalType& InputTextExceedBoundariesSignal(); - - /** - * Connects a callback function with the object's signals. - * @param[in] object The object providing the signal. - * @param[in] tracker Used to disconnect the signal. - * @param[in] signalName The signal to connect to. - * @param[in] functor A newly allocated FunctorDelegate. - * @return True if the signal was connected. - * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor. - */ - static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ); - - /** - * @see Toolkit::TextInput::SetEditMode(bool editMode) - * @see Toolkit::TextInput::SetEditMode(bool editMode, const Vector2& touchPoint) - * - * @param[in] editMode true or false to indicate editMode on or off. - * @param[in] setCursorOnTouchPoint Whether to use the touch point to set the cursor position. - * @param[in] touchPoint A position in actor coordinates within the text-input. - */ - void SetEditable(bool editMode, bool setCursorOnTouchPoint, const Vector2& touchPoint = Vector2::ZERO); - - /** - * @copydoc Toolkit::TextInput::GetEditMode - */ - bool IsEditable() const; - - /** - * @copydoc Toolkit::TextInput::SetTextSelectable - */ - void SetTextSelectable(bool textSelectable = true); - - /** - * @copydoc Toolkit::TextInput::IsTextSelectable - */ - bool IsTextSelectable() const; - - /** - * @copydoc Toolkit::TextInput::IsTextSelected - */ - bool IsTextSelected() const; - - /** - * @copydoc Toolkit::TextInput::DeSelectText - */ - void DeSelectText(); - - /** - * @copydoc Toolkit::TextInput::SetEditOnTouch - */ - void SetEditOnTouch(bool editOnTouch); - - /** - * @copydoc Toolkit::TextInput::IsEditOnTouch - */ - bool IsEditOnTouch() const; - - /** - * @copydoc Toolkit::TextInput::SetGrabHandleImage - */ - void SetGrabHandleImage(Dali::Image image); - - /** - * @copydoc Toolkit::TextInput::SetCursorImage - */ - void SetCursorImage(Dali::Image image, const Vector4& border ); - - /** - * @copydoc Toolkit::TextInput::GetSelectionHandleSize - */ - Vector3 GetSelectionHandleSize(); - - /** - * @copydoc Toolkit::TextInput::SetRTLCursorImage - */ - void SetRTLCursorImage(Dali::Image image, const Vector4& border ); - - /** - * @copydoc Toolkit::TextInput::EnableGrabHandle - */ - void EnableGrabHandle(bool toggle); - - /** - * @copydoc Toolkit::TextInput::IsGrabHandleEnabled - */ - bool IsGrabHandleEnabled(); - - /** - * @copydoc Toolkit::TextInput::EnableSelectionHandleFlip - */ - void EnableSelectionHandleFlip( bool toggle ); - - /** - * @copydoc Toolkit::TextInput::IsSelectionHandleFlipEnabled - */ - bool IsSelectionHandleFlipEnabled(); - - /** - * @copydoc Toolkit::TextInput::SetSelectionHandleFlipMargin - */ - void SetSelectionHandleFlipMargin( const Vector4& margin ); - - /** - * @copydoc Toolkit::TextInput::SetBoundingRectangle - */ - void SetBoundingRectangle( const Rect& boundingRectangle ); - - /** - * @copydoc Toolkit::TextInput::GetBoundingRectangle - */ - const Rect GetBoundingRectangle() const; - - /** - * @copydoc Toolkit::TextInput::GetSelectionHandleFlipMargin - */ - const Vector4& GetSelectionHandleFlipMargin(); - - /** - * @copydoc Toolkit::TextInput::SetTextColor - */ - void SetTextColor( const Vector4& color ); - - /** - * @copydoc Toolkit::TextInput::SetActiveStyle - */ - void SetActiveStyle( const TextStyle& style, const TextStyle::Mask mask ); - - /** - * @copydoc Toolkit::TextInput::ApplyStyle - */ - void ApplyStyle( const TextStyle& style, const TextStyle::Mask mask ); - - /** - * @copydoc Toolkit::TextInput::ApplyStyleToAll - */ - void ApplyStyleToAll( const TextStyle& style, const TextStyle::Mask mask ); - - /** - * @copydoc Toolkit::TextInput::GetStyleAtCursor - */ - TextStyle GetStyleAtCursor() const; - - /** - * Retrieves the character style for the given position. - * @param[in] position The character position which style is required. - * @return The style for the given position. - */ - TextStyle GetStyleAt( std::size_t position ) const; - - /** - * @copydoc Toolkit::TextInput::SetTextAlignment() - */ - void SetTextAlignment( Toolkit::Alignment::Type align ); - - /** - * @copydoc Toolkit::TextInput::SetTextLineJustification() - */ - void SetTextLineJustification( Toolkit::TextView::LineJustification justification ); - - /** - * @copydoc Toolkit::TextInput::SetFadeBoundary() - */ - void SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ); - - /** - * @copydoc Toolkit::TextInput::GetFadeBoundary() - */ - const Toolkit::TextView::FadeBoundary& GetFadeBoundary() const; - - /** - * @copydoc Toolkit::TextInput::GetTextAlignment() - */ - Toolkit::Alignment::Type GetTextAlignment() const; - - /** - * @copydoc Toolkit::TextInput::SetMultilinePolicy() - */ - void SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ); - - /** - * @copydoc Toolkit::TextInput::GetMultilinePolicy() - */ - Toolkit::TextView::MultilinePolicy GetMultilinePolicy() const; - - /** - * @copydoc Toolkit::TextInput::SetWidthExceedPolicy() - */ - void SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @copydoc Toolkit::TextInput::GetWidthExceedPolicy() - */ - Toolkit::TextView::ExceedPolicy GetWidthExceedPolicy() const; - - /** - * @copydoc Toolkit::TextInput::SetHeightExceedPolicy() - */ - void SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @copydoc Toolkit::TextInput::GetHeightExceedPolicy() - */ - Toolkit::TextView::ExceedPolicy GetHeightExceedPolicy() const; - - /** - * @copydoc Toolkit::TextInput::SetExceedEnabled() - */ - void SetExceedEnabled( bool enable ); - - /** - * @copydoc Toolkit::TextInput::GetExceedEnabled() - */ - bool GetExceedEnabled() const; - - /** - * @copydoc Toolkit::TextInput::SetBackground - */ - void SetBackground(Dali::Image image ); - - /** - * @copydoc Toolkit::TextInput::SetNumberOfLines - */ - void SetNumberOfLines(std::size_t lines); - - /** - * @copydoc Toolkit::TextInput::GetNumberOfLines - */ - std::size_t GetNumberOfLines(); - - /** - * @copydoc Toolkit::TextInput::GetNumberOfCharacters - */ - std::size_t GetNumberOfCharacters() const; - - /** - * Styling - */ - - /** - * Set the diffuse color for the highlight - * @param[in] color color to use - */ - void SetMaterialDiffuseColor( const Vector4& color ); - - /** - * Get the diffuse color used by the highlight - * @return color - */ - const Vector4& GetMaterialDiffuseColor() const; - -private: - - /** - * structure to hold each highlight box needed for text selection - */ - struct HighlightBox - { - Vector3 size; ///< size of the highlight box - Vector3 position; ///< position of highlight box - ImageActor highlightBoxActor; ///< as actor that is the highlight box - }; - - /** - * structure to hold each character in displayed string and its position from the left - */ - struct CharPositions - { - char character; ///< todo change to UTF to aid multi-language support - Vector3 position; - Vector2 size; - }; - - /** - * structure to hold coordinates of each quad, which will make up the mesh. - */ - struct QuadCoordinates - { - /** - * Default constructor - */ - QuadCoordinates() - { - } - - /** - * Constructor - * @param[in] x1 left co-ordinate - * @param[in] y1 top co-ordinate - * @param[in] x2 right co-ordinate - * @param[in] y2 bottom co-ordinate - */ - QuadCoordinates(float x1, float y1, float x2, float y2) - : min(x1, y1), - max(x2, y2) - { - } - - Vector2 min; ///< top-left (minimum) position of quad - Vector2 max; ///< bottom-right (maximum) position of quad - }; - - typedef std::vector QuadContainer; - - /** - * structure for information required to build the highlight mesh - */ - struct HighlightInfo - { - /** - * Adds a Quad (2D rectangular sub-selection) - * @param[in] x1 left co-ordinate - * @param[in] y1 top co-ordinate - * @param[in] x2 right co-ordinate - * @param[in] y2 bottom co-ordinate - */ - void AddQuad( float x1, float y1, float x2, float y2 ); - - /** - * Clamps all quads to fit within a min -> max 2D boundary. - */ - void Clamp2D(const Vector2& min, const Vector2& max); - - QuadContainer mQuadList; ///< List of quads (sub-selections that form to create complete selection) - }; - - /** - * Holds requested selection start and end points for highlighted text. - */ - struct SelectionParameters - { - SelectionParameters( size_t start, size_t end ) - : mStartOfSelection( start ), mEndOfSelection( end ) - { - - } - - size_t mStartOfSelection; - size_t mEndOfSelection; - }; - - enum State - { - StateEdit, - StateDraggingHandle - }; - - enum SelectionHandleId - { - HandleOne, ///< Selection handle one which is on the left - HandleTwo ///< Selection handle two which is on the right - }; - - /** - * Two different behaviours are needed to convert a touch point into a character index. - * When a tap is received and the touch point doesn't hit any character, the final character selected might - * be different than the one selected if the event is a pan. - * i.e. If a tap is received and the touch point doesn't hit any character the expected position of the cursor - * would be the end or the beginning of a line. However, this behaviour would be weird while panning. - */ - enum TouchToIndex - { - TapMode, ///< Touch point to character index conversion mode used for Tap events. - DragMode ///< Touch point to character index conversion mode used for Pan events. - }; - - /** - * Used to set the direction when find the next visible character. - */ - enum FindVisibleCharacterDirection - { - Left, ///< Find visible characters on the left. - Right, ///< Find visible characters on the right. - ByEnd ///< Start finding visible characters by the end. - }; - - /** - * - */ - virtual bool OnTouchEvent(const TouchEvent& event); - - /** - * From CustomActorImpl; called after the Text Input actor is touched - * @param[in] event The KeyEvent event. - * @return True if the event should be consumed. - */ - virtual bool OnKeyEvent(const KeyEvent& event); - - /** - * From CustomActorImpl; called when this actor gains keyboard focus. - */ - virtual void OnKeyInputFocusGained(); - - /** - * From CustomActorImpl; called when this actor loses keyboard focus. - */ - virtual void OnKeyInputFocusLost(); - - /** - * From Control; called whenever the control is added to the stage. - */ - virtual void OnControlStageConnection(); - -private: // From Control - - /** - * Creation of the layer that is used by top level active parts of the TextInput like handles - */ - void CreateActiveLayer(); - - /** - * @copydoc Control::OnInitialize() - */ - virtual void OnInitialize(); - - /** - * @copydoc Control::OnControlSizeSet() - */ - virtual void OnControlSizeSet(const Vector3& targetSize); - - /** - * @copydoc Control::OnRelayout() - */ - virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); - - /** - * Retrieves the text-input's natural size by calling TextView::GetNaturalSize(). - * - * @return The natural size. - */ - virtual Vector3 GetNaturalSize(); - - /** - * Retrieves the text-input's \e height for a given \e width by calling TextView::GetHeightForWidth(). - * - * @param[in] width The given \e width. - * - * @return The \e height for the given \e width. - */ - virtual float GetHeightForWidth( float width ); - -protected: - - /** - * Construct a new TextInput. - */ - TextInput(); - - /** - * A reference counted object may only be deleted by calling Unreference() - */ - virtual ~TextInput(); - -private: - - // Undefined - TextInput(const TextInput&); - - // Undefined - TextInput& operator=(const TextInput& rhs); - - /** - * Callback when a handle is panned/moved, either selection handles or grab handle - * @param actor Handle of the selection or grab handle. - * @param gesture Data structure with the parameters of the gesture. - */ - void OnHandlePan(Actor actor, const PanGesture& gesture); - - /** - * Callback for touch down on Grab handle - * @param[in] actor touched - * @param[in] touch touch event - */ - bool OnPressDown(Dali::Actor actor, const TouchEvent& touch); - - /** - * Callback for touch down on Selection handle one - * @param[in] actor touched - * @param[in] touch touch event, used to determine if down or up event - */ - bool OnHandleOneTouched(Dali::Actor actor, const TouchEvent& touch); - - /** - * Callback for touch down on Selection handle two - * @param[in] actor touched - * @param[in] touch touch event, used to determine if down or up event - */ - bool OnHandleTwoTouched(Dali::Actor actor, const TouchEvent& touch); - - /** - * Callback for tap on TextInput - * @param[in] actor - * @param[in] tap touch event - */ - void OnTextTap(Dali::Actor actor, const Dali::TapGesture& tap); - - /** - * Callback for double tap on TextInput - * @param[in] actor - * @param[in] tap touch event - */ - void OnDoubleTap(Dali::Actor actor, const Dali::TapGesture& tap); - - /** - * Callback for long press on TextInput - * @param[in] actor - * @param[in] longPress long press event - */ - void OnLongPress(Dali::Actor actor, const Dali::LongPressGesture& longPress); - - /** - * Callback for the ClipboardEventNotifier when text is selected in the clipboard window. - * @param[in] notifier The Clipboard Event Notifier. - */ - void OnClipboardTextSelected( ClipboardEventNotifier& notifier ); - - /** - * Callback for when a button is pressed in popup panel - * @param[in] button handle to the button pressed. - */ - bool OnPopupButtonPressed( Toolkit::Button button ); - - /** - * Callback when handle timer ticks. - * - * Cursor should become visible/invisible to simulate blinking. - * - * @return True if the timer should be keep running. - */ - bool OnCursorBlinkTimerTick(); - - /** - * Invoked upon popup Hide animation completing. - * @note Only called for animating hide, not called for instantaneous (animate = false) - * @param[in] popup The popup which was hidden. - */ - void OnPopupHideFinished(TextInputPopup& popup); - - /** - * Called in OnKeyEvent to handle key down events. - * @param[in] event The KeyEvent event. - * @return True if the event should be consumed. - */ - bool OnKeyDownEvent(const KeyEvent& event); - - /** - * Called in OnKeyEvent to handle key up events. - * @param[in] event The KeyEvent event. - * @return True if the event should be consumed. - */ - bool OnKeyUpEvent(const KeyEvent& event); - - /** - * Chooses from all handle position and alternative handle positions where to set the position of the two selection handles. - * - * @param[in] cursorPositionOne The initial position of the first selection handle. - * @param[in] cursorPositionTwo The initial position of the second selection handle. - * @param[in] altPositionValidOne Whether there is an alternative position for the first selection handle. - * @param[in] altPositionValidTwo Whether there is an alternative position for the second selection handle. - * @param[in] altPositionOne The alternative position of the first selection handle. - * @param[in] altPositionTwo The alternative position of the second selection handle. - */ - void ChooseRtlSelectionHandlePosition( const Vector3& cursorPositionOne, - const Vector3& cursorPositionTwo, - bool altPositionValidOne, - bool altPositionValidTwo, - const Vector3& altPositionOne, - const Vector3& altPositionTwo ); - /** - * Callback called when the text-view is scrolled. - * - * Updates the selection and grab handles, and the highlighted text. - * - * @param[in] textView Handle of the text-view. - * @param[in] scrollPosition The difference with the previous scroll position. - */ - void OnTextViewScrolled( Toolkit::TextView textView, Vector2 scrollPosition ); - - /** - * Scrolls the text-view to make the cursor visible. - * - * @param[in] cursorPosition The actual cursor position in actor coordinates. - */ - void ScrollTextViewToMakeCursorVisible( const Vector3& cursorPosition ); - - /** - * Creates and starts a timer to scroll the text when handles are close to the edges of the text-input. - * - * It only starts the timer if it's already created. - */ - void StartScrollTimer(); - - /** - * Stops the timer used to scroll the text. - */ - void StopScrollTimer(); - - /** - * Callback called by the timer used to scroll the text. - * - * It calculates and sets a new scroll position. - */ - bool OnScrollTimerTick(); - -public: // Public to allow internal testing. - - /** - * Register for touch events - */ - void SetUpTouchEvents(); - - /** - * Sets up TextView Actor - */ - void CreateTextViewActor(); - - /** - * Set Styled Text for text input. - * @param[in] styleText The new styled text for the text input. - */ - void SetText( const MarkupProcessor::StyledTextArray& styleText ); - - /** - * Start a timer to signal cursor to blink. - */ - void StartCursorBlinkTimer(); - - /** - * Stop the timer signalling the cursor to blink. - */ - void StopCursorBlinkTimer(); - - /** - * Starts input, setting focus and showing keyboard.. - */ - void StartEditMode(); - - /** - * Called when End of input and focus no longer required, keyboard is hidden. - */ - void EndEditMode(); - - /** - * Applies a style to the current pre-edit / predicted word to show it is being edited. - * @param[in] preEditStartPosition position in text array that the predicted word starts at - * @param[in] preEditStringLength used to calculate how many characters need their style changed. - */ - void ApplyPreEditStyle( std::size_t preEditStartPosition, std::size_t preEditStringLength ); - - /** - * Restores style to value before applying Pre-Edit style. - */ - void RemovePreEditStyle(); - - /** - * Event received from IMF manager - * @return ImfCallbackData data struture undicating if update is needed, cursor position and current text - */ - ImfManager::ImfCallbackData ImfEventReceived( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& test ); - - /** - * Called when the OnKey event is a Pre-edit string - * @param[in] keyString String received in Pre-edit - * @param[in] cursorOffset the cursor offset from where the pre-edit word starts - * @return bool true if preedit reset is required. - */ - bool PreEditReceived( const std::string& keyString, std::size_t cursorOffset ); - - /** - * Called when the OnKey event is a Commit string - * @param[in] keyString String received in Comment - * @return update flag to trigger cursor update of TextInput only when needed. - */ - bool CommitReceived( const std::string& keyString ); - - /** - * Deletes Pre-edit string - * By default it doesn't update the character's size and position table, which is a costly - * operation. As in many cases deletion and insertion (InsertAt) of text - * occurs in the same action i.e. preedit/commit. It makes sense to - * delete without updating, and then insert with updating. - * - * @return The number of characters to be deleted. - */ - std::size_t DeletePreEdit(); - - /** - * Reset all pre-edit flag and signal IMF keyboard that the current pre-edit word has been comitted. - * This may be due to the cursor being moved by user or reached the max character limit. - * @param[in] preserveCursorPosition Set true to keep cursor in current position, eg. touch event caused cursor to move. - */ - void PreEditReset( bool preserveCursorPosition ); - - /** - * Called after cursor position needs updating. - * Redraws cursor and notifies VirtualKeyboard - */ - void CursorUpdate(); - - /** - * Delete highlighted characters - * @param[in] inheritStyle Whether style from previous character in the string should be inherited. - */ - void DeleteHighlightedText( bool inheritStyle ); - - /* - * Delete range of characters - * @param[in] start position of characters to delete - * @param[in] ncharacters number of characters to delete - */ - void DeleteRange(std::size_t start, std::size_t ncharacters); - - /** - * Delete character at current cursor position and redisplay - * @param[in] positionToDelete position of character to delete - */ - void DeleteCharacter( std::size_t positionToDelete ); - - /** - * Add or replaces characters to currently displayed string at cursor position - * By default it doesn't update the character's size and position table, which is a costly - * operation. As in many cases deletion and insertion (InsertAt) of text - * occurs in the same action i.e. preedit/commit. It makes sense to - * delete without updating, and then insert with updating. - * @param[in] newText string to add to TextInput display string. - * @param[in] insertionPosition position to insert at. - * @param[in] numberOfCharactersToReplace The number of characters to replace. - * @return number of characters to offset the cursor by. - */ - std::size_t InsertAt( const Text& newText, const std::size_t insertionPosition, const std::size_t numberOfCharactersToReplace ); - - /** - * Creates a cursor. - * @param[in] color the cursor color. - * @return the image actor to be used as the cursor. - */ - ImageActor CreateCursor( const Vector4 &color ); - - /** - * Moves cursor to the right - * param[in] reverse if true then cursor moves in the reverse direction (to the left) - * param[in] places number of character cursor should move. - */ - void AdvanceCursor(bool reverse = false, std::size_t places = 1); - - /** - * Draw a cursor / caret at position where new text should appear - */ - void DrawCursor(); - - /** - * Sets cursor visibility - * This sets visibility of the cursor. Which is comprised of 2 - * cursors. The conventional cursor, and the alternate (RTL) cursor, - * which only appears when the cursor is at a character that can have - * a character appended to different visual positions depending on whether that - * character to be appended is RTL or LTR. - * @param[in] visible true - enable visibility for cursor, false - disable visiblity for cursor - */ - void SetCursorVisibility( bool visible ); - - /** - * Sets alternate cursor enable state - * @see SetCursorVisibility - * alternate cursor will only be visible if both SetCursorVisiblity - * and cursor enabled have been set to true. - */ - void SetAltCursorEnabled( bool enabled ); - - /** - * Create the grab handle that positions the cursor - * @param[in] image to be used for grab handle - * - */ - void CreateGrabHandle(Image image=Image()); - - /** - * Create Grab area to be used by Grab Handle - */ - void CreateGrabArea( Actor& parent); - - /** - * Move grab handle to the required character position - * - * @param[in] displacement Displacement of the grab handle in actor coordinates. - * - * @return The new actual position the handle has been set to. - */ - Vector3 MoveGrabHandle( const Vector2& displacement ); - - /** - * Show or hide the grab handle without baking the visibility flag. - * Used when the Grab handle needs to be invisible due to text-view scrolling making it out of view - * - * @param[in] visible bool flag to set as true is grab handle should be shown, else false to hide. - */ - void ShowGrabHandle( bool visible ); - - /** - * Show or hide the grab handle and bake the visibility flag. - * Used when the state of text-input changes to a state which the grabhandle is not required. E.g. Selection mode starts or edit mode ends. - * Calls ShowGrabHandle. - * - * @param[in] visible bool flag to set as true is grab handle should be shown, else false to hide. - */ - void ShowGrabHandleAndSetVisibility( bool visible ); - - /* Boundary Property Notifications when handle exceed bounding box*/ - - /** - * PropertyNotification Callback when left boundary exceeded so handle can be flipped. - * @param[in] source PropertyNotification - */ - void OnLeftBoundaryExceeded( PropertyNotification& source ); - /** - * PropertyNotification Callback when within left boundary so handle can be flipped back. - * @param[in] source PropertyNotification - */ - void OnReturnToLeftBoundary( PropertyNotification& source ); - /** - * PropertyNotification Callback when right boundary exceeded so handle can be flipped. - * @param[in] source PropertyNotification - */ - void OnRightBoundaryExceeded( PropertyNotification& source ); - /** - * * PropertyNotification Callback when within right boundary so handle can be flipped back. - * @param[in] source PropertyNotification - */ - void OnReturnToRightBoundary( PropertyNotification& source ); - - /** - * PropertyNotification Callbacks for hiding handle one when it exceeds boundary. - * @param[in] source PropertyNotification - */ - void OnHandleOneLeavesBoundary( PropertyNotification& source ); - /** - * PropertyNotification Callbacks for showing hidden handle one when returns within boundary - * @param[in] source PropertyNotification - */ - void OnHandleOneWithinBoundary( PropertyNotification& source ); - /** - * PropertyNotification Callbacks for hiding handle two it when exceeds boundary. - * @param[in] source PropertyNotification - */ - void OnHandleTwoLeavesBoundary( PropertyNotification& source ); - /** - * PropertyNotification Callbacks for showing hidden handle two when returns within boundary - * * @param[in] source PropertyNotification - */ - void OnHandleTwoWithinBoundary( PropertyNotification& source ); - - /** - * Set up property notifications on the position of the handles to facilitate flipping and hiding when at screen boundary. - */ - void SetUpHandlePropertyNotifications(); - - /** - * Create the selection handles that bound text to be selected for copy/cut. - * @param[in] start initial position of start selection handle. - * @param[in] end initial position of end selection handle. - * @param[in] handleOneImage (optional) to be used for selection handle - * @param[in] handleTwoImage (optional) to be used for selection handle - */ - void CreateSelectionHandles( std::size_t start = 0, std::size_t end = std::numeric_limits::max(), Dali::Image handleOneImage = Dali::Image(), Dali::Image handleTwoImage = Dali::Image() ); - - /** - * Move the selection handles to required positions in text. - * - * @param[in] handleId the handle to position - * @param[in] displacement Displacement of the selection handle in actor coordinates. - * - * @return The new actual position the handle has been set to. - */ - Vector3 MoveSelectionHandle(SelectionHandleId handleId, const Vector2& displacement); - - /** - * Calculate and position the specified selection handle the given index position - * - * @param[in] handleId the handle to position - */ - void SetSelectionHandlePosition(SelectionHandleId handleId); - - /** - * Gets a table of the visual text positions which has a flag - * for each Character. The flag is either true (character selected) - * or false (character deselected) - * @note startSelection can be greater or less than endSelection - * - * @param[in,out] selectedVisualText The vector to be resized and populated with the selected flags - * @param[in] startSelection The start selection point for the text - * @param[in] endSelection The end selection point for the text - */ - void GetVisualTextSelection(std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection); - - /** - * Iterates between selection handles and computes the info required to build the highlight mesh - */ - HighlightInfo CalculateHighlightInfo(); - - /** - * This method was added to fix a PLM. it creates one quad per character so the mesh can show different selection boxes when a mix of right to left and left to right text is selected. - */ - HighlightInfo CalculateHighlightInfoRtl(); - - /** - * Calculates new Mesh data so highlight moves with selection handles. - */ - void UpdateHighlight(); - - /** - * Removes popup, and its options. - */ - void ClearPopup(); - - /** - * Adds Popup options which have been enabled. - */ - void AddPopupOptions(); - - /** - * Sets popup position - * @param[in] position The actual position for this popup. - * @param[in] alternativePosition Alternative popup position if no space in upper area. - */ - void SetPopupPosition(const Vector3& position, const Vector2& alternativePosition ); - - /** - * Hides the popup - * @param[in] animate (optional) whether to animate popup to hide state over time (i.e. tween). - * @param[in] signalFinished (optional) whether to perform an animation finish operation after the hide animation completes. Requires animate to be true. - */ - void HidePopup( bool animate = true, bool signalFinished = true ); - - /** - * Shows the popup - * @param[in] animate (optional) whether to animate popup to show state over time (i.e. tween). - */ - void ShowPopup(bool animate = true); - - /** - * Shows the cut-copy-paste popup - */ - void ShowPopupCutCopyPaste(); - - /** - * Setup the selection popup and clipboard if relevant so the correct options are shown when ShowPopup is called. - * @param[in] showCutButton Flag to show or hide cut button, in some cases like whitespace we do not want to cut just select. - * default is true. - */ - void SetUpPopupSelection( bool showCutButton = true ); - - /** - * Return the logical index containing the character position closest to the source. - * Used for positioning the grab handle at characters when dragged along. - * Two different behaviours are needed in case the source point doesn't actually touch a - * character. @see TouchToIndex. - * @param[in] source float to match against - * @param[out] closestIndex index to the vector of character's size and position. - * @return \e true if the source point is actually inside the geometry provided by TextView. - */ - bool ReturnClosestIndex(const Vector2& source, std::size_t& closestIndex ); - - /** - * Returns the X-position of the current line justification - * (relative to left of text-view container) - * @return X position for line justification - */ - float GetLineJustificationPosition() const; - - /** - * Currently the cursor is positioned at the previous characters position plus it's width. - * If the previous character is on a different line then this function returns the correct position. - * @param[in] characterPosition the character position index that the cursor should be at - * @return position of cursor/handle - */ - Vector3 PositionCursorAfterWordWrap( std::size_t characterPosition ) const; - - - /** - * Return a vector which is the actual position for the given character position - * The character position is where a cursor would be position for that character. - * @param[in] characterPosition the logical (input) position in the 'string' of characters. - * - * @return Vector3 the actual x,y,z position - */ - Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition ) const; - - /** - * Return a vector which is the actual position for the given character position - * The character position is where a cursor would be positioned for that character to be inserted. - * An additional alternatePosition is also set in circumstances where the possible writing - * of characters would be in the opposite direction. - * e.g. "HelloشقشلاهؤEnglish" - * | | - * * + - * [*] - Primary actual position for cursor i.e. continuing writing LTR (English) - * [+] - Alternate actual position for cursor i.e. writing RTL (Arabic) - * - * @param[in] characterPosition the logical (input) position in the 'string' of characters. - * @param[out] directionRTL Whether the actual x,y,z position is after LTR (false) or RTL (true) text. - * @param[out] alternatePosition the actual x,y,z position of the cursor if user types - * in alternate direction to current flow of text. - * @param[out] alternatePositionValid whether this alternate position is valid. - * @return Vector3 the actual x,y,z position - */ - Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const; - - /** - * Retrieve the character position of the first character on the row of text - * that this character resides on. - * @param[in] logicalPosition the position in the 'string' of characters. - * @return logical character position of start of row. - */ - std::size_t GetRowStartFromCharacterPosition(std::size_t logicalPosition) const; - - /** - * Retrieves the first character of a group of characters with the same direction. - * - * @param[in] logicalPosition Index to a character. - * - * @return Index to the character. - */ - std::size_t GetFirstCharacterWithSameDirection( std::size_t logicalPosition ) const; - - /** - * Retrieve the dimensions of this row of text that the character resides on. - * @param[in] characterPosition the position in the 'string' of characters. - * @return The size of the rectangle representing this row - */ - Size GetRowRectFromCharacterPosition(std::size_t characterPosition) const; - - /** - * Retrieve the dimensions (and min-max) of this row of text that the character resides on. - * @param[in] characterPosition the position in the 'string' of characters. - * @param[out] min the top-left position of the rectangle representing this row - * @param[out] max the bottom-right position of the rectangle representing this row - * @return The size of the rectangle representing this row (max - min) - */ - Size GetRowRectFromCharacterPosition(std::size_t characterPosition, Vector2& min, Vector2& max) const; - - /** - * Checks if the provided touchedActor was this text-input - * @param[in] touchedActor the touched actor that will be checked against this text-input - * @return true if the touchActor was the text-input or one of its children - */ - bool WasTouchedCheck( const Actor& touchedActor ) const; - - /** - * Connect to the stage touch event - */ - void StartMonitoringStageForTouch(); - - /** - * Disconnect from the stage touch event - */ - void EndMonitoringStageForTouch(); - - /** - * Callback for when the screen is touched, this will be connected when selection starts and disconnected when it ends. - * @param[in] event The touch event - */ - void OnStageTouched(const TouchEvent& event); - - - /** - * Select the text between the given values - * @param[in] start position within array to start selection - * @param[in] end position within array to end selection - */ - void SelectText(std::size_t start, std::size_t end); - - /** - * Gets selected text and returns it as a StyleText vector - * @return StyledText vector that is selected. - */ - MarkupProcessor::StyledTextArray GetSelectedText(); - - /** - * Applies the given style to all text, selected or not selected. - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - */ - void ApplyStyleToRange(const TextStyle& style, const TextStyle::Mask mask, const std::size_t begin, const std::size_t end); - - /** - * Callback for when the keyboard status changes - * @param[in] keyboardShown Whether the keyboard has just been shown or not. - */ - void KeyboardStatusChanged(bool keyboardShown); - - /** - * Hide highlight shown between selection handles. - * @param[in] hidePopup flag to hide the popup too, default is to hide popup. - */ - void RemoveHighlight( bool hidePopup = true ); - - /** - * Highlights text that has been selected - */ - void CreateHighlight(); - - /** - * Copies selected text to clipboard - * @return bool true if copy was successful. - */ - bool CopySelectedTextToClipboard(); - - /** - * Pastes the given text to currently displayed string at the current cursor position - * @param[in] text Text to be pasted - */ - void PasteText( const Text& text ); - - /** - * Sets the direction of the text if it is empty. - */ - void SetTextDirection(); - - /** - * Updates the line height accordingly with the current text input style. - */ - void UpdateLineHeight(); - - /** - * Finds a visible character. - * - * The \e direction parameters specifies from where to start to look for a visible character. \e Left means start by characters in lower - * positions than \e cursorPosition, \e Right means start by characters in greater positions than \e cursorPosition and \e ByEnd starts - * by the last characters. - * - * If \e Left or \e Right is provided and any character is found, then looks in the other direction. - * - * @param[in] direction Direction used to find a visible character. - * @param[in] cursorPosition Starting position. - * - * @return The found visible character. - */ - std::size_t FindVisibleCharacter( const FindVisibleCharacterDirection direction , const std::size_t cursorPosition ) const; - - /** - * @copydoc SetSortModifier() - */ - void SetSortModifier( float depthOffset ); - - /** - * @copydoc SetSnapshotModeEnabled() - */ - void SetSnapshotModeEnabled( bool enable ); - - /** - * @copydoc IsSnapshotModeEnabled() - */ - bool IsSnapshotModeEnabled() const; - - /** - * @copydoc SetScrollEnabled() - */ - void SetScrollEnabled( bool enable ); - - /** - * @copydoc IsScrollEnabled() - */ - bool IsScrollEnabled() const; - - /** - * @copydoc SetScrollPosition() - */ - void SetScrollPosition( const Vector2& position ); - - /** - * @copydoc GetScrollPosition() - */ - Vector2 GetScrollPosition() const; - - /** - * @brief Sets whether markup processing should be carried out. - * - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ); - - /** - * @brief Returns whether markup processing is enabled or not - * - * @return true is markup processing is enabled - */ - bool IsMarkupProcessingEnabled() const; - - /** - * Insert or replaces the given text in the given position. It checks if the text exceeds the maximum allowed number of characters - * and if it fits in the text-input's boundaries. - * - * @param[in] text Text to be inserted. - * @param[in] position Position where the text is inserted. - * @param[in] numberOfCharactersToReplace The number of characters to replace. - * @param[out] textExceedsMaximunNumberOfCharacters The number of characters that have been inserted. - * @param[out] textExceedsBoundary Whether the inserted text has exceeded the boundaries of the text-input. - * - * @return The number of characters that have been inserted. - */ - std::size_t DoInsertAt( const Text& text, std::size_t position, std::size_t numberOfCharactersToReplace, bool& textExceedsMaximunNumberOfCharacters, bool& textExceedsBoundary ); - - /** - * Retrieve Text-view's layout info. - */ - void GetTextLayoutInfo(); - - /** - * Set the offset for positioning Popup from the TextInput - * @param[in] offset in the order, left, top, right, bottom - */ - void SetOffsetFromText( const Vector4& offset ); - - /** - * Get the offset of the Popup from the TextInput - * @return Vector4 with the offset in the order, left, top, right, bottom - */ - const Vector4& GetOffsetFromText() const; - - /** - * Show the Placeholder text with an already created StyleTextArray - * @param[in] stylePlaceHolderText Required placeholder text to be used - */ - void ShowPlaceholderText( const MarkupProcessor::StyledTextArray& stylePlaceHolderText ); - - // Properties - - /** - * Called when a property of an object of this type is set. - * @param[in] object The object whose property is set. - * @param[in] index The property index. - * @param[in] value The new property value. - */ - static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); - - /** - * Called to retrieve a property of an object of this type. - * @param[in] object The object whose property is to be retrieved. - * @param[in] index The property index. - * @return The current value of the property. - */ - static Property::Value GetProperty( BaseObject* object, Property::Index propertyIndex ); - - /** - * Emits the style changed signal. - */ - void EmitStyleChangedSignal(); - - /** - * Emit signal when text is modified. - */ - void EmitTextModified(); - - /** - * Emits max input characters reached signal. - */ - void EmitMaxInputCharactersReachedSignal(); - - /** - * Emits a signal when the input text exceeds the boundaries of the text-input. - */ - void EmitInputTextExceedsBoundariesSignal(); - -private: - - State mState; ///< Current State of Text input. - MarkupProcessor::StyledTextArray mStyledText; ///< String currently displayed by TextView with style info. - TextStyle mInputStyle; ///< Stores the current input style. - float mLineHeight; ///< Stores the current line height accordingly with the input style. - Toolkit::TextView mDisplayedTextView; ///< Actor which actually display text - - MarkupProcessor::StyledTextArray mStyledPlaceHolderText; ///< Text used as place holder with style info. - - std::size_t mMaxStringLength; ///< Max number of characters for string - std::size_t mNumberOflinesLimit; ///< Limit on the number of lines this TextInput will display. - - ImageActor mCursor; ///< Cursor overlayed on Text to show where new text will be inserted - ImageActor mCursorRTL; ///< Right To Left Cursor overlayed on Text (where new RTL text would be inserted) - Animation mCursorAnimation; ///< animator for cursor blinking. - std::size_t mCursorPosition; ///< position along string cursor is at. - Timer mCursorBlinkTimer; ///< Timer to signal cursor to blink - - Layer mActiveLayer; ///< Layer for active handles and alike that ensures they are above all else. - - Image mGrabHandleImage; ///< image to be used for grab handle - ImageActor mGrabHandle; ///< Handle used to move cursor for editing - - Actor mGrabArea; ///< invisible actor that receives pans events for the grab handle. - PanGestureDetector mPanGestureDetector; ///< Pan gesture for handles - TapGestureDetector mTapDetector; ///< used to start editing - TapGestureDetector mDoubleTapDetector; ///< double tap detector - - Vector3 mActualGrabHandlePosition; ///< actual position of grab handle, this might not be snapped to a character - - LongPressGestureDetector mLongPressDetector; ///< Gesture to start selection - - /*Selection handles*/ - Image mSelectionHandleOneImage; ///< image used for selection handle one - Image mSelectionHandleOneImagePressed; ///< image used for selection handle one pressed state - Image mSelectionHandleTwoImage; ///< image used for selection handle two - Image mSelectionHandleTwoImagePressed; ///< image used for selection handle two pressed state - - bool mIsSelectionHandleOneFlipped:1; ///< Flag to know whether the handle one is flipped or not. - bool mIsSelectionHandleTwoFlipped:1; ///< Flag to know whether the handle two is flipped or not. - Vector3 mSelectionHandleOneOffset; ///< Handle One's Offset - Vector3 mSelectionHandleTwoOffset; ///< Handle Two's Offset - Vector3 mSelectionHandleOneActualPosition; ///< Actual x y position of handle - Vector3 mSelectionHandleTwoActualPosition; ///< Actual x y position of handle - std::size_t mSelectionHandleOnePosition; ///< Position of handle along the string of text - std::size_t mSelectionHandleTwoPosition; ///< Position of handle along the string of text - ImageActor mSelectionHandleOne; ///< First selection handle used for selecting text to cut&paste - ImageActor mSelectionHandleTwo; ///< Second selection handle used for selecting text to cut&paste - Actor mHandleOneGrabArea; ///< invisible actor that receives pans events for the selection handle. - Actor mHandleTwoGrabArea; ///< invisible actor that receives pans events for the selection handle. - - HighlightInfo mNewHighlightInfo; ///< Geometry info to create highlight. - - Text mPreEditString; ///< Holds current input string prior to it being committed. - std::size_t mPreEditStartPosition; ///< Cursor position for start of pre-edit string - std::size_t mPreEditLength; ///< Cursor position for length of current pre-edit string after purging characters that do not fit. - std::size_t mNumberOfSurroundingCharactersDeleted; ///< Stores the number of surrounding characters deleted. - unsigned long mTouchStartTime; ///< Touch Start time (time in ms when down press began) - - Toolkit::TextView::TextLayoutInfo mTextLayoutInfo; ///< It contains a table layout info per character sorted by the character's visual index (retrieved from TextView), - ///< a reorder map that stores each character's visual (output) index according to its logical (input) index, - ///< a reorder map that stores each character's logical (input) index according to its visual (output) index, - ///< the text size after layout and the scroll offset. - - MarkupProcessor::StyledTextArray mCurrentCopySelecton; ///< Array to store copied text. - TextInputPopup mPopupPanel; ///< Panel to house cut and paste, select all buttons. - - Timer mScrollTimer; - Vector2 mScrollDisplacement; - Vector3 mCurrentHandlePosition; - SelectionHandleId mCurrentSelectionId; - Vector3 mCurrentSelectionHandlePosition; - SelectionParameters mRequestedSelection; - Vector4 mSelectionHandleFlipMargin; - Vector4 mBoundingRectangleWorldCoordinates; - - Clipboard mClipboard; ///< Handle to clipboard - - // Styling - Vector4 mMaterialColor; // Color of the highlight - Vector4 mPopupOffsetFromText; // Offset of Popup from the TextInput. - - bool mOverrideAutomaticAlignment:1; ///< Whether to override the alignment automatically set by the text content (e.g. european LTR or arabic RTL) - bool mCursorRTLEnabled:1; ///< Enable state of Alternate RTL Cursor (need to keep track of this as it's not always enabled) - bool mClosestCursorPositionEOL:1; ///< closest cursor position is end of line. - bool mCursorBlinkStatus:1; ///< \e true shows the cursor, \e false hiddes it. - - bool mCursorVisibility:1; ///< Visibility status of Cursor - bool mGrabHandleVisibility:1; ///< Visibility status of the grab handle. - - bool mIsCursorInScrollArea:1; ///< Whether the cursor is inside the boundaries of the text-input. - bool mIsGrabHandleInScrollArea:1; ///< Whether the grab handle is inside the boundaries of the text-input. - - bool mEditModeActive:1; ///< true to indicate TextInput is in edit mode. - bool mEditOnTouch:1; ///< true indicates edit mode starts by touching/tapping the TextInput - bool mTextSelection:1; ///< true indicates text selection is enabled. - bool mExceedEnabled:1; ///< Whether text-input editing text beyond its boundary is enabled or not. By default is enabled. - bool mGrabHandleEnabled:1; ///< Flag to enable the grab handle instead of the default magnifier. - bool mIsSelectionHandleFlipEnabled:1; ///< Flag to enable the selection handle flip - - bool mPreEditFlag:1; ///< Flag to indicate if key string received is still in pre-edit mode (Ecore IMF keyboard) - bool mIgnoreCommitFlag:1; ///< Flag to indicate if the commit string should be ignored, maybe due to a keyboard reset. - bool mIgnoreFirstCommitFlag:1; ///< Whether to ignore the first commit. - bool mSelectingText:1; ///< Ignore surrounding text as selecting text - - bool mPreserveCursorPosition:1; ///< Indicates that the commit message is from a reset and does not require the cursor to be moved - - bool mSelectTextOnCommit:1; - - bool mUnderlinedPriorToPreEdit:1; ///< As predictive text adds underline style this flag enables us to revert back or keep underline. - - bool mCommitByKeyInput:1; ///< Set if a commit is done by key input rather than automatically (usually when a space bar or enter is pressed). - - bool mPlaceHolderSet:1; ///< Whether the place holder text is set. - bool mMarkUpEnabled:1; ///< enable to scan for mark-up - - Toolkit::TextInput::InputSignalType mInputStartedSignal; ///< Signal emitted when input starts - Toolkit::TextInput::InputSignalType mInputFinishedSignal; ///< Signal emitted when input ends - Toolkit::TextInput::StyleChangedSignalType mStyleChangedSignal; ///< Signal emitted when style changes. - Toolkit::TextInput::TextModifiedSignalType mTextModifiedSignal; ///< Signal emitted when text modified. - Toolkit::TextInput::MaxInputCharactersReachedSignalType mMaxInputCharactersReachedSignal; ///< Signal emitted when max input characters is reached. - Toolkit::TextInput::InputSignalType mCutAndPasteToolBarDisplayed; ///< Signal emitted when toolbar displayed - Toolkit::TextInput::InputTextExceedBoundariesSignalType mInputTextExceedBoundariesSignal; ///< Signal emitted when input text exceeds the boundaries of the text-input. -}; - -} // namespace Internal - -// Helpers for public-api forwarding methods - -inline Toolkit::Internal::TextInput& GetImpl(Toolkit::TextInput& textInput) -{ - DALI_ASSERT_ALWAYS(textInput); - - Dali::RefObject& handle = textInput.GetImplementation(); - - return static_cast(handle); -} - -inline const Toolkit::Internal::TextInput& GetImpl(const Toolkit::TextInput& textInput) -{ - DALI_ASSERT_ALWAYS(textInput); - - const Dali::RefObject& handle = textInput.GetImplementation(); - - return static_cast(handle); -} - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp deleted file mode 100644 index e92e4d0..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-popup-impl.cpp +++ /dev/null @@ -1,917 +0,0 @@ -/* - * Copyright (c) 2014 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 -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include - -using namespace Dali; - -#define GET_LOCALE_TEXT(string) dgettext("sys_string", string) - -namespace -{ -const Vector2 DEFAULT_POPUP_INDICATOR_OFFSET(0.0f, 60.0f); - -// 1. For selection: should be above top of highlighted selection, or below bottom of highlighted selection + end handle. -// 2. For cursor: should be above top of cursor, or below bottom of cursor + grab handle. - -/** - * Image resource paths - */ -const char* const POPUP_BACKGROUND = DALI_IMAGE_DIR "popup_bubble_bg.#.png"; -const char* const POPUP_BACKGROUND_EFFECT = DALI_IMAGE_DIR "popup_bubble_bg_ef.#.png"; -const char* const POPUP_BACKGROUND_LINE = DALI_IMAGE_DIR "popup_bubble_bg_line.#.png"; - -const char* const POPUP_TAIL_BOTTOM = DALI_IMAGE_DIR "popup_bubble_tail_bottom.png"; -const char* const POPUP_TAIL_BOTTOM_EFFECT = DALI_IMAGE_DIR "popup_bubble_tail_bottom_ef.png"; -const char* const POPUP_TAIL_BOTTOM_LINE = DALI_IMAGE_DIR "popup_bubble_tail_bottom_line.png"; -const char* const POPUP_TAIL_TOP = DALI_IMAGE_DIR "popup_bubble_tail_top.png"; -const char* const POPUP_TAIL_TOP_EFFECT = DALI_IMAGE_DIR "popup_bubble_tail_top_ef.png"; -const char* const POPUP_TAIL_TOP_LINE = DALI_IMAGE_DIR "popup_bubble_tail_top_line.png"; - -const char* const OPTION_ICON_CLIPBOARD = DALI_IMAGE_DIR "copy_paste_icon_clipboard.png"; -const char* const OPTION_ICON_COPY = DALI_IMAGE_DIR "copy_paste_icon_copy.png"; -const char* const OPTION_ICON_CUT = DALI_IMAGE_DIR "copy_paste_icon_cut.png"; -const char* const OPTION_ICON_PASTE = DALI_IMAGE_DIR "copy_paste_icon_paste.png"; -const char* const OPTION_ICON_SELECT = DALI_IMAGE_DIR "copy_paste_icon_select.png"; -const char* const OPTION_ICON_SELECT_ALL = DALI_IMAGE_DIR "copy_paste_icon_select_all.png"; - -/** - * Constant values for building the GUI - */ -const Vector4 POPUP_MARGIN( 14.0f, 14.0f, 14.0f, 14.0f ); ///< Margin around the popup visible background Image. -const Vector4 POPUP_BORDER( 2.0f, 2.0f, 2.0f, 2.0f ); ///< The Border of the popup. -const Vector2 POPUP_MIN_SIZE( 0.0f, 126.0f ); ///< The minimum size of the popup. -const Vector2 POPUP_MAX_SIZE( 720.0f, 126.0f ); ///< The maximum size of the popup. -const float POPUP_TAIL_Y_OFFSET( -2.25f ); ///< The y offset of the tail. -const Vector2 POPUP_TAIL_SIZE( 36.0f, 36.0f ); ///< The size of the tail. -const Vector2 POPUP_DIVIDER_SIZE( 1.0f, 126.0f ); ///< The size of the divider. - -const Vector4 OPTION_PADDING( 16.0f, 16.0f, 24.0f, 19.0f ); ///< The padding within the option to position icon and text away from the border. The order is left, right, top and bottom -const Vector2 OPTION_MAX_SIZE( 220.0f, 126.0f ); ///< The maximum size of the option. -const Vector2 OPTION_MIN_SIZE( 128.0f, 126.0f ); ///< The minimum size of the option. -const Vector2 OPTION_ICON_SIZE( 45.0f, 45.0f ); ///< The size of the icon. -const Vector2 OPTION_TEXT_MIN_SIZE( 128.0f, 30.0f ); ///< The minimum size of the text. -const float OPTION_GAP_ICON_TEXT( 8.0f ); ///< The gap between the icon and the text - -const float HIDE_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup hide animation in seconds. -const float SHOW_POPUP_ANIMATION_DURATION( 0.2f ); ///< Duration of popup show animation in seconds. - -/** - * Default Colors - */ -const Vector4 DEFAULT_POPUP_BACKGROUND( Vector4( .20f, 0.29f, 0.44f, 1.0f ) ); -const Vector4 DEFAULT_POPUP_BACKGROUND_PRESSED( Vector4( 0.07f, 0.10f, 0.17f, 1.0f ) ); -const Vector4 DEFAULT_POPUP_LINE_COLOR( Vector4( 0.36f, 0.45f, 0.59f, 1.0f ) ); -const Vector4 DEFAULT_OPTION_ICON( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); -const Vector4 DEFAULT_OPTION_ICON_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); -const Vector4 DEFAULT_OPTION_TEXT( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); -const Vector4 DEFAULT_OPTION_TEXT_PRESSED( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ) ); - -} // unnamed namespace - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace -{ - -// Signals - -const char* const SIGNAL_PRESSED = "pressed"; -const char* const SIGNAL_HIDE_FINISHED = "hide-finished"; -const char* const SIGNAL_SHOW_FINISHED = "show-finished"; - -} - -const char* const TextInputPopup::OPTION_SELECT_WORD = "option-select_word"; // "Select Word" popup option. -const char* const TextInputPopup::OPTION_SELECT_ALL("option-select_all"); // "Select All" popup option. -const char* const TextInputPopup::OPTION_CUT("option-cut"); // "Cut" popup option. -const char* const TextInputPopup::OPTION_COPY("option-copy"); // "Copy" popup option. -const char* const TextInputPopup::OPTION_PASTE("option-paste"); // "Paste" popup option. -const char* const TextInputPopup::OPTION_CLIPBOARD("option-clipboard"); // "Clipboard" popup option. - -TextInputPopup::TextInputPopup() -: mState(StateHidden), - mRoot( Layer::New() ), - mButtons(), - mVisiblePopUpSize(), - mPopupTailXPosition( 0.0f ), - mContentSize(), - mBackgroundColor( DEFAULT_POPUP_BACKGROUND ), - mBackgroundPressedColor( DEFAULT_POPUP_BACKGROUND_PRESSED ), - mLineColor( DEFAULT_POPUP_LINE_COLOR ), - mIconColor( DEFAULT_OPTION_ICON ), - mIconPressedColor( DEFAULT_OPTION_ICON_PRESSED ), - mTextColor( DEFAULT_OPTION_TEXT ), - mTextPressedColor( DEFAULT_OPTION_TEXT_PRESSED ), - mSelectOptionPriority(1), - mSelectAllOptionPriority(2), - mCutOptionPriority(3), - mCopyOptionPriority(4), - mPasteOptionPriority(5), - mClipboardOptionPriority(6), - mPressedSignal(), - mHideFinishedSignal(), - mShowFinishedSignal() -{ - mRoot.SetParentOrigin( ParentOrigin::TOP_LEFT ); - mRoot.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); -} - -void TextInputPopup::AddToParent( Actor parent ) -{ - Actor existingParent = mRoot.GetParent(); - - if ( !existingParent ) - { - parent.Add( mRoot ); - } -} - -void TextInputPopup::RemoveFromParent() -{ - Actor parent = mRoot.GetParent(); - - if ( parent ) - { - parent.Remove( mRoot ); - } -} - -void TextInputPopup::CreateLayer( const Vector2& size ) -{ - mLayer = Layer::New(); - mLayer.SetParentOrigin(ParentOrigin::CENTER); - mLayer.SetAnchorPoint(AnchorPoint::CENTER); - mLayer.SetSize( size ); // matches stencil size - mLayer.SetName("popup-mLayer"); -} - -void TextInputPopup::CreateStencil( const Vector2& size ) -{ - mStencil = CreateSolidColorActor( Color::BLUE ); - mStencil.SetParentOrigin( ParentOrigin::CENTER ); - mStencil.SetAnchorPoint( AnchorPoint::CENTER ); - mStencil.SetDrawMode( DrawMode::STENCIL ); - mStencil.SetVisible( true ); - mStencil.SetName( "popup-stencil" ); - mStencil.SetSize( size ); -} - -void TextInputPopup::OnScrollStarted( const Vector3& position ) -{ - mButtons.SetSensitive( false ); -} - -void TextInputPopup::OnScrollCompleted( const Vector3& position ) -{ - mButtons.SetSensitive( true ); -} - -void TextInputPopup::CreateScrollView() -{ - mScrollView = Toolkit::ScrollView::New(); - mScrollView.SetName("popup-scroll-view"); - mScrollView.SetAnchorPoint( AnchorPoint::CENTER ); - mScrollView.SetParentOrigin( ParentOrigin::CENTER ); - mScrollView.SetScrollingDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 40.0f ) ); - mScrollView.SetAxisAutoLock( true ); - mScrollView.ScrollStartedSignal().Connect( this, &TextInputPopup::OnScrollStarted ); - mScrollView.ScrollCompletedSignal().Connect( this, &TextInputPopup::OnScrollCompleted ); -} - -void TextInputPopup::UpdateScrollViewRulerAndSize( const Vector2& visibleSize ) -{ - mScrollView.SetSize( visibleSize.x, visibleSize.y ); - - RulerPtr rulerX = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed. - RulerPtr rulerY = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed. - rulerY->Disable(); - rulerX->SetDomain( RulerDomain( 0, mContentSize.width, true ) ); - mScrollView.SetRulerX(rulerX); - mScrollView.SetRulerY(rulerY); -} - - -void TextInputPopup::Clear() -{ - if ( mBackground ) - { - UnparentAndReset( mTail ); - UnparentAndReset( mStencil ); - UnparentAndReset( mBackground ); - UnparentAndReset( mButtons ); - UnparentAndReset( mScrollView ); - mDividerContainer.clear(); - RemoveFromParent(); - mState = StateHidden; - } -} - -ImageActor TextInputPopup::CreateOptionIcon( Image iconImage, const Vector4& color ) -{ - ImageActor icon = ImageActor::New( iconImage ); - icon.SetSize( OPTION_ICON_SIZE ); - icon.SetParentOrigin( ParentOrigin::TOP_CENTER ); - icon.SetAnchorPoint( AnchorPoint::TOP_CENTER ); - icon.SetColor( color ); - icon.SetY( OPTION_PADDING.z - POPUP_BORDER.y ); - return icon; -} - -Toolkit::TextView TextInputPopup::CreateOptionCaption( const std::string& caption, const Vector4& color ) -{ - TextStyle style; - style.SetTextColor( color ); - - PointSize pointSize( Font::PixelsToPoints( OPTION_TEXT_MIN_SIZE.y ) ); - style.SetFontPointSize( pointSize ); - - MarkupProcessor::StyledTextArray styledCaption; - styledCaption.push_back( MarkupProcessor::StyledText( Text( caption ), style ) ); - - Toolkit::TextView textView = Toolkit::TextView::New( styledCaption ); - textView.SetWidthExceedPolicy( Toolkit::TextView::EllipsizeEnd ); - textView.SetHeightExceedPolicy( Toolkit::TextView::EllipsizeEnd ); - textView.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); - textView.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); - textView.SetY( -OPTION_PADDING.w + POPUP_BORDER.w ); - - MarkupProcessor::StyledTextArray styledCaptionEllipsize; - MarkupProcessor::SetTextStyle( Text("..."), styledCaptionEllipsize, style ); - textView.SetEllipsizeText( styledCaptionEllipsize ); - - const float textWidth = textView.GetWidthForHeight( OPTION_TEXT_MIN_SIZE.y ); - textView.SetSize( textWidth, OPTION_TEXT_MIN_SIZE.y ); - - return textView; -} - -void TextInputPopup::CreateBackground() -{ - // Create background-panel if not already created (required if we have at least one option) - if ( !mBackground ) - { - Image bgImg = ResourceImage::New( POPUP_BACKGROUND ); - mBackground = ImageActor::New( bgImg ); - mBackground.SetAnchorPoint( AnchorPoint::CENTER ); - mBackground.SetParentOrigin( ParentOrigin::CENTER ); - mBackground.SetName( "text-input-popup-background" ); - mBackground.SetColor( mBackgroundColor ); - - Image bgEffectImg = ResourceImage::New( POPUP_BACKGROUND_EFFECT ); - mBackgroundEffect = ImageActor::New( bgEffectImg ); - mBackgroundEffect.SetAnchorPoint( AnchorPoint::CENTER ); - mBackgroundEffect.SetParentOrigin( ParentOrigin::CENTER ); - mBackgroundEffect.SetName( "text-input-popup-background-effect" ); - mBackgroundEffect.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - mBackgroundEffect.SetZ( 1.0f ); - mBackground.Add( mBackgroundEffect ); - - Image bgLine = ResourceImage::New( POPUP_BACKGROUND_LINE ); - mBackgroundLine = ImageActor::New( bgLine ); - mBackgroundLine.SetAnchorPoint( AnchorPoint::CENTER); - mBackgroundLine.SetParentOrigin( ParentOrigin::CENTER ); - mBackgroundLine.SetName( "text-input-popup-background-effect" ); - mBackgroundLine.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - mBackgroundLine.SetColor( mLineColor ); - mBackgroundLine.SetZ( 0.1f ); - mBackgroundEffect.Add( mBackgroundLine ); - - Hide(false); - } -} - -void TextInputPopup::CreateTail() -{ - if ( !mTail ) - { - Image tail = ResourceImage::New( POPUP_TAIL_BOTTOM ); - mTail = ImageActor::New( tail ); - mTail.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); - mTail.SetAnchorPoint( AnchorPoint::TOP_CENTER ); - mTail.SetName( "text-input-popup-tail" ); - mTail.SetPosition( 0.0f, POPUP_TAIL_Y_OFFSET - POPUP_BORDER.w, 1.2f ); - mTail.SetColor( mBackgroundColor ); - - Image tailEffect = ResourceImage::New( POPUP_TAIL_BOTTOM_EFFECT ); - mTailEffect = ImageActor::New( tailEffect ); - mTailEffect.SetParentOrigin( ParentOrigin::CENTER ); - mTailEffect.SetAnchorPoint( AnchorPoint::CENTER ); - mTailEffect.SetName( "text-input-popup-tail-effect" ); - mTailEffect.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - mTailEffect.SetZ( 0.1f ); - mTail.Add( mTailEffect ); - - Image tailLine = ResourceImage::New( POPUP_TAIL_BOTTOM_LINE ); - mTailLine = ImageActor::New( tailLine ); - mTailLine.SetParentOrigin( ParentOrigin::CENTER ); - mTailLine.SetAnchorPoint( AnchorPoint::CENTER ); - mTailLine.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); - mTailLine.SetName( "text-input-popup-tail-line" ); - mTailLine.SetColor( mLineColor ); - mTailLine.SetZ( 0.1f ); - mTailEffect.Add( mTailLine ); - } -} - -ImageActor TextInputPopup::CreateDivider() -{ - ImageActor divider = Toolkit::CreateSolidColorActor( mLineColor ); - divider.SetParentOrigin( ParentOrigin::TOP_LEFT ); - divider.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - divider.SetSize( POPUP_DIVIDER_SIZE.width , mContentSize.height ); - divider.SetPosition( mContentSize.width - POPUP_DIVIDER_SIZE.width, 0.0f ); - - // Keep track of all the dividers. As their height's need to be updated to the max of all - // buttons currently added. - mDividerContainer.push_back( divider ); - - return divider; -} - -ImageActor TextInputPopup::CreatePressedBackground( const Vector2& requiredSize ) -{ - ImageActor pressedBg = Toolkit::CreateSolidColorActor( mBackgroundPressedColor ); - pressedBg.SetDrawMode( DrawMode::OVERLAY ); - pressedBg.SetParentOrigin( ParentOrigin::CENTER ); - pressedBg.SetAnchorPoint( AnchorPoint::CENTER ); - pressedBg.SetSize( requiredSize ); - return pressedBg; -} - -TextInputPopup::ButtonRequirement TextInputPopup::CreateRequiredButton( TextInputPopup::Buttons buttonId, std::size_t orderOfPriority, - const std::string& name, const std::string& caption, Image iconImage, bool enabled ) -{ - TextInputPopup::ButtonRequirement currentButton; - currentButton.buttonId = buttonId; - currentButton.orderOfPriority = orderOfPriority; - currentButton.name = name; - currentButton.caption = caption; - currentButton.iconImage = iconImage; - currentButton.enabled = enabled; - - return currentButton; -} - -void TextInputPopup::CreateOrderedListOfOptions() -{ - mOrderListOfButtons.clear(); - - for ( std::size_t index= 0; index < ButtonsEnumEnd; index++ ) - { - TextInputPopup::ButtonRequirement currentButton; - - // Create button for each possible option using Option priority - switch ( index ) - { - case ButtonsCut: - { - Image cutIcon = ResourceImage::New( OPTION_ICON_CUT ); - currentButton = CreateRequiredButton( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), cutIcon, false ); - break; - } - case ButtonsCopy: - { - Image copyIcon = ResourceImage::New( OPTION_ICON_COPY ); - currentButton = CreateRequiredButton( ButtonsCopy, mCopyOptionPriority, OPTION_COPY, GET_LOCALE_TEXT("IDS_COM_BODY_COPY"), copyIcon, false ); - break; - } - case ButtonsPaste: - { - Image pasteIcon = ResourceImage::New( OPTION_ICON_PASTE ); - currentButton = CreateRequiredButton( ButtonsPaste, mPasteOptionPriority, OPTION_PASTE, GET_LOCALE_TEXT("IDS_COM_BODY_PASTE"), pasteIcon, false ); - break; - } - case ButtonsSelect: - { - Image selectIcon = ResourceImage::New( OPTION_ICON_SELECT ); - currentButton = CreateRequiredButton( ButtonsSelect, mSelectOptionPriority, OPTION_SELECT_WORD, GET_LOCALE_TEXT("IDS_COM_SK_SELECT"), selectIcon, false ); - break; - } - case ButtonsSelectAll: - { - Image selectAllIcon = ResourceImage::New( OPTION_ICON_SELECT_ALL ); - currentButton = CreateRequiredButton( ButtonsSelectAll, mSelectAllOptionPriority, OPTION_SELECT_ALL, GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL"), selectAllIcon, false ); - break; - } - case ButtonsClipboard: - { - Image clipboardIcon = ResourceImage::New( OPTION_ICON_CLIPBOARD ); - currentButton = CreateRequiredButton( ButtonsClipboard, mClipboardOptionPriority, OPTION_CLIPBOARD, GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD"), clipboardIcon, false ); - break; - } - } - - bool match = false; - - // Insert button in list of buttons in order of priority setting. - for( std::vector::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it ) - { - const ButtonRequirement& button( *it ); - if ( currentButton.orderOfPriority < button.orderOfPriority ) - { - if ( currentButton.orderOfPriority != 0 ) // If order priority 0 then do not add button as not required. - { - mOrderListOfButtons.insert( it, currentButton ); - } - match = true; - } - } - - if ( !match ) - { - mOrderListOfButtons.push_back( currentButton ); - } - } -} - -Vector2 TextInputPopup::GetConstrainedTextSize( const Vector2& textSize ) -{ - return Vector2( std::min( textSize.width, OPTION_MAX_SIZE.width - OPTION_PADDING.x - OPTION_PADDING.y ), textSize.height ); -} - -void TextInputPopup::AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption) -{ - // 1. Create container for text and icon when not pressed. - Actor optionContainer = Actor::New(); - optionContainer.SetParentOrigin( ParentOrigin::TOP_LEFT ); - optionContainer.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - - // 2. Add text. - Toolkit::TextView captionTextView = CreateOptionCaption( caption, mTextColor ); - optionContainer.Add( captionTextView ); - - // 3. Add icon. - ImageActor icon = CreateOptionIcon( iconImage, mIconColor ); - optionContainer.Add( icon ); - - // 4. Calculate the size of option. - const Vector2 textSize = Vector2( captionTextView.GetNaturalSize() ); - captionTextView.SetSize( GetConstrainedTextSize( textSize ) ); - - - const Vector2 optionSize( std::max( textSize.x, OPTION_ICON_SIZE.x ) + OPTION_PADDING.x + OPTION_PADDING.z, - OPTION_PADDING.z + OPTION_ICON_SIZE.y + OPTION_GAP_ICON_TEXT + textSize.y + OPTION_MAX_SIZE.y ); - - - Vector2 constrainedOptionSize = Min( Max( optionSize, OPTION_MIN_SIZE ), OPTION_MAX_SIZE ); - - constrainedOptionSize.height = constrainedOptionSize.height - POPUP_BORDER.y - POPUP_BORDER.z; - - // 5. Create a option. - Toolkit::PushButton option = Toolkit::PushButton::New(); - option.SetParentOrigin( ParentOrigin::TOP_LEFT ); - option.SetAnchorPoint( AnchorPoint::TOP_LEFT ); - option.SetSize( constrainedOptionSize ); - option.SetX( mContentSize.x ); - option.SetName( name ); - option.SetAnimationTime( 0.0f ); - option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed ); - mButtons.Add( option ); - - // 6. Set the normal option image. - option.SetButtonImage( optionContainer ); - - // 7. Update the content size. - mContentSize.x += constrainedOptionSize.x; - mContentSize.y = std::max ( constrainedOptionSize.y, mContentSize.y ); - - // 8. Create the pressed container. - Actor optionPressedContainer = Actor::New(); - - // 9. Add option pressed background. - Vector2 optionPressedBackgroundSize( constrainedOptionSize.x - POPUP_BORDER.x, mContentSize.y - POPUP_BORDER.y - POPUP_BORDER.w ); - ImageActor optionPressedBackground = CreatePressedBackground( optionPressedBackgroundSize ); - optionPressedContainer.Add( optionPressedBackground ); - - // 10. Add pressed text - Toolkit::TextView pressedCaptionTextView = CreateOptionCaption( caption, mTextPressedColor ); - pressedCaptionTextView.SetSize( GetConstrainedTextSize( Vector2( pressedCaptionTextView.GetNaturalSize() ) ) ); - optionPressedBackground.Add( pressedCaptionTextView ); - - // 11. Add pressed icon - ImageActor pressedIcon = CreateOptionIcon( iconImage, mIconPressedColor ); - optionPressedBackground.Add( pressedIcon ); - - // 12. Set the pressed option image - option.SetSelectedImage( optionPressedContainer ); - - // 13. Add the divider - if ( !finalOption ) - { - ImageActor divider = CreateDivider(); - mButtons.Add( divider ); - } -} - -void TextInputPopup::Hide(bool animate) -{ - if( mRoot ) - { - if(mAnimation) - { - mAnimation.Clear(); - mAnimation.Reset(); - } - - if(animate) - { - mAnimation = Animation::New( HIDE_POPUP_ANIMATION_DURATION ); - mAnimation.AnimateTo( Property(mRoot, Actor::Property::SCALE), Vector3::ZERO, AlphaFunctions::EaseOut ); - mAnimation.AnimateTo( Property(mRoot, Actor::Property::COLOR_ALPHA), 0.0f, AlphaFunctions::EaseOut ); - mAnimation.Play(); - - mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnHideFinished ); - mState = StateHiding; - } - else - { - mRoot.SetProperty(Actor::Property::SCALE, Vector3::ZERO); - mRoot.SetProperty(Actor::Property::COLOR_ALPHA, 0.0f); - mState = StateHidden; - } - } -} - -void TextInputPopup::Show( Actor target, bool animate ) -{ - if( mRoot ) - { - mRoot.SetSensitive( true ); - - if(mAnimation) - { - mAnimation.Clear(); - mAnimation.Reset(); - } - - if ( target ) - { - AddToParent( target ); - } - - if(animate) - { - mAnimation = Animation::New( SHOW_POPUP_ANIMATION_DURATION ); - mAnimation.AnimateTo( Property(mRoot, Actor::Property::SCALE), Vector3::ONE, AlphaFunctions::EaseOut ); - mAnimation.AnimateTo( Property(mRoot, Actor::Property::COLOR_ALPHA), 1.0f, AlphaFunctions::EaseOut ); - mAnimation.Play(); - - mAnimation.FinishedSignal().Connect( this, &TextInputPopup::OnShowFinished ); - mState = StateShowing; - } - else - { - mRoot.SetProperty(Actor::Property::SCALE, Vector3::ONE); - mRoot.SetProperty(Actor::Property::COLOR_ALPHA, 1.0f); - mState = StateShown; - } - } -} - -TextInputPopup::State TextInputPopup::GetState(void) const -{ - return mState; -} - -Actor TextInputPopup::GetRootActor() const -{ - return mRoot; -} - -// Styling - -void TextInputPopup::SetCutPastePopupColor( const Vector4& color ) -{ - mBackgroundColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupColor() const -{ - return mBackgroundColor; -} - -void TextInputPopup::SetCutPastePopupPressedColor( const Vector4& color ) -{ - mBackgroundPressedColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupPressedColor() const -{ - return mBackgroundPressedColor; -} - -void TextInputPopup::SetCutPastePopupBorderColor( const Vector4& color ) -{ - mLineColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupBorderColor() const -{ - return mLineColor; -} - -void TextInputPopup::SetCutPastePopupIconColor( const Vector4& color ) -{ - mIconColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupIconColor() const -{ - return mIconColor; -} - -void TextInputPopup::SetCutPastePopupIconPressedColor( const Vector4& color ) -{ - mIconPressedColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupIconPressedColor() -{ - return mIconPressedColor; -} - -void TextInputPopup::SetCutPastePopupTextColor( const Vector4& color ) -{ - mTextColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupTextColor() -{ - return mTextColor; -} - -void TextInputPopup::SetCutPastePopupTextPressedColor( const Vector4& color ) -{ - mTextPressedColor = color; -} - -const Vector4& TextInputPopup::GetCutPastePopupTextPressedColor() -{ - return mTextPressedColor; -} - -void TextInputPopup::TogglePopupButtonOnOff( TextInputPopup::Buttons requiredButton, bool enable ) -{ - bool match ( false ); - for( std::vector::iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt && !match ); ++it ) - { - ButtonRequirement& button( *it ); - if ( requiredButton == button.buttonId ) - { - button.enabled = enable; - match = true; - } - } -} - -void TextInputPopup::SetButtonPriorityPosition( TextInputPopup::Buttons button, unsigned int priority ) -{ - switch ( button ) - { - case ButtonsCut: - { - mCutOptionPriority = priority; - break; - } - case ButtonsCopy: - { - mCopyOptionPriority = priority; - break; - } - case ButtonsPaste: - { - mPasteOptionPriority = priority; - break; - } - case ButtonsSelect: - { - mSelectOptionPriority = priority; - break; - } - case ButtonsSelectAll: - { - mSelectAllOptionPriority = priority; - break; - } - case ButtonsClipboard: - { - mClipboardOptionPriority = priority; - break; - } - case ButtonsEnumEnd: - { - DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice"); - break; - } - } - CreateOrderedListOfOptions(); // Update list of options as priority changed. -} - -unsigned int TextInputPopup::GetButtonPriorityPosition( TextInputPopup::Buttons button ) const -{ - unsigned int priority = 0; - - switch ( button ) - { - case ButtonsCut: - { - priority = mCutOptionPriority; - break; - } - case ButtonsCopy: - { - priority = mCopyOptionPriority; - break; - } - case ButtonsPaste: - { - priority = mPasteOptionPriority; - break; - } - case ButtonsSelect: - { - priority = mSelectOptionPriority; - break; - } - case ButtonsSelectAll: - { - priority = mSelectAllOptionPriority; - break; - } - case ButtonsClipboard: - { - priority = mClipboardOptionPriority; - break; - } - case ButtonsEnumEnd: - { - DALI_ASSERT_DEBUG( "ButtonsEnumEnd used but an invalid choice"); - break; - } - } - - return priority; -} - -void TextInputPopup::AddPopupOptions() -{ - mContentSize = Vector2( POPUP_MIN_SIZE.width, ( POPUP_BORDER.y + POPUP_BORDER.z ) ); - - // 1. Create the background. - CreateBackground(); - - // 2. Create the tail. - CreateTail(); - - // 3. Create the scroll view and Actor to hold buttons. - CreateScrollView(); - - // Clear previous buttons - if ( mButtons ) - { - UnparentAndReset( mButtons ); - } - - mButtons = Actor::New(); - mButtons.SetParentOrigin( ParentOrigin::CENTER ); - mButtons.SetAnchorPoint( AnchorPoint::CENTER ); - - // 4. Create the options and add into the scroll view. - for( std::vector::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it ) - { - const ButtonRequirement& button( *it ); - if ( button.enabled ) - { - AddOption( button.name, button.caption, button.iconImage, it != ( endIt - 1 ) ? false : true ); - } - } - - // 5. Calculate size of content and of popup including borders - const Vector2 popupSize = Vector2( std::min ( ( POPUP_BORDER.x + mContentSize.width + POPUP_BORDER.z ), POPUP_MAX_SIZE.width ) , POPUP_BORDER.y + mContentSize.height + POPUP_BORDER.w ); - - mVisiblePopUpSize = Vector3( popupSize.width - POPUP_BORDER.x - POPUP_BORDER.z , mContentSize.height, 1.0f); - - mBackground.SetSize( popupSize.x + 28 - POPUP_BORDER.x - POPUP_BORDER.z, popupSize.y + 28 - POPUP_BORDER.y - POPUP_BORDER.w ); - mButtons.SetSize( mVisiblePopUpSize.GetVectorXY() ); - - // 6. Set the scroll view ruler. - UpdateScrollViewRulerAndSize( mVisiblePopUpSize.GetVectorXY() ); - - // 7. Create stencil - const Vector2 stencilSize = Vector2( mVisiblePopUpSize.GetVectorXY() ); - - CreateLayer( stencilSize ); - CreateStencil( stencilSize ); - - mScrollView.Add ( mButtons ); - mLayer.Add( mScrollView); - mLayer.Add( mStencil); - mRoot.Add( mTail ); - mRoot.Add( mBackground ); - mRoot.Add( mLayer ); - - // 8. Set the root size. - mRoot.SetSize( popupSize ); // Make Root Actor reflect the size of its content -} - -const Vector3& TextInputPopup::GetVisibileSize() const -{ - return mVisiblePopUpSize; -} - -void TextInputPopup::SetTailPosition( const Vector3& position, bool yAxisFlip ) -{ - mPopupTailXPosition = std::max( position.x, POPUP_TAIL_SIZE.width*0.5f - mVisiblePopUpSize.width*0.5f + POPUP_BORDER.x ); - - std::min( mPopupTailXPosition, mVisiblePopUpSize.width*0.5f - POPUP_BORDER.x - POPUP_TAIL_SIZE.width*0.5f ); - - mTail.SetX( mPopupTailXPosition ); - - if ( yAxisFlip ) - { - Image tail = ResourceImage::New( POPUP_TAIL_TOP ); - Image tailEffect = ResourceImage::New( POPUP_TAIL_TOP_EFFECT ); - Image tailLine = ResourceImage::New( POPUP_TAIL_TOP_LINE ); - - mTail.SetImage( tail ); - mTailEffect.SetImage( tailEffect ); - mTailLine.SetImage( tailLine ); - - mTail.SetParentOrigin( ParentOrigin::TOP_CENTER ); - mTail.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); - mTail.SetY( POPUP_BORDER.y - POPUP_TAIL_Y_OFFSET ); - } -} - -bool TextInputPopup::OnButtonPressed( Toolkit::Button button ) -{ - mPressedSignal.Emit( button ); - return false; -} - -void TextInputPopup::OnHideFinished(Animation& source) -{ - source.FinishedSignal().Disconnect( this, &TextInputPopup::OnHideFinished ); - Clear(); - mState = StateHidden; - mHideFinishedSignal.Emit( *this ); -} - -void TextInputPopup::OnShowFinished(Animation& source) -{ - source.FinishedSignal().Disconnect( this, &TextInputPopup::OnShowFinished ); - mState = StateShown; - mShowFinishedSignal.Emit( *this ); -} - -TextInputPopup::PressedSignalType& TextInputPopup::PressedSignal() -{ - return mPressedSignal; -} - -TextInputPopup::VisibilityChangeFinishedSignalType& TextInputPopup::HideFinishedSignal() -{ - return mHideFinishedSignal; -} - -TextInputPopup::VisibilityChangeFinishedSignalType& TextInputPopup::ShowFinishedSignal() -{ - return mShowFinishedSignal; -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h b/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h deleted file mode 100644 index 2f9a91d..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-popup-impl.h +++ /dev/null @@ -1,469 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_H__ - -/* - * Copyright (c) 2014 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 -#include -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -class Button; - -namespace Internal -{ - -class TextInputPopup : public ConnectionTracker -{ - -public: - - enum State - { - StateHidden, - StateHiding, - StateShowing, - StateShown - }; - - enum Buttons - { - ButtonsCut, - ButtonsCopy, - ButtonsPaste, - ButtonsSelect, - ButtonsSelectAll, - ButtonsClipboard, - ButtonsEnumEnd - }; - - struct ButtonRequirement - { - TextInputPopup::Buttons buttonId; - std::size_t orderOfPriority; - std::string name; - std::string caption; - Image iconImage; - bool enabled; - }; - - static const char* const OPTION_SELECT_WORD; - static const char* const OPTION_SELECT_ALL; - static const char* const OPTION_CUT; - static const char* const OPTION_COPY; - static const char* const OPTION_PASTE; - static const char* const OPTION_CLIPBOARD; - - // Popup Button Pressed - typedef Signal< bool( Toolkit::Button ) > PressedSignalType; - - // Popup Hide / Show Finished - typedef Signal< void( TextInputPopup& ) > VisibilityChangeFinishedSignalType; - - /** - * Signal emitted when the button is touched. - */ - PressedSignalType& PressedSignal(); - - /** - * Signal emitted when popup is completely hidden - * @note Only occurs after a Show() call with animation enabled. - */ - VisibilityChangeFinishedSignalType& HideFinishedSignal(); - - /** - * Signal emitted when popup is completely shown - * @note Only occurs after a Hide() call with animation enabled. - */ - VisibilityChangeFinishedSignalType& ShowFinishedSignal(); - -public: - - /** - * Default constructor - * Creates an empty popup base actor (no content i.e. invisible) - */ - TextInputPopup(); - - /** - * Clears popup options (popup no longer exists) - */ - void Clear(); - - /** - * Create the label - * @return the newly created Image actor to be used as the icon - */ - ImageActor CreateOptionIcon( Image iconImage, const Vector4& color ); - - /** - * Create the caption - * @param[in] styledCaption The text to be displayed - * @return the newly created label - */ - Toolkit::TextView CreateOptionCaption( const std::string& caption, const Vector4& color ); - - /** - * Creates and sets up the background - */ - void CreateBackground(); - - /** - * Create and set up the tail - */ - void CreateTail(); - - /** - * Create divider if multiple options - * @return Return a divider image actor - */ - ImageActor CreateDivider(); - - /** - * Create a background to be used when option pressed - * @param[in] requiredSize size Image actor should be - * @return Returns an Image Actor to be used a pressed background - */ - ImageActor CreatePressedBackground( const Vector2& requiredSize ); - - /** - * Creates a ordered vector of button options - */ - void CreateOrderedListOfOptions(); - - /** - * Get the TextSize after constrained by the Popup margins. - * @param[in] textSize Natural size of text - * @return Vector2 constrained text size. - * - */ - Vector2 GetConstrainedTextSize( const Vector2& textSize ); - - /** - * Adds a popup option. - * @note Creates popup frame if not already created. - * @param[in] name The unique name for this option. - * @param[in] caption The caption (label) for this option - * @param[in] iconImage Image to displayed with text. - * @param[in] finalOption Flag to indicate that this is the final option. - * (set to true on the last option you add) - */ - void AddOption(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption); - - /** - * Hides the popup - * @param[in] animate (optional) whether to animate popup to hide state over time (i.e. tween). - */ - void Hide(bool animate = true); - - /** - * Shows the popup - * @param[in] animate (optional) whether to animate popup to show state over time (i.e. tween). - * @param[in] target Actor to parent popup. - */ - void Show( Actor target, bool animate = true ); - - /** - * Returns the current state of the popup. - * @return The state of the popup see enum State - */ - State GetState(void) const; - - /** - * Get the root actor which the buttons are added to. - * @return the root actor - */ - Actor GetRootActor() const; - - /** - * Set the Cut and Paste buttons color when in normal state - * @param[in] color color to use - */ - void SetCutPastePopupColor( const Vector4& color ); - - /** - * Get the set color of the Copy and Paste Popup buttons - * @return color - */ - const Vector4& GetCutPastePopupColor() const; - - /** - * Set the Cut and Paste button color when pressed. - * @param[in] color color to use - */ - void SetCutPastePopupPressedColor( const Vector4& color ); - - /** - * Get the Cut and Paste pressed button color. - * @return color - */ - const Vector4& GetCutPastePopupPressedColor() const; - - /** - * Set the border color of the popup - * @param[in] color required color - */ - void SetCutPastePopupBorderColor( const Vector4& color ); - - /** - * Get the border color - * @return Vector4 the color of the border - */ - const Vector4& GetCutPastePopupBorderColor() const; - - /** - * Toggle if a popup button should be enabled (shown) or not - * @param[in] requiredButton Button Id to enable or disable - * @param[in] enable toggle to enable (true) or disable (false) - */ - void TogglePopupButtonOnOff( TextInputPopup::Buttons requiredButton, bool enable ); - - /** - * Set the Button Priority Position - * @param[in] button Button id for priority to be set on - * @param[in] priority Priority level, 1 is highest so will appear first. 0 priority will not show the button. - */ - void SetButtonPriorityPosition( TextInputPopup::Buttons button, unsigned int priority ); - - /** - * Set the icon color of the popup - * @param[in] color required color - */ - void SetCutPastePopupIconColor( const Vector4& color ); - - /** - * Get the popup icon color - * @return Vector4 the color of the popup icon - */ - const Vector4& GetCutPastePopupIconColor() const; - - /** - * Set the pressed icon color of the popup - * @param[in] color required color - */ - void SetCutPastePopupIconPressedColor( const Vector4& color ); - - /** - * Get the popup pressed icon color - * @return Vector4 the color of the popup pressed icon - */ - const Vector4& GetCutPastePopupIconPressedColor(); - - /** - * Set the text color of the popup - * @param[in] color required color - */ - void SetCutPastePopupTextColor( const Vector4& color ); - - /** - * Get the popup text color - * @return Vector4 the color of the popup text - */ - const Vector4& GetCutPastePopupTextColor(); - - /** - * Set the pressed text color of the popup - * @param[in] color required color - */ - void SetCutPastePopupTextPressedColor( const Vector4& color ); - - /** - * Get the popup pressed text color - * @return Vector4 the color of the popup pressed text - */ - const Vector4& GetCutPastePopupTextPressedColor(); - - /** - * Get the Button Priority Position - * @param[in] button Button id to get priority of - * @return the button priority, 1 is highest, 0 is not shown. - */ - unsigned int GetButtonPriorityPosition( TextInputPopup::Buttons button ) const; - - /** - * Adds Popup options which have been enabled. - */ - void AddPopupOptions(); - - /** - * Get Visible size of the Popup, excludes content that needs scrolling - * @return Vector3 size of Popup - */ - const Vector3& GetVisibileSize() const; - - /** - * Sets the positon of the PopUp tail relative to TextInput - * @param[in] position Position to set - * @param[in] yAxisFlip If tail should be flipped in y axis - */ - void SetTailPosition( const Vector3& position, const bool yAxisFlip ); - -private: - - /** - * Creates a Button with the required parameters. - * @param[in] buttonId enum representing the button - * @param[in] orderOfPriority Position in toolbar button should be position, 1 is first from left to right. - * @param[in] name Given name for Button actor - * @param[in] caption Text to display in button - * @param[in] iconImage Icon to display in button - * @param[in] enabled Toggle if button should be used or not, this is decided by the current state/conditions. - */ - TextInputPopup::ButtonRequirement CreateRequiredButton( TextInputPopup::Buttons buttonId, std::size_t orderOfPriority, - const std::string& name, const std::string& caption, Image iconImage, bool enabled ); - - /** - * @brief Adds popup to the given parent - * @paran[in] parent target to add Popup to - */ - void AddToParent( Actor parent ); - - /** - * @brief Removes Popup from Parent - */ - void RemoveFromParent(); - - /** - * Applies constraint to keep Popup in view within the desired area. - */ - void ApplyConfinementConstraint(); - - /** - * Applies constraint to keep the Tail attached to Popup - */ - void ApplyTailConstraint(); - - /** - * Create Layer to be used with stencil to allow scrolling of buttons which do not fit in visible popup - * @param[in] size of the layer. - */ - void CreateLayer( const Vector2& size ); - - /** - * Create a stencil to clip the scroll view content - * @param[in] size of the stencil. - */ - void CreateStencil( const Vector2& size ); - - /** - * Popup has started to scroll - * @param[in] position current scroll view position - */ - void OnScrollStarted( const Vector3& position ); - - /** - * Popup has stopped scrolling - * @param[in] position current scroll view position - */ - void OnScrollCompleted( const Vector3& position ); - - /** - * Create a scroll view to hold the popup buttons and allow scrolling if too many buttons to fit within the visible boundary - */ - void CreateScrollView(); - - /** - * Set the scroll view size and ruler. - * @param[in] visibleSize size of the visible scroll view - */ - void UpdateScrollViewRulerAndSize( const Vector2& visibleSize ); - - /** - * Called when a button is pressed in the Popup - * @param[in] button The button pressed. - */ - bool OnButtonPressed( Toolkit::Button button ); - - /** - * Invoked upon popup Hide animation completing. - * @note Only called for animating hide, not called for instantaneous (animate = false) - * @param[in] source The animation which completed. - */ - void OnHideFinished(Animation& source); - - /** - * Invoked upon popup Show animation completing. - * @note Only called for animating show, not called for instantaneous (animate = false) - * @param[in] source The animation which completed. - */ - void OnShowFinished(Animation& source); - -private: - - State mState; ///< Popup State. - Layer mRoot; ///< The actor which all popup content is added to (i.e. panel and buttons) - Actor mButtons; ///< Actor which holds all the buttons, sensitivity can be set on all buttons via this actor - ImageActor mBackground; ///< The background popup panel - ImageActor mBackgroundEffect; ///< The background effect - ImageActor mBackgroundLine; ///< The background line - ImageActor mTail; ///< The tail for the popup - ImageActor mTailEffect; ///< the tail effect - ImageActor mTailLine; ///< The border/outline around the tail - - Vector3 mVisiblePopUpSize; ///< Visible Size of Popup excluding content that needs scrolling. - float mPopupTailXPosition; ///< X position of PopUp tail. - - Vector2 mContentSize; ///< Size of Content (i.e. Buttons) - ActorContainer mDividerContainer; ///< List of dividers added to popup. - Animation mAnimation; ///< Popup Hide/Show animation. - - Layer mLayer; ///< Layer to be used with Stencil - Actor mStencil; ///< Stencil to clip scrollview - Toolkit::ScrollView mScrollView; ///< Scrollview to house the popup - - std::vector mOrderListOfButtons; // List of buttons in the order to be displayed and a flag to indicate if needed. - - Vector4 mBackgroundColor; // Color of the background of the text input popup - Vector4 mBackgroundPressedColor; // Color of the option background. - Vector4 mLineColor; // Color of the line around the text input popup - Vector4 mIconColor; // Color of the popup icon. - Vector4 mIconPressedColor; // Color of the popup icon when pressed. - Vector4 mTextColor; // Color of the popup text. - Vector4 mTextPressedColor; // Color of the popup text when pressed. - - // Priority of Options/Buttons in the Cut and Paste pop-up, higher priority buttons are displayed first, left to right. - std::size_t mSelectOptionPriority; // Position of Select Button - std::size_t mSelectAllOptionPriority; // Position of Select All button - std::size_t mCutOptionPriority; // Position of Cut button - std::size_t mCopyOptionPriority; // Position of Copy button - std::size_t mPasteOptionPriority; // Position of Paste button - std::size_t mClipboardOptionPriority; // Position of Clipboard button - - PressedSignalType mPressedSignal; ///< Signal emitted when a button within the popup is pressed. - VisibilityChangeFinishedSignalType mHideFinishedSignal; ///< Signal emitted when popup is completely hidden - VisibilityChangeFinishedSignalType mShowFinishedSignal; ///< Signal emitted when popup is completely shown - -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_ITEM_VIEW_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h b/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h deleted file mode 100644 index 92f6bad..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-popup-new-impl.h +++ /dev/null @@ -1,268 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES - -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * @brief Class to create and Popup bar made up of buttons. - * It provides signals when a button is pressed. - * The Popup must be positioned by it's owner. - * The future plan is to reuse the Toolkit Popup control to house the buttons. - */ - -class TextInputPopupNew : public ConnectionTracker -{ - -public: - - enum State - { - StateHidden, - StateHiding, - StateShowing, - StateShown - }; - - // Popup Button Pressed - typedef Signal< bool( Toolkit::Button ) > PopUpPressedSignal; - - // Popup Hide Finished - typedef Signal< void( TextInputPopupNew& ) > PopUpVisibilityChangeFinishedSignal; - - /** - * Signal emitted when the button is touched. - */ - PopUpPressedSignal& PressedSignal() { return mPressedSignal; } - - /** - * Signal emitted when popup is completely hidden - * @note Only occurs after a Show() call with animation enabled. - */ - PopUpVisibilityChangeFinishedSignal& HideFinishedSignal() { return mHideFinishedSignal; } - - /** - * Signal emitted when popup is completely shown - * @note Only occurs after a Hide() call with animation enabled. - */ - PopUpVisibilityChangeFinishedSignal& ShowFinishedSignal() { return mShowFinishedSignal; } - -public: - - /** - * Default constructor - * Creates an empty popup base actor (no content i.e. invisible) - */ - TextInputPopupNew() - : mState(StateHidden) - { }; - - /** - * Destructor - */ - ~TextInputPopupNew(){}; - - /** - * @return The root actor of for this popup is returned. - */ - Actor Self() { return mRootActor; }; - - /** - * Clears popup options (popup no longer exists) - */ - void Clear(){}; - - /** - * Create the label - * @param[in] styledCaption The text to be displayed - * @return the newly created label - */ - Toolkit::TextView CreateLabel( const MarkupProcessor::StyledTextArray& styledCaption ){return Toolkit::TextView();}; - - /** - * Create the label - * @param[in] iconImage the image to be used - * @return the newly created Image actor to be used as the icon - */ - ImageActor CreateIcon( Image iconImage ) {return ImageActor();}; - - /** - * Creates and sets up the popup background - */ - void CreatePopUpBackground(){}; - - /** - * Create divider if multiple options - */ - void CreateDivider(){}; - - /** - * Create a background to be used when button pressed - * @param[in] requiredSize size Image actor should be - * @param[in] finalFlag flag to be set if option is the final one. - * @return Returns an Image Actor to be used a pressed background - */ - ImageActor CreatePressedBackground( const Vector3 requiredSize, const bool finalFlag ){ return ImageActor(); }; - - /** - * Adds a popup option button. - * @note Creates popup frame if not already created. - * @param[in] name The unique name for this option. - * @param[in] caption The caption (label) for this option - * @param[in] iconImage Image to displayed with text. - * @param[in] finalOption Flag to indicate that this is the final option. - * (set to true on the last option you add) - */ - void AddButton(const std::string& name, const std::string& caption, const Image iconImage, bool finalOption ){}; - - /** - * Hides the popup - * @param[in] animate (optional) whether to animate popup to hide state over time (i.e. tween). - */ - void Hide(bool animate = true){}; - - /** - * Shows the popup - * @param[in] animate (optional) whether to animate popup to show state over time (i.e. tween). - * @param[in] target Actor to parent popup. - */ - void Show( Actor target, bool animate = true ){}; - - /** - * @brief Get the calculated size of the PopUp - * This can not be set directly as is calculated depending on the content added. - * - * @return Vector3 size of PopUp. - */ - Vector3 GetSize() const { return Vector3::ZERO;}; - - /** - * Returns the current state of the popup. - * @return The state of the popup see enum State - */ - State GetState(void) const{ return StateHidden;}; - - /** - * Get the root actor which the buttons are added to. - * @return the root actor - */ - Actor GetRootActor() const { return Actor(); }; - - /** - * @brief Creates the PopUp with the required buttons for the provided states. - * @param[in] isAllTextSelectedAlready Is all the text already selected - * @param[in] isTextEmpty Contains some text - * @param[in] hasClipboardGotContent Something to paste from clipboard - * @param[in] isSubsetOfTextAlreadySelected Some but not all text is selected - */ - void CreateCutCopyPastePopUp( bool isAllTextSelectedAlready, bool isTextEmpty, bool hasClipboardGotContent, bool isSubsetOfTextAlreadySelected ){}; - - /** - * @brief Applies constraint to keep Popup in view within the desired area. - * @param[in] bounding box in which the PopUp must remain. - * - */ - void ApplyConfinementConstraint( Vector4 boundingBox ){}; - -private: - - /** - * @brief Adds popup to the given parent - * @paran[in] parent target to add Popup to - */ - void AddToParent( Actor parent ){}; - - /** - * Removes popup from Parent. - */ - void RemoveFromStage(){}; - - /** - * Called when a button is pressed in the popup - * @param[in] button The button pressed. - */ - bool OnButtonPressed( Toolkit::Button button ){return false;}; - - /** - * Invoked upon popup Hide animation completing. - * @note Only called for animating hide, not called for instantaneous (animate = false) - * @param[in] source The animation which completed. - */ - void OnHideFinished(Animation& source){}; - - /** - * Invoked upon popup Show animation completing. - * @note Only called for animating show, not called for instantaneous (animate = false) - * @param[in] source The animation which completed. - */ - void OnShowFinished(Animation& source); - -private: - - /** - * @brief Copy Constructor - * @param[in] popup - * Undefined/Hidden. - */ - TextInputPopupNew(const TextInputPopupNew& popup ); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - TextInputPopupNew& operator=(const TextInputPopupNew& rhs); - -private: - - State mState; // Popup State. - Actor mRootActor; // The actor which all popup content is added to (i.e. panel and buttons) - Vector3 mPopupSize; // Size of the PopUp determined by it's content and max/min size constraints. - ImageActor mBackground; // The background popup panel - ImageActor mTail; // The tail for the popup - Vector3 mContentSize; // Size of Content (i.e. Buttons) - ActorContainer mButtonContainer; // List of buttons added to popup. - ActorContainer mDividerContainer; // List of dividers added to popup. - Animation mAnimation; // Popup Hide/Show animation. - - PopUpPressedSignal mPressedSignal; // Signal emitted when a button within the popup is pressed. - PopUpVisibilityChangeFinishedSignal mHideFinishedSignal; // Signal emitted when popup is completely hidden - PopUpVisibilityChangeFinishedSignal mShowFinishedSignal; // Signal emitted when popup is completely shown - -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_POPUP_NEW_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.cpp b/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.cpp deleted file mode 100644 index 2659f48..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include -#include - -// INTERNAL INCLUDES - -using namespace Dali; - -namespace -{ - /** - * Selection state enumeration (FSM) - */ - enum SelectionState - { - SelectionNone, ///< Currently not encountered selected section. - SelectionStarted, ///< Encountered selected section - SelectionFinished ///< Finished selected section - }; - - const Vector4 LIGHTBLUE( 10.0f/255.0f, 140.0f/255.0f, 210.0f/255.0f, 1.0f ); // todo make this a setting - - const float CHARACTER_THRESHOLD( 2.5f ); // todo check if unified method to do this in Text -} - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -// Default constructor -TextHighlight::TextHighlight( TextViewCharacterPositioning& textViewCharacterPositioning ) : - mTextViewCharacterPositioning( textViewCharacterPositioning ) -{ -} - -TextHighlight::~TextHighlight() -{ -} - -void TextHighlight::GetVisualTextSelection(std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection, - Toolkit::TextView::TextLayoutInfo& textLayoutInfo ) -{ - std::vector::iterator it = textLayoutInfo.mCharacterLogicalToVisualMap.begin(); - std::vector::iterator startSelectionIt = textLayoutInfo.mCharacterLogicalToVisualMap.begin() + std::min(startSelection, endSelection); - std::vector::iterator endSelectionIt = textLayoutInfo.mCharacterLogicalToVisualMap.begin() + std::max(startSelection, endSelection); - std::vector::iterator end = textLayoutInfo.mCharacterLogicalToVisualMap.end(); - - selectedVisualText.resize( mTextViewCharacterPositioning.GetNumberOfCharactersInText() ); - - // Deselect text prior to startSelectionIt - for(;it!=startSelectionIt;++it) - { - selectedVisualText[*it] = false; - } - - // Select text from startSelectionIt -> endSelectionIt - for(;it!=endSelectionIt;++it) - { - selectedVisualText[*it] = true; - } - - // Deselect text after endSelection - for(;it!=end;++it) - { - selectedVisualText[*it] = false; - } - - selectedVisualText.resize( mTextViewCharacterPositioning.GetNumberOfCharactersInText(), false ); -} - -// Calculate the dimensions of the quads they will make the highlight mesh -TextHighlight::HighlightInfo TextHighlight::CalculateHighlightInfo( std::size_t handlePositionStart, std::size_t handlePositionEnd, Toolkit::TextView::TextLayoutInfo& textLayoutInfo ) -{ - // At the moment there is no public API to modify the block alignment option. - - TextHighlight::HighlightInfo newHighlightInfo; - //newHighlightInfo.mQuadList.clear(); // clear last quad information. - - if ( !mTextViewCharacterPositioning.IsTextEmpty() && !textLayoutInfo.mCharacterLogicalToVisualMap.empty() ) - { - // Get vector of flags representing characters that are selected (true) vs unselected (false). - std::vector selectedVisualText; - GetVisualTextSelection(selectedVisualText, handlePositionStart, handlePositionEnd, textLayoutInfo ); - std::vector::iterator selectedIt(selectedVisualText.begin()); - std::vector::iterator selectedEndIt(selectedVisualText.end()); - - SelectionState selectionState = SelectionNone; ///< Current selection status of cursor over entire text. - float rowLeft = 0.0f; - float rowRight = 0.0f; - // Keep track of the TextView's min/max extents. Should be able to query this from TextView. - float maxRowLeft = std::numeric_limits::max(); - float maxRowRight = 0.0f; - - Toolkit::TextView::CharacterLayoutInfoContainer::iterator it = textLayoutInfo.mCharacterLayoutInfoTable.begin(); - Toolkit::TextView::CharacterLayoutInfoContainer::iterator end = textLayoutInfo.mCharacterLayoutInfoTable.end(); - - Toolkit::TextView::CharacterLayoutInfoContainer::iterator lastIt = it; - - // Scan through entire text. - while(it != end) - { - // selectionState: None when not in selection, Started when in selection, and Ended when reached end of selection. - - Toolkit::TextView::CharacterLayoutInfo& charInfo(*it); - bool charSelected( false ); - if( selectedIt != selectedEndIt ) - { - charSelected = *selectedIt++; - } - - if(selectionState == SelectionNone) - { - if(charSelected) - { - selectionState = SelectionStarted; - rowLeft = charInfo.mPosition.x - textLayoutInfo.mScrollOffset.x; - rowRight = rowLeft + charInfo.mSize.width; - } - } - else if(selectionState == SelectionStarted) - { - // break selection on: - // 1. new line causing selection break. (\n or wordwrap) - // 2. character not selected. - if(charInfo.mPosition.y - lastIt->mPosition.y > CHARACTER_THRESHOLD || - !charSelected) - { - // finished selection. - // TODO: TextView should have a table of visual rows, and each character a reference to the row - // that it resides on. That way this enumeration is not necessary. - Vector2 min, max; - if(lastIt->mIsNewParagraphChar) - { - // If the last character is a new line, then to get the row rect, we need to scan from the character before the new line. - lastIt = std::max( textLayoutInfo.mCharacterLayoutInfoTable.begin(), lastIt - 1 ); - } - const Size rowSize( mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( lastIt - textLayoutInfo.mCharacterLayoutInfoTable.begin(), min, max ) ); - maxRowLeft = std::min(maxRowLeft, min.x); - maxRowRight = std::max(maxRowRight, max.x); - float rowBottom = lastIt->mPosition.y - textLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - - // Still selected, and block-align mode then set rowRight to max, so it can be clamped afterwards - if(charSelected) - { - rowRight = std::numeric_limits::max(); - } - newHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - - selectionState = SelectionNone; - - // Still selected? start a new selection - if( charSelected ) - { - // if block-align mode then set rowLeft to min, so it can be clamped afterwards - rowLeft = 0.0f; - rowRight = ( charInfo.mPosition.x - textLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width; - selectionState = SelectionStarted; - } - } - else - { - // build up highlight(s) with this selection data. - rowLeft = std::min( charInfo.mPosition.x - textLayoutInfo.mScrollOffset.x, rowLeft ); - rowRight = std::max( ( charInfo.mPosition.x - textLayoutInfo.mScrollOffset.x ) + charInfo.mSize.width, rowRight ); - } - } - - lastIt = it++; - } - - // If reached end, and still on selection, then close selection. - if(it == end) - { - if(selectionState == SelectionStarted) - { - // finished selection. - Vector2 min, max; - if(lastIt != end && lastIt->mIsNewParagraphChar) - { - lastIt = std::max( textLayoutInfo.mCharacterLayoutInfoTable.begin(), lastIt - 1 ); - } - if( lastIt != end ) - { - const Size rowSize( mTextViewCharacterPositioning.GetRowRectFromCharacterPosition( lastIt - textLayoutInfo.mCharacterLayoutInfoTable.begin(), min, max ) ); - maxRowLeft = std::min(maxRowLeft, min.x); - maxRowRight = std::max(maxRowRight, max.x); - float rowBottom = lastIt->mPosition.y - textLayoutInfo.mScrollOffset.y; - float rowTop = rowBottom - rowSize.height; - newHighlightInfo.AddQuad( rowLeft, rowTop, rowRight, rowBottom ); - } - } - } - - // Get the top left and bottom right corners. - const Toolkit::TextView::CharacterLayoutInfo& firstCharacter( *textLayoutInfo.mCharacterLayoutInfoTable.begin() ); - const Vector2 topLeft( maxRowLeft, firstCharacter.mPosition.y - firstCharacter.mSize.height ); - const Vector2 bottomRight( topLeft.x + textLayoutInfo.mTextSize.width, topLeft.y + textLayoutInfo.mTextSize.height ); - - // Clamp quads so they appear to clip to borders of the whole text. - newHighlightInfo.Clamp2D( topLeft, bottomRight ); - - // For block-align align Further Clamp quads to max left and right extents - // BlockAlign: Will adjust highlight to block: - // i.e. - // H[ello] (top row right = max of all rows right) - // [--this-] (middle rows' left = min of all rows left, middle rows' right = max of all rows right) - // [is some] (middle rows' left = min of all rows left, middle rows' right = max of all rows right) - // [text] (bottom row left = min of all rows left) - // (common in SMS messaging selection) - // - // As opposed to the default which is tight text highlighting. - // H[ello] - // [this] - // [is some] - // [text] - // (common in regular text editors/web browser selection) - newHighlightInfo.Clamp2D( Vector2(maxRowLeft, topLeft.y), Vector2(maxRowRight, bottomRight.y ) ); - - } - - return newHighlightInfo; -} - -void TextHighlight::UpdateHighlight( TextHighlight::HighlightInfo& newHighlightInfo ) -{ -} - -void TextHighlight::CreateHighLightMesh() -{ -} - -void TextHighlight::HighlightInfo::AddQuad( float x1, float y1, float x2, float y2 ) -{ - QuadCoordinates quad(x1, y1, x2, y2); - mQuadList.push_back( quad ); -} - -void TextHighlight::HighlightInfo::Clamp2D(const Vector2& min, const Vector2& max) -{ - for(std::size_t i = 0;i < mQuadList.size(); i++) - { - QuadCoordinates& quad = mQuadList[i]; - - quad.min.Clamp(min, max); - quad.max.Clamp(min, max); - } -} - -} // Internal - -} // namespace Toolkit - -} // namespace Dali - diff --git a/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h b/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h deleted file mode 100644 index 8fdbcd9..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-text-highlight-impl.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * @brief TextHighlight is a decoration which highlights selected text. - * - * The class creates a highlight mesh used to show selected text between handles. - * Not responsible for positioning. - */ -class TextHighlight -{ - /** - * structure to hold coordinates of each quad, which will make up the mesh. - */ - struct QuadCoordinates - { - /** - * Default constructor - */ - QuadCoordinates() - { - } - - /** - * Constructor - * @param[in] x1 left co-ordinate - * @param[in] y1 top co-ordinate - * @param[in] x2 right co-ordinate - * @param[in] y2 bottom co-ordinate - */ - QuadCoordinates(float x1, float y1, float x2, float y2) - : min(x1, y1), - max(x2, y2) - { - } - - Vector2 min; ///< top-left (minimum) position of quad - Vector2 max; ///< bottom-right (maximum) position of quad - }; - - typedef std::vector QuadContainer; - -public: - - /** - * structure for information required to build the highlight mesh - */ - struct HighlightInfo - { - /** - * Adds a Quad (2D rectangular sub-selection) - * @param[in] x1 left co-ordinate - * @param[in] y1 top co-ordinate - * @param[in] x2 right co-ordinate - * @param[in] y2 bottom co-ordinate - */ - void AddQuad( float x1, float y1, float x2, float y2 ); - - /** - * Clamps all quads to fit within a min -> max 2D boundary. - */ - void Clamp2D(const Vector2& min, const Vector2& max); - - QuadContainer mQuadList; ///< List of quads (sub-selections that form to create complete selection) - }; - - /** - * Constructor - * @param[in] textViewCharacterPositioning TextViewCharacterPositioning to be used for positioning information. - */ - TextHighlight( TextViewCharacterPositioning& textViewCharacterPositioning ); - - /** - * Destructor - */ - ~TextHighlight(); - - /** - * Gets the table of the visual text positions which has a flag - * for each Character. The flag is either true (character selected) - * or false (character de-selected) - * @note startSelection can be greater or less than endSelection - * - * @param[in,out] selectedVisualText The vector to be resized and populated with the selected flags - * @param[in] startSelection The start selection point for the text - * @param[in] endSelection The end selection point for the text - * @param[in] endSelection The end selection point for the text - * @param[in] textLayoutInfo TextView character layout information - */ - void GetVisualTextSelection(std::vector& selectedVisualText, std::size_t startSelection, std::size_t endSelection, - Toolkit::TextView::TextLayoutInfo& textLayoutInfo); - - /** - * Iterates between selection handles and computes the info required to build the highlight mesh - * @param[in] handlePositionStart starting handle position - * @param[in] handlePositionEnd ending handle position - * @return textHighlight target TextHighlight - */ - TextHighlight::HighlightInfo CalculateHighlightInfo( std::size_t handlePositionStart, std::size_t handlePositionEnd, Toolkit::TextView::TextLayoutInfo& textLayoutInfo ); - - /** - * Calculates new Mesh data so highlight moves with selection handles. - * @param[in] newHighlightInfo HighlightInfo calculated by CalculateHighlightInfo - */ - void UpdateHighlight( TextHighlight::HighlightInfo& newHighlightInfo ); - - /** - * Creates the Mesh data needed by the Mesh Actor - */ - void CreateHighLightMesh(); - -private: - - /** - * @brief Copy Constructor - * @param[in] textHight - * Undefined/Hidden. - */ - TextHighlight(const TextHighlight& textHight ); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - TextHighlight& operator=(const TextHighlight& rhs); - -private: - - TextViewCharacterPositioning& mTextViewCharacterPositioning; - - HighlightInfo mNewHighlightInfo; ///< Geometry info to create highlight. - -}; - - -} // namespace Internal - - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_HIGHLIGHT_H__ diff --git a/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h b/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h deleted file mode 100644 index 235923a..0000000 --- a/dali-toolkit/internal/controls/text-input/text-input-text-style-impl.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__ - -/* - * Copyright (c) 2014 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 -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class TextInputTextStyle; - -typedef IntrusivePtr TextInputTextStylePtr; - -/** - * Stores the Input Text Style and provides functions to retrieve and manipulate it. - */ - -class TextInputTextStyle : ConnectionTracker -{ - -public: - - /** - * @brief Constructor - */ - TextInputTextStyle(){}; - - /** - * @brief Destructor - */ - ~TextInputTextStyle(){}; - - /** - * @brief Returns the current Input Style, this is the style that newly inputed text will inherit. - * @return TextStyle object representing new style. - */ - TextStyle GetInputStyle() const{return mInputStyle;}; - - /** - * @brief Sets the Input style so newly inputed text will inherit this. - * @param[in] newStyle the style to now use for Input - * @return returns true if style changed. False if new style is the same as current setting. - */ - bool SetInputStyle( const TextStyle newStyle, const TextStyle::Mask mask = TextStyle::ALL ){return false;}; - - /** - * @brief Gets the Current Font used for newly inputed text - * @return the Font currently set for new text - */ - Dali::Font GetInputFont() const{return Dali::Font();}; - - /** - * Signals - */ - - /* Input style changed signal.*/ - typedef Signal< void( const TextStyle& style ) > StyleChangedSignalType; - - /** - * @brief Signal emitted when style changes. - * @return The signal to connect to - */ - StyleChangedSignalType& StyleChangedSignal(); - -private: - - /** - * @brief Copy Constructor - * @param[in] textStyle - * Undefined/Hidden. - */ - TextInputTextStyle(const TextInputTextStyle& textStyle ); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined/Hidden. - */ - TextInputTextStyle& operator=(const TextInputTextStyle& rhs); - -private: - - TextStyle mInputStyle; // Stores the current input style. - StyleChangedSignalType mStyleChangedSignal; // Signal emitted when style changes. -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXT_STYLE_H__ - - diff --git a/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h b/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h deleted file mode 100644 index 3f754bf..0000000 --- a/dali-toolkit/internal/controls/text-input/textview-character-positions-impl.h +++ /dev/null @@ -1,338 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -class TextInputTextStyle; - -/** - * Class which contains functions related to the TextView. - * Functions which are needed by various parts of the TextInput to determine the position of characters. - * Functions to Set the TextView so text justification, alignment and wrapping behaviour in the desired manner for text input. - * The functionality of this class may be divided in future. - */ -class TextViewCharacterPositioning -{ - -public: - - /** - * @brief Constructor - * - * @param[in] displayedTextView TextView to be used with this class. - * @param[in] textStyle TextInputTextStyle to be used - */ - TextViewCharacterPositioning( Toolkit::TextView displayedTextView, TextInputTextStyle& textStyle ):mTextStyle( textStyle ){}; - - /** - * Destructor - */ - ~TextViewCharacterPositioning(){}; - - /** - * @brief Creates the TextView to be used within this class. - */ - void CreateTextView(){}; - - /* - * @brief Get a handle to the current text view object - * If one does not exist then it's create. - * @return TextView - */ - Toolkit::TextView GetTextView() const{return Toolkit::TextView();}; - - /** - * @brief Get the TextLayoutInfo from the TextView so know the updated positions of characters. - */ - void UpdateTextLayoutInfo(){}; - - - /** - * @brief Get the TextLayoutInfo structure for the TextView - * @return the TextLayoutInfo structure - */ - const Toolkit::TextView::TextLayoutInfo& GetLayoutInfo() const{return mTextLayoutInfo;}; - - - /** - * @brief Get the number of characters visually represented in the text - * @return the number of characters - */ - std::size_t GetNumberOfCharactersInText() const{return 0;}; - - /** - * @brief Check if any text exists in TextView's character layout table - * @return bool true if empty - */ - bool IsTextEmpty() const{return false;}; - - /** - * @brief Get the height of the line at the given cursor position - * @param[in] position - * @return float the height of the line - */ - float GetLineHeight( std::size_t position ) const{return 0.0f;}; - - /** - * @brief Sets if the inputed text can exceed the text-input boundary. - * By default is enabled. - * @param[in] enable Whether the inputed text can exceed its boundary. - */ - void SetTextExceedEnabled( bool enable ) {}; - - /** - * @brief Retrieves whether inputed text can exceed the text-input boundary. - * @return \e true if text inputed can exceed the boundary, otherwise \e false. - */ - bool IsTextExceedEnabled() const{ return false;}; - - /** - * @brief From the given x and y vector the closest character position is returned - * @param[in] source the x and y position - * @return the position in the string of the character closest to the source. - */ - std::size_t ReturnClosestIndex( const Vector2& source ){return 0;}; - - /** - * @brief If no text exists then this function uses the text alignment to position cursor. - * @param[in] cursorPosition - */ - void GetActualPositionFromCharacterPositionWhenNoText( Vector3& cursorPosition ) const{}; - - /** - * @brief Function to position cursor when a word is wrapped to another line - * @param[in] characterPosition that actual position is required for - * @return the actual position of the cursor. - */ - Vector3 PositionCursorAfterWordWrap( std::size_t characterPosition ) const{return Vector3::ZERO;}; - - /** - * @brief Returns the x-position of the current line justification - * (relative to left of text-view container) - * @return x position for line justification - */ - float GetLineJustificationPosition() const{return 0.0f;}; - - /** - * @brief Retrieve the dimensions (and min-max) of this row of text that the character resides on. - * @param[in] characterPosition the position in the 'string' of characters. - * @param[out] min the top-left position of the rectangle representing this row - * @param[out] max the bottom-right position of the rectangle representing this row - * @return The size of the rectangle representing this row (max - min) - */ - Size GetRowRectFromCharacterPosition(std::size_t characterPosition, Vector2& min, Vector2& max) const{return Vector2::ZERO;}; - - /** - * @brief Retrieve the character position of the first character on the row of text - * that this character resides on. - * @param[in] logicalPosition the position in the 'string' of characters. - * @return logical character position of start of row. - */ - std::size_t GetRowStartFromCharacterPosition(std::size_t logicalPosition) const{return 0;}; - - /** - * @brief Gets the visual position of a logical position. - * @note This is preferred over directly accessing the Map, as it resolves visual - * positions outside of the character map range. - * @param[in] logicalPosition The logical position - * @return Visual position is returned. - */ - std::size_t GetVisualPosition(std::size_t logicalPosition) const{return 0;}; - - /** - * @brief Return a vector which is the actual position for the given character position - * The character position is where a cursor would be position for that character. - * @param[in] characterPosition the logical (input) position in the 'string' of characters. - * - * @return Vector3 the actual x,y,z position - */ - Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition ) const{return Vector3::ZERO;}; - - /** - * @brief Return a vector which is the actual position for the given character position - * The character position is where a cursor would be positioned for that character to be inserted. - * An additional alternatePosition is also set in circumstances where the possible writing - * of characters would be in the opposite direction. - * e.g. "HelloشقشلاهؤEnglish" - * | | - * * + - * [*] - Primary actual position for cursor i.e. continuing writing LTR (English) - * [+] - Alternate actual position for cursor i.e. writing RTL (Arabic) - * - * @param[in] characterPosition the logical (input) position in the 'string' of characters. - * @param[out] directionRTL Whether the actual x,y,z position is after LTR (false) or RTL (true) text. - * @param[out] alternatePosition the actual x,y,z position of the cursor if user types - * in alternate direction to current flow of text. - * @param[out] alternatePositionValid whether this alternate position is valid. - * @return Vector3 the actual x,y,z position - */ - Vector3 GetActualPositionFromCharacterPosition(std::size_t characterPosition, bool& directionRTL, Vector3& alternatePosition, bool& alternatePositionValid ) const{return Vector3::ZERO;}; - - /** - * @brief Get the currently displayed text. - * @return The currently displayed text. - */ - std::string GetText() const{return std::string();}; - - /** - * @brief Get the text currently being displayed together with mark-up tags. - * @return string, the currently displayed string with mark-up. - */ - std::string GetMarkupText() const{return std::string();}; - - /** - * @brief Sets whether markup processing should be carried out. - * - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ){}; - - /** - * @brief Returns whether markup processing is enabled or not - * - * @return true is markup processing is enabled - */ - bool IsMarkupProcessingEnabled() const{ return false;}; - - // Styled Text - - /** - * @brief Check if styled text is empty - * @return bool returns true if styled text is empty - */ - bool IsStyledTextEmpty() const{ return false;}; - - /** - * @brief The size of the style text - * @return std::size_t returns number of characters in styled text - */ - std::size_t StyledTextSize() const{return 0;}; - - /** - * @brief Get the styled text array - * @return reference to MarkupProcessor::StyledTextArray - */ - MarkupProcessor::StyledTextArray& GetStyledTextArray(){return mStyledText;}; - - /** - * @brief Get the style for the character at the given position - * @param[in] position of character style is required for - * @return a copy of the style structure for the character at the given position - */ - TextStyle GetStyleAt( std::size_t position ) const{return TextStyle();}; - -/** - * @briefApplies the given style to all text, selected or not selected. - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @param[in] style style to apply - * @param[in] mask mask style should be applied to - * @param[in] begin start position of range to apply style - * @param[in] end end position of range to apply style - */ - void ApplyStyleToRange( const TextStyle& style, const TextStyle::Mask mask, const std::size_t begin, const std::size_t end ){}; - - // Snapshot - /** - * @copydoc TextView::SetSnapshotModeEnabled() - */ - void SetSnapshotModeEnabled( bool enable ){}; - - /** - * @copydoc TextView::IsSnapshotModeEnabled() - */ - bool IsSnapshotModeEnabled() const{ return false;}; - - // Scrolling - /** - * @copydoc TextView::SetScrollEnabled() - */ - void SetScrollEnabled( bool enable ){}; - - /** - * @copydoc TextView::SetScrollPosition() - */ - void SetScrollPosition( const Vector2& position ){}; - - /** - * @copydoc TextView::IsScrollEnabled() - */ - bool IsScrollEnabled() const{ return false;}; - - /** - * @copydoc TextView::GetScrollPosition() - */ - Vector2 GetScrollPosition() const{return Vector2::ZERO;}; - - /** - * @copydoc TextView::GetScrollPosition() - */ - bool IsScrollPositionTrimmed() const{ return false;}; - -private: - - /** - * @brief Copy Constructor - * @param[in] characterPositioning - * Undefined. - */ - TextViewCharacterPositioning(const TextViewCharacterPositioning& characterPositioning ); - - /** - * @Assignment Constructor - * @param[in] rhs - * Undefined. - */ - TextViewCharacterPositioning& operator=(const TextViewCharacterPositioning& rhs); - -private: - - Toolkit::TextView mDisplayedTextView; // A text view object used to display the text. - TextInputTextStyle& mTextStyle; // Holds the style object related to input style - - MarkupProcessor::StyledTextArray mStyledText; // String currently displayed by TextView with style info. - - Toolkit::TextView::TextLayoutInfo mTextLayoutInfo; // It contains a table layout info per character sorted by the character's visual index (retrieved from TextView), - // a reorder map that stores each character's visual (output) index according to its logical (input) index, - // a reorder map that stores each character's logical (input) index according to its visual (output) index - - bool mExceedEnabled:1; // flag set by user to determine if text can exceed the control's size - bool mMarkUpEnabled:1; // If Markup is being passed with the text -}; - - -} // namespace Internal - - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_INPUT_TEXTVIEW_CHARACTER_POSITIONS_H__ diff --git a/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp b/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp deleted file mode 100644 index 54761fb..0000000 --- a/dali-toolkit/internal/controls/text-view/relayout-utilities.cpp +++ /dev/null @@ -1,2565 +0,0 @@ -/* - * Copyright (c) 2014 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/license/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 - -// EXTERNAL INCLUDES -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewRelayout -{ - -const float MINIMUM_FADE_BOUNDARY = 0.05f; // When the fade boundary is the same as the text-view boundary, this constant reduces it in order to avoid a zero division. - -RelayoutParameters::RelayoutParameters() -: mPositionOffset(), - mParagraphSize(), - mWordSize(), - mCharacterSize(), - mIndices(), - mCharacterGlobalIndex( 0u ), - mIsFirstCharacter( false ), - mIsFirstCharacterOfWord( false ), - mIsNewLine( false ), - mIsNewParagraphCharacter( false ), - mIsWhiteSpace( false ), - mIsVisible( false ) -{ -} - -RelayoutParameters::~RelayoutParameters() -{ -} - -FadeParameters::FadeParameters() -: mRightFadeBoundary( 0.f ), - mRightFadeThreshold( 0.f ), - mRightFadeBoundaryOffset( 0.f ), - mRightFadeThresholdOffset( 0.f ), - mRightAlphaCoeficients(), - mLeftFadeBoundary( 0.f ), - mLeftFadeThreshold( 0.f ), - mLeftFadeBoundaryOffset( 0.f ), - mLeftFadeThresholdOffset( 0.f ), - mLeftAlphaCoeficients(), - mTopFadeBoundary( 0.f ), - mTopFadeThreshold( 0.f ), - mTopFadeBoundaryOffset( 0.f ), - mTopFadeThresholdOffset( 0.f ), - mTopAlphaCoeficients(), - mBottomFadeBoundary( 0.f ), - mBottomFadeThreshold( 0.f ), - mBottomFadeBoundaryOffset( 0.f ), - mBottomFadeThresholdOffset( 0.f ), - mBottomAlphaCoeficients(), - mIsPartiallyVisible( false ) -{ -} - -FadeParameters::~FadeParameters() -{ -} - -EllipsizeParameters::EllipsizeParameters() -: mPosition(), - mLineDescender( 0.f ), - mLineWidth( 0.f ), - mEllipsizeBoundary(), - mFirstIndex( 0u ), - mLastIndex( 0u ), - mEllipsizeLine( false ), - mIsLineWidthFullyVisible( false ), - mIsLineHeightFullyVisible( false ), - mIsNextLineFullyVisibleHeight( false ), - mCreateEllipsizedTextActors( false ), - mLineFits( false ), - mWordFits( false ) -{ -} - -EllipsizeParameters::~EllipsizeParameters() -{ -} - -UnderlineInfo::UnderlineInfo() -: mMaxHeight( 0.f ), - mMaxThickness( 0.f ), - mPosition( 0.f ) -{ -} - -UnderlineInfo::~UnderlineInfo() -{ -} - -TextUnderlineStatus::TextUnderlineStatus() -: mUnderlineInfo(), - mCharacterGlobalIndex( 0u ), - mLineGlobalIndex( 0u ), - mCurrentUnderlineStatus( false ) -{ -} - -TextUnderlineStatus::~TextUnderlineStatus() -{ -} - -LineLayoutInfo::LineLayoutInfo() -: mLineLength( 0.f ), - mMaxCharHeight( 0.f ), - mMaxAscender( 0.f ) -{ -} - -LineLayoutInfo::~LineLayoutInfo() -{ -} - -/** - * Whether the given text-actor exceeds the left or the right boundary of the text-view. - * - * @param[in] position The position of the text-actor. - * @param[in] size The size of the text-actor. - * @param[in] parantSize The size of the text-view. - * - * @return \e true if the text-actor exceeds the left or the right boundary of the text-view. - */ -bool IsExceedingWidth( const Vector3& position, const Size& size, const Size& parentSize ) -{ - return ( ( position.x < 0.f ) || - ( position.x + size.width > parentSize.width ) ); -} - -/** - * Whether the given text-actor exceeds the top or the bottom boundary of the text-view. - * - * @param[in] position The position of the text-actor. - * @param[in] size The size of the text-actor. - * @param[in] parantSize The size of the text-view. - * - * @return \e true if the text-actor exceeds the top or the bottom boundary of the text-view. - */ -bool IsExceedingHeight( const Vector3& position, const Size& size, const Size& parentSize ) -{ - return ( ( position.y > parentSize.height ) || - ( position.y < size.height ) ); -} - -/** - * Calculates the line length adding the new word or character width. - * - * It also returns the length of white spaces if they are at the end of the line. - * - * @param[in] isWhiteSpace Whether the word is a white space. - * @param[in] width The width of the character or word. - * @param[in] parentWidth The parent width. - * @param[out] found Whether the sum of the new character or word is exceding the parent's width. - * @param[out] lineLength The length of the portion of line which doesn't exceed the parant's width - * @param[out] endWhiteSpaceLength The length of white spaces which are at the end of the line. - */ -void CalculateLineLength( bool isWhiteSpace, float width, float parentWidth, bool& found, float& lineLength, float& endWhiteSpaceLength ) -{ - if( lineLength + width > parentWidth ) - { - found = true; - lineLength -= endWhiteSpaceLength; - } - else - { - lineLength += width; - - if( isWhiteSpace ) - { - endWhiteSpaceLength += width; - } - else - { - endWhiteSpaceLength = 0.f; - } - } -} - -struct CurrentTextActorInfo -{ - TextActor textActor; - Text text; - Vector3 position; - Size size; - Vector4 color; - TextViewProcessor::CharacterLayoutInfo* characterLayout; -}; - -void SetVisualParameters( CurrentTextActorInfo& currentTextActorInfo, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - const float lineHeight ) -{ - currentTextActorInfo.textActor.SetTextColor( currentTextActorInfo.color ); - if( ( NULL != currentTextActorInfo.characterLayout ) && - ( NULL != currentTextActorInfo.characterLayout->mGradientInfo ) ) - { - currentTextActorInfo.textActor.SetGradientColor( currentTextActorInfo.characterLayout->mGradientInfo->mGradientColor ); - currentTextActorInfo.textActor.SetGradientStartPoint( currentTextActorInfo.characterLayout->mGradientInfo->mStartPoint ); - currentTextActorInfo.textActor.SetGradientEndPoint( currentTextActorInfo.characterLayout->mGradientInfo->mEndPoint ); - } - - // The italics offset is used in the offscreen rendering. When text is in italics, it may exceed the text-view's boundary - // due to the trick used to implement it. - const Radian& italicsAngle = currentTextActorInfo.textActor.GetItalicsAngle(); - const float italicsOffset = lineHeight * std::tan( italicsAngle ); - relayoutData.mTextLayoutInfo.mMaxItalicsOffset = std::max( relayoutData.mTextLayoutInfo.mMaxItalicsOffset, italicsOffset ); - - // Sets the sort modifier value. - // currentTextActorInfo.textActor.SetSortModifier( visualParameters.mSortModifier ); - - // Enables or disables the blending. - // currentTextActorInfo.textActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF ); -} - -void CalculateLineLayout( float parentWidth, - const TextViewProcessor::TextInfoIndices& indices, - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo, - HorizontalWrapType splitPolicy, - float shrinkFactor, - LineLayoutInfo& subLineInfo ) -{ - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - - float endWhiteSpaceLength = 0.f; - - std::size_t characterIndex = indices.mCharacterIndex; - float lineOffset = 0.f; - bool found = false; - bool isFirstCharacter = true; - for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex, - wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - ( wordIt != wordEndIt ) && !found; - ++wordIt ) - { - const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt ); - - const float shrunkWordWidth = wordLayoutInfo.mSize.width * shrinkFactor; - const bool isWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType; - - bool splitByCharacter = false; - - switch( splitPolicy ) - { - case WrapByCharacter: - { - splitByCharacter = true; - break; - } - case WrapByWord: - case WrapByParagraphCharacter: // Fall through - { - splitByCharacter = false; - break; - } - case WrapByWordAndSplit: - { - splitByCharacter = ( shrunkWordWidth > parentWidth ); - break; - } - case WrapByParagraphCharacterAndSplit: - { - if( ( 0u != characterIndex ) || - ( ( 0u == characterIndex ) && ( lineOffset + shrunkWordWidth > parentWidth ) ) ) - { - splitByCharacter = true; - } - else - { - lineOffset += shrunkWordWidth; - splitByCharacter = false; - } - } - } - - if( splitByCharacter ) - { - for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + characterIndex, - charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - ( charIt != charEndIt ) && !found; - ++charIt ) - { - const TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt ); - CalculateLineLength( isWhiteSpace, characterLayoutInfo.mSize.width * shrinkFactor, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength ); - if( !found || isFirstCharacter ) - { - subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, characterLayoutInfo.mSize.height ); - subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, characterLayoutInfo.mAscender ); - } - - // All characters for word 'wordIndex' have been processed. - // Next word need to process all characters, so the characterIndex is reset to 0. - characterIndex = 0u; - isFirstCharacter = false; - } - - lineOffset += subLineInfo.mLineLength; - } - else - { - CalculateLineLength( isWhiteSpace, shrunkWordWidth, parentWidth, found, subLineInfo.mLineLength, endWhiteSpaceLength ); - if( !found || isFirstCharacter ) - { - subLineInfo.mMaxCharHeight = std::max( subLineInfo.mMaxCharHeight, wordLayoutInfo.mSize.height ); - subLineInfo.mMaxAscender = std::max( subLineInfo.mMaxAscender, wordLayoutInfo.mAscender ); - } - isFirstCharacter = false; - } - } - - subLineInfo.mMaxCharHeight *= shrinkFactor; - subLineInfo.mMaxAscender *= shrinkFactor; -} - - -/** - * Sets a character of a line of a bidirectional paragraph in the new position. - * - * @param[in] wordsLayoutInfo Layout info of all the words of the paragraph. - * @param[in] index Index within the paragraph to the character to be set in the new position. - * @param[in,out] character Reference to the character in the new position. - */ -void SetCharacter( const TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo, - std::size_t index, - TextViewProcessor::CharacterLayoutInfo& character ) -{ - // Traverse all the characters of the paragraph till the one pointed by index is found. - std::size_t traversedCharacters = 0u; - for( TextViewProcessor::WordLayoutInfoContainer::const_iterator wordIt = wordsLayoutInfo.begin(), - wordEndIt = wordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - const TextViewProcessor::WordLayoutInfo& word( *wordIt ); - - const std::size_t numberOfCharacters = word.mCharactersLayoutInfo.size(); - if( index < traversedCharacters + numberOfCharacters ) - { - character = *( word.mCharactersLayoutInfo.begin() + ( index - traversedCharacters ) ); - return; - } - traversedCharacters += numberOfCharacters; - } -} - -/** - * Reorders the layout info of each line of the paragraph. - * - * Uses the visual to logical conversion table to order the text, styles and character's layout (metrics). - * - * @param[in] characterGlobalIndex Index within the whole text of the first character of the paragraph. - * @param[in,out] rtlParagraph Layout info for the paragraph with rtl text. - * @param[in,out] relayoutData The text-view's data structures. - */ -void ReorderLayout( std::size_t characterGlobalIndex, - TextViewProcessor::ParagraphLayoutInfo& paragraph, - TextView::RelayoutData& relayoutData ) -{ - // Clear any previous right to left layout. - if( NULL != paragraph.mRightToLeftLayout ) - { - paragraph.mRightToLeftLayout->Clear(); - paragraph.mRightToLeftLayout->mPreviousLayoutCleared = true; - } - else - { - // Create a new right to left layout if there isn't any. - paragraph.mRightToLeftLayout = new TextViewProcessor::RightToLeftParagraphLayout(); - } - - // Reorder Text and Styles. - - // Reserve space for the styles. - paragraph.mRightToLeftLayout->mTextStyles.Reserve( paragraph.mTextStyles.Count() ); - - // Traverses all the bidirectional info per line. - for( Vector::ConstIterator it = paragraph.mBidirectionalLinesInfo.Begin(), endIt = paragraph.mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - TextProcessor::BidirectionalLineInfo* info( *it ); - - const std::size_t characterParagraphIndex = info->mCharacterParagraphIndex; - const Vector& visualToLogicalMap = info->mVisualToLogicalMap; - - // The text can be appended as it's already reordered. - paragraph.mRightToLeftLayout->mText.Append( info->mText ); - - // The visual to logical map needs to be used to reorder the styles. - for( std::size_t index = 0u, size = visualToLogicalMap.Count(); index < size; ++index ) - { - paragraph.mRightToLeftLayout->mTextStyles.PushBack( *( paragraph.mTextStyles.Begin() + ( characterParagraphIndex + *( visualToLogicalMap.Begin() + index ) ) ) ); - } - } - - // Reorder Layout Info. - - // Reserve space for the new word layout. - paragraph.mRightToLeftLayout->mWordsLayoutInfo.reserve( paragraph.mWordsLayoutInfo.size() ); - - // Traverses all the bidirectional info per line. - for( Vector::ConstIterator it = paragraph.mBidirectionalLinesInfo.Begin(), endIt = paragraph.mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - TextProcessor::BidirectionalLineInfo* info( *it ); - - // Reserve space for all characters. - TextViewProcessor::CharacterLayoutInfoContainer characters; - characters.resize( info->mNumberOfCharacters ); - - // Uses the visual to logical map to set every character in its new position. - for( std::size_t index = 0u; index < info->mNumberOfCharacters; ++index ) - { - SetCharacter( paragraph.mWordsLayoutInfo, - info->mCharacterParagraphIndex + info->mVisualToLogicalMap[index], - *( characters.begin() + index ) ); - } - - // Sets the new 'x' position for each character. - // Updates the text-view's layout info table with the new position of the character. - float xPosition = 0.f; - std::size_t index = 0u; - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator it = characters.begin(), endIt = characters.end(); it != endIt; ++it, ++index ) - { - TextViewProcessor::CharacterLayoutInfo& character( *it ); - - // Set the 'x' position. - character.mPosition.x = xPosition; - - // Update layout info table. - relayoutData.mCharacterLayoutInfoTable[characterGlobalIndex + info->mVisualToLogicalMap[index]].mPosition = character.mPosition; - - // Update the position for the next character. - xPosition += character.mSize.width; - } - - // Split the reordered text in words. - std::size_t previousPosition = 0u; - Vector positions; - TextProcessor::SplitInWords( info->mText, positions ); - - // Whether last character is a word or a paragraph separator. - const std::size_t lastCharacterIndex = info->mText.GetLength() - 1u; - const bool isLastCharacterParagraphSeparator = info->mText.IsNewLine( lastCharacterIndex ); - const bool isLastCharacterWordSeparator = info->mText.IsWhiteSpace( lastCharacterIndex ); - - // Sets the characters into the words they belong to. - for( Vector::ConstIterator it = positions.Begin(), endIt = positions.End(); it != endIt; ++it ) - { - const std::size_t position = *it; - - TextViewProcessor::WordLayoutInfo word; - word.mCharactersLayoutInfo.insert( word.mCharactersLayoutInfo.end(), - characters.begin() + previousPosition, - characters.begin() + position ); - - if( !word.mCharactersLayoutInfo.empty() ) - { - // Updates the layout of the word. - TextViewProcessor::UpdateLayoutInfo( word ); - - paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word ); - } - - // white space or new paragraph. - TextViewProcessor::WordLayoutInfo space; - - space.mCharactersLayoutInfo.insert( space.mCharactersLayoutInfo.end(), - characters.begin() + position, - characters.begin() + position + 1u ); - - space.mType = TextViewProcessor::WordSeparator; - - TextViewProcessor::UpdateLayoutInfo( space ); - - paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( space ); - - previousPosition = position + 1u; - } - - // The last word. - if( previousPosition < paragraph.mRightToLeftLayout->mText.GetLength() ) - { - TextViewProcessor::WordLayoutInfo word; - word.mCharactersLayoutInfo.insert( word.mCharactersLayoutInfo.end(), - characters.begin() + previousPosition, - characters.end() ); - - if( isLastCharacterParagraphSeparator ) - { - word.mType = TextViewProcessor::ParagraphSeparator; - } - else if( isLastCharacterWordSeparator ) - { - word.mType = TextViewProcessor::WordSeparator; - } - TextViewProcessor::UpdateLayoutInfo( word ); - - paragraph.mRightToLeftLayout->mWordsLayoutInfo.push_back( word ); - } - } -} - -/** - * Creates the bidirectional info needed to reorder each line of the paragraph. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in,out] paragraph Layout info for the paragraph. - * @param[in] characterGlobalIndex Index to the character within the whole text. - * @param[in] lineLayoutInfoIndex Index to the table of lines. - */ -void CreateBidirectionalInfoForLines( TextView::RelayoutData& relayoutData, - TextViewProcessor::ParagraphLayoutInfo& paragraph, - std::size_t& characterGlobalIndex, - std::size_t& lineLayoutInfoIndex ) -{ - const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number or laid out lines. - bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last laid out line. - - // Clear previously created bidirectional info. - paragraph.ClearBidirectionalInfo(); - - // For each character, it sets the character's direction. - - // Initialize the paragraph direction. Used to set the direction of weak characters. - const bool isParagraphRightToLeft = paragraph.mBidirectionalParagraphInfo->IsRightToLeftParagraph(); - bool isPreviousRightToLeft = isParagraphRightToLeft; - - for( std::size_t index = 0u; index < paragraph.mNumberOfCharacters; ++index ) - { - // Get the character's layout information (the one is shared with text-input) - Toolkit::TextView::CharacterLayoutInfo& info = *( relayoutData.mCharacterLayoutInfoTable.begin() + ( characterGlobalIndex + index ) ); - - // Gets the character's direction. - const Character::CharacterDirection direction = paragraph.mText[index].GetCharacterDirection(); - if( Character::RightToLeft == direction ) - { - info.mIsRightToLeftCharacter = true; - } - else if( Character::Neutral == direction ) - { - // For neutral characters it check's the next and previous directions. - // If they are equals set that direction. If they are not, sets the paragraph direction. - // If there is no next, sets the previous direction. - - // Check next character's direction. - bool isNextRightToLeft = isPreviousRightToLeft; - if( index < paragraph.mNumberOfCharacters - 1u ) - { - const Character::CharacterDirection nextDirection = paragraph.mText[index + 1u].GetCharacterDirection(); - isNextRightToLeft = Character::RightToLeft == nextDirection; - } - - info.mIsRightToLeftCharacter = isPreviousRightToLeft == isNextRightToLeft ? isPreviousRightToLeft : isParagraphRightToLeft; - } - else - { - info.mIsRightToLeftCharacter = false; - } - - isPreviousRightToLeft = info.mIsRightToLeftCharacter; - } - - std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph). - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - TextViewProcessor::WordLayoutInfo& word( *wordIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt ) - { - TextProcessor::BidirectionalLineInfo* bidirectionalLineInfo = NULL; - - // Check if there is a new line. - const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ); - - if( newLine ) - { - // Point to the next line. - ++lineLayoutInfoIndex; - if( lineLayoutInfoIndex >= lineLayoutInfoSize ) - { - // Arrived at last line. - lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector. - } - - // Number of characters of the line. - const size_t numberOfCharacters = ( lineLayoutEnd ? relayoutData.mTextLayoutInfo.mNumberOfCharacters : relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ) - characterGlobalIndex; - - // There is right to left characters in this line. It needs to be reordered. - bidirectionalLineInfo = new TextProcessor::BidirectionalLineInfo(); - bidirectionalLineInfo->mCharacterParagraphIndex = characterParagraphIndex; - bidirectionalLineInfo->mNumberOfCharacters = numberOfCharacters; - - // Set all the Text's characters in the visual order and creates the mapping tables. - TextProcessor::ReorderLine( paragraph.mBidirectionalParagraphInfo, - bidirectionalLineInfo ); - - paragraph.mBidirectionalLinesInfo.PushBack( bidirectionalLineInfo ); - - for( std::size_t index = 0u; index < numberOfCharacters; ++index ) - { - relayoutData.mCharacterLogicalToVisualMap.push_back( characterGlobalIndex + bidirectionalLineInfo->mLogicalToVisualMap[index] ); - relayoutData.mCharacterVisualToLogicalMap.push_back( characterGlobalIndex + bidirectionalLineInfo->mVisualToLogicalMap[index] ); - } - } - - ++characterGlobalIndex; - ++characterParagraphIndex; - } // characters - } // words -} - -void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData ) -{ - // Reset conversion tables shared through public-api - relayoutData.mCharacterLogicalToVisualMap.clear(); - relayoutData.mCharacterVisualToLogicalMap.clear(); - - std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text). - std::size_t lineLayoutInfoIndex = 0u; // Index to the line info. - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - - if( NULL != paragraph.mBidirectionalParagraphInfo ) - { - // There is right to left text in this paragraph. - - // Stores the current global character index as is needed in both functions. - const std::size_t currentGlobalIndex = characterGlobalIndex; - - // Creates the bidirectional info needed to reorder each line of the paragraph. - CreateBidirectionalInfoForLines( relayoutData, - paragraph, - characterGlobalIndex, - lineLayoutInfoIndex ); - - // Reorder each line of the paragraph - ReorderLayout( currentGlobalIndex, paragraph, relayoutData ); - } - else - { - // Identity in case the paragraph has no right to left text. - for( std::size_t index = 0u; index < paragraph.mNumberOfCharacters; ++index ) - { - const std::size_t globalIndex = characterGlobalIndex + index; - relayoutData.mCharacterLogicalToVisualMap.push_back( globalIndex ); - relayoutData.mCharacterVisualToLogicalMap.push_back( globalIndex ); - } - characterGlobalIndex += paragraph.mNumberOfCharacters; - } - } // paragraphs -} - -float CalculateXoffset( Toolkit::Alignment::Type horizontalTextAlignment, float parentWidth, float wholeTextWidth ) -{ - float xOffset( 0.f ); - switch( horizontalTextAlignment ) - { - case Toolkit::Alignment::HorizontalLeft: - { - // nothing to do. - break; - } - case Toolkit::Alignment::HorizontalCenter: - { - xOffset = 0.5f * ( parentWidth - wholeTextWidth ); - break; - } - case Toolkit::Alignment::HorizontalRight: - { - xOffset = parentWidth - wholeTextWidth; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateXoffset: Wrong horizontal text alignment. Did you set a vertical one?" ); - } - } - - return xOffset; -} - -float CalculateYoffset( Toolkit::Alignment::Type verticalTextAlignment, float parentHeight, float wholeTextHeight ) -{ - float yOffset( 0.f ); - switch( verticalTextAlignment ) - { - case Toolkit::Alignment::VerticalTop: - { - // nothing to do. - break; - } - case Toolkit::Alignment::VerticalCenter: - { - yOffset = 0.5f * ( parentHeight - wholeTextHeight ); - break; - } - case Toolkit::Alignment::VerticalBottom: - { - yOffset = parentHeight - wholeTextHeight; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateXoffset: Wrong vertical text alignment. Did you set an horizontal one?" ); - } - } - - return yOffset; -} - -float CalculateJustificationOffset( Toolkit::TextView::LineJustification justification, float wholeTextWidth, float lineLength ) -{ - float offset = 0.f; - switch( justification ) - { - case Toolkit::TextView::Left: - { - offset = 0.f; - break; - } - case Toolkit::TextView::Center: - { - offset = 0.5f * ( wholeTextWidth - lineLength ); - break; - } - case Toolkit::TextView::Right: - { - offset = wholeTextWidth - lineLength; - break; - } - case Toolkit::TextView::Justified: - { - offset = 0.f; - break; - } - } - - return offset; -} - -bool IsVisible( const Vector3& position, const Size& size, const Size& parentSize, VisibilityTestType type ) -{ - bool visible = false; - - switch( type ) - { - case FULLY_VISIBLE: - { - // Whether the text-actor is fully inside the boundaries of the text-view. - visible = ( ( position.x >= 0.f ) && ( position.x + size.width <= parentSize.width ) && - ( position.y >= size.height ) && ( position.y <= parentSize.height ) ); - break; - } - case FULLY_VISIBLE_WIDTH: - { - // Whether the text-actor is between the left and right boundaries of the text-view. - visible = ( ( position.x >= 0.f ) && ( position.x + size.width <= parentSize.width ) ); - break; - } - case FULLY_VISIBLE_HEIGHT: - { - // Whether the text-actor is between the top and bottom boundaries of the text-view. - visible = ( ( position.y >= size.height ) && ( position.y <= parentSize.height ) ); - break; - } - case PARTIALLY_VISIBLE: - { - // Whether the text-actor is partially inside the boundaries of the text-view. - visible = ( ( position.x < parentSize.width ) && - ( position.x + size.width > 0.f ) && - ( position.y > 0.f ) && - ( position.y - size.height < parentSize.height ) ); - break; - } - case PARTIALLY_VISIBLE_WIDTH: - { - // Whether the text-actor is partially inside the area defined by the left and the right boundaries of the text-view. - // It may not be partially inside the text-view. - visible = ( ( position.x < parentSize.width ) && - ( position.x + size.width > 0.f ) ); - break; - } - case PARTIALLY_VISIBLE_HEIGHT: - { - // Whether the text-actor is partially inside the area defined by the top and the bottom boundaries of the text-view. - // It may not be partially inside the text-view. - visible = ( ( position.y > 0.f ) && - ( position.y - size.height < parentSize.height ) ); - break; - } - } - - return visible; -} - -Vector2 CalculateRectParameters( const Vector2& p0, const Vector2& p1 ) -{ - const float gradient = ( p1.y - p0.y ) / ( p1.x - p0.x ); - - return Vector2( gradient, p0.y - gradient * p0.x ); -} - -void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // Calculates an offset to align the whole text within the text-view's boundary accordingly with the set alignment and justification options. - // The offset could be negative if the whole text is bigger than the boundary of the text-view. - - // If the exceed policy is ellipsize at the end, negative offsets are not wanted. - // In that case, it will align the line to the left and/or top, and ellipsize the end. - const bool ellipsizeAlignToLeft = ( layoutParameters.mExceedPolicy == TextView::EllipsizeEndOriginal ) || - ( layoutParameters.mExceedPolicy == TextView::EllipsizeEnd ) || - ( layoutParameters.mExceedPolicy == TextView::SplitEllipsizeEnd ); - const bool ellipsizeAlignToTop = ( layoutParameters.mExceedPolicy == TextView::EllipsizeEnd ) || - ( layoutParameters.mExceedPolicy == TextView::SplitEllipsizeEnd ); - - RelayoutParameters relayoutParameters; - - // Calculates the vertical and horizontal offsets. - const float textHorizontalOffset = CalculateXoffset( layoutParameters.mHorizontalAlignment, relayoutData.mTextViewSize.width, relayoutData.mTextSizeForRelayoutOption.width ); - const float textVerticalOffset = CalculateYoffset( layoutParameters.mVerticalAlignment, relayoutData.mTextViewSize.height, relayoutData.mTextSizeForRelayoutOption.height ); - - // Index to the global character (within the whole text). - std::size_t characterGlobalIndex = 0u; - - // Index to the line info. - std::size_t lineLayoutInfoIndex = 0u; - - relayoutParameters.mIndices.mParagraphIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - float justificationOffset = 0.f; - - const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines. - bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line. - - relayoutParameters.mIndices.mWordIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), - endWordLayoutIt = wordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++characterGlobalIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - // Check if there is a new line. - const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ); - - if( newLine ) - { - // Calculate line justification offset. - justificationOffset = CalculateJustificationOffset( layoutParameters.mLineJustification, relayoutData.mTextSizeForRelayoutOption.width, relayoutData.mLines[lineLayoutInfoIndex].mSize.width ); - - // Point to the next line. - ++lineLayoutInfoIndex; - if( lineLayoutInfoIndex >= lineLayoutInfoSize ) - { - // Arrived at last line. - lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector. - } - } - - // Deletes the offsets if the exceed policies are EllipsizeEnd. - const float horizontalOffset = textHorizontalOffset + justificationOffset; - characterLayoutInfo.mOffset.x = ( ellipsizeAlignToLeft && ( horizontalOffset < 0.f ) ) ? 0.f : horizontalOffset; - characterLayoutInfo.mOffset.y = ( ellipsizeAlignToTop && ( textVerticalOffset < 0.f ) ) ? 0.f : textVerticalOffset; - - // Updates the size and position table for text-input with the alignment offset. - Vector3 positionOffset( characterLayoutInfo.mPosition ); - - // Update layout info table. - std::vector::iterator infoTableIt = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[characterGlobalIndex]; - Toolkit::TextView::CharacterLayoutInfo& characterTableInfo( *infoTableIt ); - - characterTableInfo.mPosition.x = positionOffset.x + characterLayoutInfo.mOffset.x; - characterTableInfo.mPosition.y = positionOffset.y + characterLayoutInfo.mOffset.y; - - positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor; - } // end characters - } // end words - } // end paragraphs -} - -void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - TextView::RelayoutData& relayoutData ) -{ - // No bearing used. - // - // gggggggggg - // gggggggggg - // gggg gggg - // gggg gggg - // gggg gggg - // gggg gggg - // gggg gggg - // gggg gggg - // ggggg gggggggggg bb ggggg - // gg gg gggggggggg bb gg gg - // gg gg gggg bb gg gg - // gg gg gggg bb gg gg - // ggggg gg gggg bbbbbbb ggggg - // gg gg gggg bb bb gg - // g gg gggggggggg bb bb g gg - // ggggg gggggggggg bbbbbbb ggggg - // - // Bearing used. - // - // gggggggggg - // gggggggggg - // gggg gggg bb - // gggg gggg bb - // gggg gggg bb - // ggggg gggg gggg bb ggggg - // gg gg gggg gggg bbbbbbb gg gg - // gg gg gggg gggg bb bb gg gg - // gg gg gggggggggg bb bb gg gg - // ggggg gggggggggg bbbbbbb ggggg - // gg gggg gg - // g gg gggg g gg - // ggggg gg gggg ggggg - // gg gggg - // gggggggggg - // gggggggggg - - const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1u ) ); - const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - ( characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender ); - - characterLayoutInfo.mPosition.y -= bearingOffset * relayoutData.mShrinkFactor; -} - -void UpdateLayoutInfoTable( Vector4& minMaxXY, - TextViewProcessor::WordLayoutInfo& wordLayoutInfo, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - RelayoutParameters& relayoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // updates min and max position to calculate the text size for multiline policies. - minMaxXY.x = std::min( minMaxXY.x, characterLayoutInfo.mPosition.x ); - minMaxXY.z = std::max( minMaxXY.z, characterLayoutInfo.mPosition.x + characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor ); - - minMaxXY.y = std::min( minMaxXY.y, characterLayoutInfo.mPosition.y - characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ); - minMaxXY.w = std::max( minMaxXY.w, characterLayoutInfo.mPosition.y ); - - // Adds layout info to be retrieved by external controls or applications. - Vector3 positionOffset( characterLayoutInfo.mPosition ); - - const float descender = characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender; - - const Toolkit::TextView::CharacterLayoutInfo characterLayoutTableInfo( Size( characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor, - characterLayoutInfo.mSize.height * relayoutData.mShrinkFactor ), - positionOffset, - ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ), - false, // whether the character is right to left. The value is set in a next step in the CreateBidirectionalInfoForLines function - true, // whether the character is visible. - descender ); - - relayoutData.mCharacterLayoutInfoTable.push_back( characterLayoutTableInfo ); - - positionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor; -} - -void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - const TextStyle& style, - RelayoutParameters& relayoutParameters, - FadeParameters& fadeParameters, - TextView::RelayoutData& relayoutData ) -{ - if( ( TextView::Fade != layoutParameters.mExceedPolicy ) && - ( TextView::SplitFade != layoutParameters.mExceedPolicy ) && - ( TextView::FadeOriginal != layoutParameters.mExceedPolicy ) && - ( TextView::OriginalFade != layoutParameters.mExceedPolicy ) ) - { - // nothing to fade - return; - } - - // Calculates visibility of a text-actor according the exceed policies. - - // position + alignment offset. - const Vector3 position( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x, - characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y, - characterLayoutInfo.mPosition.z ); - - // Whether the text actor is fully, partially or non visible (according exceed policies). - switch( layoutParameters.mExceedPolicy ) - { - case TextView::Fade: - { - // All text-actors which are not completely inside the text-view's boundaries are set as non visible. - // All text-actors which are partially inside the text-view's boundaries are set as partially visible. - if( !IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE ) ) - { - relayoutParameters.mIsVisible = false; - if( IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - PARTIALLY_VISIBLE ) ) - { - fadeParameters.mIsPartiallyVisible = true; - - // Checks if a text-actor is exceeding more than one boundary as this case is not supported. - if( IsExceedingWidth( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize ) && - IsExceedingHeight( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize ) ) - { - // Combination not fully supported by text-view. - // Need to check if text-actor really supports this combination. - fadeParameters.mIsPartiallyVisible = false; - } - } - } - break; - } - case TextView::FadeOriginal: - { - // All text-actors which are not completely between the left and right text-view's boundaries are set as non visible. - // All text-actors which are partially inside the text-view's boundaries are set as partially visible. - if( !IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_WIDTH ) ) - { - relayoutParameters.mIsVisible = false; - if( IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - PARTIALLY_VISIBLE_WIDTH ) ) - { - fadeParameters.mIsPartiallyVisible = true; - } - } - break; - } - case TextView::OriginalFade: - case TextView::SplitFade: // Fallthrough - { - // All text-actors which are not completely between the top and bottom text-view's boundaries are set as non visible. - // All text-actors which are partially inside the text-view's boundaries are set as partially visible. - if( !IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_HEIGHT ) ) - { - relayoutParameters.mIsVisible = false; - if( IsVisible( position, - characterLayoutInfo.mSize, - relayoutData.mTextViewSize, - PARTIALLY_VISIBLE_HEIGHT ) ) - { - fadeParameters.mIsPartiallyVisible = true; - } - } - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateVisibilityForFade. Wrong exceed policies." ) - break; - } - } - - if( relayoutParameters.mIsVisible || fadeParameters.mIsPartiallyVisible ) - { - characterLayoutInfo.mIsVisible = true; - - const Size size = characterLayoutInfo.mSize * relayoutData.mShrinkFactor; - const float characterPositionPlusWidth = position.x + size.width; - const float characterPositionMinusHeight = position.y - size.height; - - // Calculates which edges need to be faded-out. - bool rightFadeOut = false; - bool leftFadeOut = false; - bool bottomFadeOut = false; - bool topFadeOut = false; - - switch( layoutParameters.mExceedPolicy ) - { - case TextView::Fade: - { - // All text-actors exceeding any of the boundaries will be faded-out. - rightFadeOut = ( characterPositionPlusWidth > fadeParameters.mRightFadeThreshold ); - leftFadeOut = ( position.x < fadeParameters.mLeftFadeThreshold ); - bottomFadeOut = ( position.y > fadeParameters.mBottomFadeThreshold ); - topFadeOut = ( characterPositionMinusHeight < fadeParameters.mTopFadeThreshold ); - break; - } - case TextView::FadeOriginal: - { - // Only text-actors exceeding the left or the right boundaries will be faded-out. - rightFadeOut = ( characterPositionPlusWidth > fadeParameters.mRightFadeThreshold ); - leftFadeOut = ( position.x < fadeParameters.mLeftFadeThreshold ); - break; - } - case TextView::SplitFade: - case TextView::OriginalFade: //Fallthrough - { - // Only text-actors exceeding the top or the bottom boundaries will be faded-out. - bottomFadeOut = ( position.y > fadeParameters.mBottomFadeThreshold ); - topFadeOut = ( characterPositionMinusHeight < fadeParameters.mTopFadeThreshold ); - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextViewRelayout::CalculateVisibilityForFade. Wrong exceed policies." ); - break; - } - } - - // Calculates gradient parameters for a text-actor. - Vector4 gradientColor = Vector4::ZERO; - Vector2 startPoint = Vector2::ZERO; - Vector2 endPoint = Vector2::ZERO; - - if( !( rightFadeOut && leftFadeOut ) ) - { - // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the left and the right boundaries. - if( rightFadeOut ) - { - gradientColor = style.GetTextColor(); - - // Calculates gradient coeficients. - characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mRightAlphaCoeficients.x * position.x + fadeParameters.mRightAlphaCoeficients.y ); - gradientColor.a *= std::max( 0.f, fadeParameters.mRightAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mRightAlphaCoeficients.y ); - - startPoint = Vector2( std::max( 0.f, std::min( 1.f, ( fadeParameters.mRightFadeThresholdOffset - position.x ) / size.width ) ), 0.5f ); - endPoint = Vector2( std::min( 1.f, std::max( 0.f, ( relayoutData.mTextViewSize.width - position.x ) / size.width ) ), 0.5f ); - - if( NULL == characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo(); - } - } - else if( leftFadeOut ) - { - gradientColor = style.GetTextColor(); - - // Calculates gradient coeficients. - characterLayoutInfo.mColorAlpha = std::min( 1.f, fadeParameters.mLeftAlphaCoeficients.x * characterPositionPlusWidth + fadeParameters.mLeftAlphaCoeficients.y ); - gradientColor.a *= gradientColor.a * std::max( 0.f, fadeParameters.mLeftAlphaCoeficients.x * position.x + fadeParameters.mLeftAlphaCoeficients.y ); - - startPoint = Vector2( std::max( 0.f, std::min( 1.f, ( fadeParameters.mLeftFadeThresholdOffset - position.x ) / size.width ) ), 0.5f ); - endPoint = Vector2( std::min( 1.f, std::max( 0.f, -position.x / size.width ) ), 0.5f ); - - if( NULL == characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo(); - } - } - } - - if( !( bottomFadeOut && topFadeOut ) ) - { - // Current implementation can't set gradient parameters for a text-actor exceeding at the same time the top and the bottom boundaries. - if( bottomFadeOut ) - { - gradientColor = style.GetTextColor(); - - // Calculates gradient coeficients. - characterLayoutInfo.mColorAlpha = gradientColor.a * std::min( 1.f, fadeParameters.mBottomAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mBottomAlphaCoeficients.y ); - gradientColor.a *= std::max( 0.f, fadeParameters.mBottomAlphaCoeficients.x * position.y + fadeParameters.mBottomAlphaCoeficients.y ); - - startPoint = Vector2( 0.5f, std::max( 0.f, std::min( 1.f, ( fadeParameters.mBottomFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) ) ); - endPoint = Vector2( 0.5f, std::min( 1.f, std::max( 0.f, ( relayoutData.mTextViewSize.height - characterPositionMinusHeight ) / size.height ) ) ); - - if( NULL == characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo(); - } - } - else if( topFadeOut ) - { - gradientColor = style.GetTextColor(); - - // Calculates gradient coeficients. - characterLayoutInfo.mColorAlpha *= gradientColor.a * std::min( 1.f, fadeParameters.mTopAlphaCoeficients.x * position.y + fadeParameters.mTopAlphaCoeficients.y ); - gradientColor.a *= std::max( 0.f, fadeParameters.mTopAlphaCoeficients.x * characterPositionMinusHeight + fadeParameters.mTopAlphaCoeficients.y ); - - startPoint = Vector2( 0.5f, std::max( 0.f, std::min( 1.f, ( fadeParameters.mTopFadeThresholdOffset - characterPositionMinusHeight ) / size.height ) ) ); - endPoint = Vector2( 0.5f, std::min( 1.f, std::max( 0.f, -characterPositionMinusHeight / size.height ) ) ); - - if( NULL == characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo = new TextViewProcessor::GradientInfo(); - } - } - } - - if( NULL != characterLayoutInfo.mGradientInfo ) - { - characterLayoutInfo.mGradientInfo->mGradientColor = gradientColor; - characterLayoutInfo.mGradientInfo->mStartPoint = startPoint; - characterLayoutInfo.mGradientInfo->mEndPoint = endPoint; - } - } - else - { - characterLayoutInfo.mIsVisible = false; - } -} - -bool CalculateVisibilityForEllipsizeEndOriginal( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - const EllipsizeParameters& ellipsizeParameters ) -{ - bool isPartiallyVisible = false; - - if( !IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - FULLY_VISIBLE_WIDTH ) ) - { - // The character doesn't fit in the text-view's width. - characterLayoutInfo.mIsVisible = false; - - // Checks if the character is partially visible (it's cut by the boundary) - isPartiallyVisible = IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - PARTIALLY_VISIBLE_WIDTH ); - } - else - { - // The character fits in the text-view's width. Set it to visible. - characterLayoutInfo.mIsVisible = true; - } - - return isPartiallyVisible; -} - -bool CalculateVisibilityForEllipsizeEnd( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - const EllipsizeParameters& ellipsizeParameters ) -{ - bool isPartiallyVisible = false; - - if( !IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - FULLY_VISIBLE ) ) - { - // The character is not fully visible. Needs to check if it's partially visible. - characterLayoutInfo.mIsVisible = false; - - // Checks if the character doesn't cut the bottom edge of the text-view. - const bool fullyVisibleHeight = IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - FULLY_VISIBLE_HEIGHT ); - - // Checks if the character cuts the right edge of the text-view. - const bool partiallyVisibleWidth = IsVisible( ellipsizeParameters.mPosition, - characterLayoutInfo.mSize, - ellipsizeParameters.mEllipsizeBoundary, - PARTIALLY_VISIBLE_WIDTH ); - - // Character will be ellipsized if it cuts the right edge of the text-view but fits completely in the text-view's height. - isPartiallyVisible = ( fullyVisibleHeight && partiallyVisibleWidth ); - } - else - { - // The character fits in the boundary of the text-view. Set it to visible. - characterLayoutInfo.mIsVisible = true; - } - - return isPartiallyVisible; -} - -void CalculateVisibilityForEllipsize( const Internal::TextView::LayoutParameters& layoutParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ) -{ - // Calculates visibility for EllipsizeEnd exceed policies. - - // It defines a boundary on the right side of the text-view by substracting the ellipsize-text's size (...) to the text-view's size. - // If a character is cut by this boundary and the whole line (if the multi-line policy is split-by-new-line-char) - // or the whole word (if the multi-line policy is split-by-word) doesn't fit in the text-view's width, then it's replaced by the ellipsize-text. - - // Position of the character used to do the visibility test. - ellipsizeParameters.mPosition = Vector3( characterLayoutInfo.mPosition.x + characterLayoutInfo.mOffset.x, - characterLayoutInfo.mPosition.y + characterLayoutInfo.mOffset.y, - characterLayoutInfo.mPosition.z ); - - // Text will be ellipsized if a character is partially visible (it's cut by the boundary defined in the right side of the text-view). - bool isPartiallyVisible = false; - - // Checks if the whole line or the whole word fits in the text-view's width accordingly with the multiline policy. - const bool fitsInWidth = ( Toolkit::TextView::SplitByNewLineChar == layoutParameters.mMultilinePolicy ) ? ellipsizeParameters.mLineFits: ellipsizeParameters.mWordFits; - - // Will only ellipsize the text if it cuts the right vertical edge and it doesn't fit in the text-view's width. - if( fitsInWidth ) - { - // The line or word fits completely inside the text-view's width. Nothing else to do. - characterLayoutInfo.mIsVisible = true; - } - else - { - // The line or word doesn't fit in the text-view's width. - - // Calculates visibility for each type of ellipsize policies. - switch( layoutParameters.mExceedPolicy ) - { - case TextView::EllipsizeEndOriginal: - { - // Ellipsizes the text if it doesn't fit in the width but it doesn't ellipsize if the text doesn't fit in the height. - - isPartiallyVisible = CalculateVisibilityForEllipsizeEndOriginal( characterLayoutInfo, - ellipsizeParameters ); - - break; - } - case TextView::SplitEllipsizeEnd: - case TextView::EllipsizeEnd: - { - // Ellipsizes the text if it doesn't fit in the width and fully fits in the text-view's height. - - isPartiallyVisible = CalculateVisibilityForEllipsizeEnd( characterLayoutInfo, - ellipsizeParameters ); - - break; - } - default: - { - DALI_ASSERT_DEBUG( !"TextViewRelayout::CalculateVisibilityForEllipsize. Wrong exceed value." ); - break; - } - } - } - - // If the current character is not fully visible but is partially visible, it is cut by the boundary of the text-view. - // In that case, the charater needs to be replaced by the ellipsize text. - ellipsizeParameters.mCreateEllipsizedTextActors = ( !characterLayoutInfo.mIsVisible && isPartiallyVisible ); -} - -void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ) -{ - // The default ellipsize text is '...' and all dots have the same style. However, a differernt ellipsize text could be set and it can have characters with differernt styles. - // The code bellow creates the text-actors needed for the ellipsize text. - - // Set ellipsize's position by the end of visible text. - Vector3 ellipsizePosition = ellipsizeParameters.mPosition; - // Stores current ellipsize text. - Text ellipsizeText; - // Stores current ellipsize style. - TextStyle ellipsizeStyle; - // Stores the current size. - Size ellipsizeSize; - //Whether current glyph is an emoticon. - bool isColorGlyph = false; - - float bearingOffset = 0.f; - - // Create ellipsize text-actor. - std::size_t characterIndex = 0u; - for( TextViewProcessor::CharacterLayoutInfoContainer::const_iterator ellipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.begin(), - endEllipsizeCharacterLayoutIt = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.end(); - ellipsizeCharacterLayoutIt != endEllipsizeCharacterLayoutIt; - ++ellipsizeCharacterLayoutIt, ++characterIndex ) - { - const TextViewProcessor::CharacterLayoutInfo& ellipsizeCharacterLayoutInfo( *ellipsizeCharacterLayoutIt ); - const TextStyle& style = *( *( relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin() + characterIndex ) ); - - if( isColorGlyph || - ( isColorGlyph != ellipsizeCharacterLayoutInfo.mIsColorGlyph ) || - ( ellipsizeStyle != style ) ) - { - // The style is different, so a new text-actor is needed. - if( !ellipsizeText.IsEmpty() ) - { - // It only creates a text-actor if there is any text. - RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache ); - ellipsizeGlyphActor.SetSize( ellipsizeSize ); - ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) ); - - // Updates the position for the next text-actor. - ellipsizePosition.x += ellipsizeSize.width; - - // Adds the text-actor to the list. - relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor ); - } - - // Resets the current ellipsize info. - ellipsizeText = Text( relayoutData.mTextLayoutInfo.mEllipsisText[characterIndex] ); - ellipsizeStyle = style; - ellipsizeSize = ellipsizeCharacterLayoutInfo.mSize; - isColorGlyph = ellipsizeCharacterLayoutInfo.mIsColorGlyph; - - bearingOffset = ( ellipsizeParameters.mLineDescender - ( ellipsizeCharacterLayoutInfo.mSize.height - ellipsizeCharacterLayoutInfo.mAscender ) ) * relayoutData.mShrinkFactor; - } - else - { - // Updates text and size with the new character. - ellipsizeText.Append( relayoutData.mTextLayoutInfo.mEllipsisText[characterIndex] ); - TextViewProcessor::UpdateSize( ellipsizeSize, ellipsizeCharacterLayoutInfo.mSize ); - } - } - - if( !ellipsizeText.IsEmpty() ) - { - // Creates the last glyph-actor. - RenderableActor ellipsizeGlyphActor = CreateGlyphActor( ellipsizeText, ellipsizeStyle, relayoutData.mTextActorCache ); - ellipsizeGlyphActor.SetSize( ellipsizeSize ); - ellipsizeGlyphActor.SetPosition( Vector3( ellipsizePosition.x, ellipsizePosition.y - bearingOffset, ellipsizePosition.z ) ); - - // Adds the glyph-actor to the list. - relayoutData.mEllipsizedGlyphActors.push_back( ellipsizeGlyphActor ); - } -} - -void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, - EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ) -{ - // Traverses the text layout info from the first character of the line - // to the last one setting to each character its visibility. If needed, it adds the ellipsize text (...). - - // Indices to the first character of the line. - TextViewProcessor::TextInfoIndices firstIndices; - TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mFirstIndex, - relayoutData.mTextLayoutInfo, - firstIndices ); - - // Indices to the last character of the line. - TextViewProcessor::TextInfoIndices lastIndices; - TextViewProcessor::GetIndicesFromGlobalCharacterIndex( ellipsizeParameters.mLastIndex, - relayoutData.mTextLayoutInfo, - lastIndices ); - - // Defines a boundary by substracting the ellipsize-text's width to the text-view's width. - // This is the boundary used to check if a character have to be ellipsized. - ellipsizeParameters.mEllipsizeBoundary = relayoutData.mTextViewSize; - ellipsizeParameters.mEllipsizeBoundary.width -= relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + firstIndices.mParagraphIndex, - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + lastIndices.mParagraphIndex + 1u; - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - ellipsizeParameters.mLineFits = ellipsizeParameters.mIsLineWidthFullyVisible && ellipsizeParameters.mIsLineHeightFullyVisible && ellipsizeParameters.mIsNextLineFullyVisibleHeight; - - if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight ) - { - ellipsizeParameters.mEllipsizeBoundary.width = ellipsizeParameters.mLineWidth; - } - - bool firstWord = true; - bool lastWord = false; - - std::size_t wordCount = 0u; - - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin() + firstIndices.mWordIndex, - endWordLayoutIt = wordsLayoutInfo.begin() + lastIndices.mWordIndex + 1u; - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++wordCount ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - if( wordCount == lastIndices.mWordIndex - firstIndices.mWordIndex ) - { - lastWord = true; - } - - const std::size_t firstCharacterIndex = firstWord ? firstIndices.mCharacterIndex : 0u; - const std::size_t lastCharacterIndex = lastWord ? lastIndices.mCharacterIndex : wordLayoutInfo.mCharactersLayoutInfo.size() - 1u; - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + firstCharacterIndex, - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin() + lastCharacterIndex + 1u; - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - if( ellipsizeParameters.mEllipsizeLine ) - { - // Calculates the character visibility and whether it needs to be replace by ellipsized text. - CalculateVisibilityForEllipsize( layoutParameters, - characterLayoutInfo, - ellipsizeParameters, - relayoutData ); - - if( ellipsizeParameters.mCreateEllipsizedTextActors ) - { - // Create ellipsize text-actors if the character needs to be replaced. - CreateEllipsizeTextActor( ellipsizeParameters, - relayoutData ); - } - } - else - { - if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) || - ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy )) - { - if( !ellipsizeParameters.mIsLineHeightFullyVisible ) - { - // Make characters invisible. - characterLayoutInfo.mIsVisible = false; - } - } - } - } // end characters - firstWord = false; - } // end words - } // end paragraphs -} - -void SetTextVisible( TextView::RelayoutData& relayoutData ) -{ - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - std::size_t characterIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), - endWordLayoutIt = wordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++characterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - characterLayoutInfo.mIsVisible = true; - delete characterLayoutInfo.mGradientInfo; - characterLayoutInfo.mGradientInfo = NULL; - characterLayoutInfo.mColorAlpha = ( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) )->GetTextColor().a; - } // end characters - } // end words - } // end paragraphs - - // Updates the visibility for text-input.. - for( std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin(), - endIt = relayoutData.mCharacterLayoutInfoTable.end(); - it != endIt; - ++it ) - { - Toolkit::TextView::CharacterLayoutInfo& characterLayoutInfo( *it ); - - characterLayoutInfo.mIsVisible = true; - } -} - -void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - RelayoutParameters relayoutParameters; - FadeParameters fadeParameters; - - // Calculates the fade thresholds (from where the text starts to fade out). If any of the fade boundaries is zero, it sets a very small value just to avoid a zero division. - fadeParameters.mRightFadeBoundary = static_cast( visualParameters.mFadeBoundary.mRight ); - fadeParameters.mRightFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mRight > 0u ? fadeParameters.mRightFadeBoundary : MINIMUM_FADE_BOUNDARY ); - fadeParameters.mRightFadeThreshold = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundary; - fadeParameters.mRightFadeThresholdOffset = relayoutData.mTextViewSize.width - fadeParameters.mRightFadeBoundaryOffset; - fadeParameters.mLeftFadeBoundary = static_cast( visualParameters.mFadeBoundary.mLeft ); - fadeParameters.mLeftFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mLeft > 0u ? fadeParameters.mLeftFadeBoundary : MINIMUM_FADE_BOUNDARY ); - fadeParameters.mLeftFadeThreshold = fadeParameters.mLeftFadeBoundary; - fadeParameters.mLeftFadeThresholdOffset = fadeParameters.mLeftFadeBoundaryOffset; - fadeParameters.mTopFadeBoundary = static_cast( visualParameters.mFadeBoundary.mTop ); - fadeParameters.mTopFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mTop > 0u ? fadeParameters.mTopFadeBoundary : MINIMUM_FADE_BOUNDARY ); - fadeParameters.mTopFadeThreshold = fadeParameters.mTopFadeBoundary; - fadeParameters.mTopFadeThresholdOffset = fadeParameters.mTopFadeBoundaryOffset; - fadeParameters.mBottomFadeBoundary = static_cast( visualParameters.mFadeBoundary.mBottom ); - fadeParameters.mBottomFadeBoundaryOffset = ( visualParameters.mFadeBoundary.mBottom > 0u ? fadeParameters.mBottomFadeBoundary : MINIMUM_FADE_BOUNDARY ); - fadeParameters.mBottomFadeThreshold = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundary; - fadeParameters.mBottomFadeThresholdOffset = relayoutData.mTextViewSize.height - fadeParameters.mBottomFadeBoundaryOffset; - - // Calculates the fade out rect coeficients for the right, left, top and bottom sides of the text-view. - fadeParameters.mRightAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mRightFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.width, 0.f ) ); - fadeParameters.mLeftAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mLeftFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) ); - fadeParameters.mTopAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mTopFadeThresholdOffset, 1.f ), Vector2( 0.f, 0.f ) ); - fadeParameters.mBottomAlphaCoeficients = CalculateRectParameters( Vector2( fadeParameters.mBottomFadeThresholdOffset, 1.f ), Vector2( relayoutData.mTextViewSize.height, 0.f ) ); - - // Traverses all characters and calculates the visibility. - - std::size_t infoTableCharacterIndex = 0u; - - relayoutParameters.mIndices.mParagraphIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - std::size_t characterIndex = 0u; - relayoutParameters.mIndices.mWordIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), - endWordLayoutIt = wordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - relayoutParameters.mIsFirstCharacterOfWord = true; - relayoutParameters.mWordSize = wordLayoutInfo.mSize; - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex, ++infoTableCharacterIndex, ++characterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - relayoutParameters.mIsVisible = true; - fadeParameters.mIsPartiallyVisible = false; - - // Calculates the visibility for the current character. - CalculateVisibilityForFade( layoutParameters, - characterLayoutInfo, - *( *( paragraphLayoutInfo.mTextStyles.Begin() + characterIndex ) ), - relayoutParameters, - fadeParameters, - relayoutData ); - - // Updates the visibility for text-input.. - std::vector::iterator it = relayoutData.mCharacterLayoutInfoTable.begin() + relayoutData.mCharacterVisualToLogicalMap[infoTableCharacterIndex]; - - Toolkit::TextView::CharacterLayoutInfo& characterLayoutTableInfo( *it ); - - characterLayoutTableInfo.mIsVisible = relayoutParameters.mIsVisible; - - relayoutParameters.mIsFirstCharacterOfWord = false; - } // end character - } // end words - } // end paragraphs -} - -void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - // TODO check ellipsis with rtl text. - - // Traverses the lines and checks which ones doesn't fit in the text-view's boundary. - for( Toolkit::TextView::LineLayoutInfoContainer::const_iterator lineInfoIt = relayoutData.mLines.begin(), endLineInfoIt = relayoutData.mLines.end(); - lineInfoIt != endLineInfoIt; - ++lineInfoIt ) - { - const Toolkit::TextView::LineLayoutInfo& lineInfo( *lineInfoIt ); - - // To check if a line fits in the text-view's boundary, - // get the position of the first character is needed and do the test - // with the line size. - - // An bearing offset may have been applied to the first character so it's needed to - // get the start position of the line. - - // Some parameters used in the CalculateVisibilityForEllipsize() function. - EllipsizeParameters ellipsizeParameters; - - // Retrieves the first index and the last index of the line. - ellipsizeParameters.mFirstIndex = lineInfo.mCharacterGlobalIndex; - ellipsizeParameters.mLastIndex = 0u; - if( ( lineInfoIt + 1u ) != endLineInfoIt ) - { - const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *( lineInfoIt + 1u ) ); - ellipsizeParameters.mLastIndex = nextLineInfo.mCharacterGlobalIndex - 1u; - } - else - { - ellipsizeParameters.mLastIndex = relayoutData.mCharacterLayoutInfoTable.size() - 1u; - } - - // Retrieves the first character of the line and build the position of the line with the bearing. - const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + ellipsizeParameters.mFirstIndex ); - - // Calculates the bearing offset applied to the first character. - const float bearingOffset = ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender; - - // Build the position of the line by removing the bearing offset from the first character's position. - const Vector3 position( characterInfo.mPosition.x, - characterInfo.mPosition.y + bearingOffset, - characterInfo.mPosition.z ); - - // Checks if the line needs to be ellipsized, - ellipsizeParameters.mIsLineWidthFullyVisible = IsVisible( position, - lineInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_WIDTH ); - - // If the exceed policy is EllipsizeEndOriginal it's enough to check - // if the line fits in the width. - ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsLineWidthFullyVisible; - - // If the exceed policy is EllipsizeEnd, it's needed to check if the next line exceeds the text-view's height. - // If the next line exceeds the text-view height then it's going to be invisible and current line needs to be ellipsized. - ellipsizeParameters.mIsLineHeightFullyVisible = true; - ellipsizeParameters.mIsNextLineFullyVisibleHeight = true; - if( ( TextView::EllipsizeEnd == layoutParameters.mExceedPolicy ) || - ( TextView::SplitEllipsizeEnd == layoutParameters.mExceedPolicy ) ) - { - // Need to check if there is lines which doesn't fit in the height. - - ellipsizeParameters.mIsLineHeightFullyVisible = IsVisible( position, - lineInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_HEIGHT ); - - ellipsizeParameters.mEllipsizeLine = ellipsizeParameters.mEllipsizeLine && ellipsizeParameters.mIsLineHeightFullyVisible; - - if( ellipsizeParameters.mIsLineHeightFullyVisible && !ellipsizeParameters.mEllipsizeLine ) - { - // Current line is not ellipsized. - // Need to check if there is a next line and if it's not visible. If there is, current line needs to be ellipsized. - Toolkit::TextView::LineLayoutInfoContainer::const_iterator nextLineInfoIt = lineInfoIt + 1u; - if( nextLineInfoIt != endLineInfoIt ) - { - // Retrives the position of the first character of the line and remove - // the bearing offset to build to build the position of the line. - const Toolkit::TextView::LineLayoutInfo& nextLineInfo( *nextLineInfoIt ); - const Toolkit::TextView::CharacterLayoutInfo& characterInfo = *( relayoutData.mCharacterLayoutInfoTable.begin() + nextLineInfo.mCharacterGlobalIndex ); - - const float bearingOffset = ( ( lineInfo.mSize.height - lineInfo.mAscender ) - characterInfo.mDescender ) * relayoutData.mShrinkFactor; - - const Vector3 position( characterInfo.mPosition.x, - characterInfo.mPosition.y + bearingOffset, - characterInfo.mPosition.z ); - - ellipsizeParameters.mIsNextLineFullyVisibleHeight = IsVisible( position, - nextLineInfo.mSize, - relayoutData.mTextViewSize, - FULLY_VISIBLE_HEIGHT ); - - // If the next line is not visible, current line have to be ellipsized. - ellipsizeParameters.mEllipsizeLine = !ellipsizeParameters.mIsNextLineFullyVisibleHeight; - } - } - } - - if( !ellipsizeParameters.mIsNextLineFullyVisibleHeight ) - { - ellipsizeParameters.mLineWidth = position.x + lineInfo.mSize.width - relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mSize.width; - } - - // Sets the line descender. - ellipsizeParameters.mLineDescender = lineInfo.mSize.height - lineInfo.mAscender; - - // At this point, ellipsizeLine distinguish if a piece of line have to be ellipsized or not. - EllipsizeLine( layoutParameters, ellipsizeParameters, relayoutData ); - } -} - -void UpdateVisibility( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - switch( layoutParameters.mExceedPolicy ) - { - case TextView::FadeOriginal: - case TextView::OriginalFade: - case TextView::Fade: - case TextView::SplitFade: // Fall through - { - UpdateVisibilityForFade( layoutParameters, - visualParameters, - relayoutData ); - break; - } - case TextView::EllipsizeEndOriginal: - case TextView::SplitEllipsizeEnd: - case TextView::EllipsizeEnd: // Fall through - { - // Set first all characters to visible as UpdateVisibilityForEllipsize() doesn't traverse all of them. - SetTextVisible( relayoutData ); - - UpdateVisibilityForEllipsize( layoutParameters, - visualParameters, - relayoutData ); - break; - } - default: - { - SetTextVisible( relayoutData ); - break; - } - } -} - -/** - * Creates an image actor for the emoticon. - * - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] characterLayout Layout info for the character. - * @param[in] character The character. - */ -void CreateEmoticon( const TextView::VisualParameters& visualParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayout, - const Character& character ) -{ - // The character is an emoticon. - ImageActor imageActor = ImageActor::DownCast( characterLayout.mGlyphActor ); - if( !imageActor ) - { - imageActor = ImageActor::New(); - - GlyphImage image = GlyphImage::New( character ); - - if( image ) - { - imageActor.SetImage( image ); - } - } - - imageActor.SetPosition( Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x, - characterLayout.mPosition.y + characterLayout.mOffset.y, - characterLayout.mPosition.z ) ); - imageActor.SetSize( characterLayout.mSize ); - - // Sets the sort modifier value. - // imageActor.SetSortModifier( visualParameters.mSortModifier ); - - characterLayout.mGlyphActor = imageActor; -} - -/** - * Creates text-actors for the given text. - * - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in,out] paragraph Layout info for the paragraph. - * @param[in,out] wordLayout Layout info for the word. - * @param[in,out] characterLayout Layout info for the character. - * @param[in] character The character. - * @param[in] style The character's style. - * @param[in,out] currentTextActorInfo Temporary stores the text-actor's info to be set. - * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles. - * @param[in,out] textActorCreated Whether a text-actor - */ -void CreateTextActor( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - const TextViewProcessor::ParagraphLayoutInfo& paragraph, - TextViewProcessor::WordLayoutInfo& wordLayout, - TextViewProcessor::CharacterLayoutInfo& characterLayout, - const Character& character, - const TextStyle& style, - CurrentTextActorInfo& currentTextActorInfo, - bool createGlyphActors, - bool& textActorCreated ) -{ - textActorCreated = false; - - // Set the text-actor for the current traversed text. - if( currentTextActorInfo.textActor ) - { - if( ( NULL != currentTextActorInfo.characterLayout ) && - currentTextActorInfo.characterLayout->mSetText ) - { - currentTextActorInfo.textActor.SetText( currentTextActorInfo.text ); - currentTextActorInfo.characterLayout->mSetText = false; - } - currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position ); - currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size ); - - SetVisualParameters( currentTextActorInfo, - visualParameters, - relayoutData, - paragraph.mSize.height ); - } - - float rightToLeftOffset = 0.f; - if( character.IsWhiteSpace() ) - { - // In left to right text, a word never starts with a white space but - // it may happen in right to left text as the text is reversed. - // The text alignment and justification offset is calculated without this white space. - // It causes a missalignment which can be corrected by removing the size of the white space. - rightToLeftOffset = characterLayout.mSize.width * relayoutData.mShrinkFactor; - } - - // Whether this word is not a white space or if it is, it is underlined. - // Don't want to create text-actors for white spaces unless they are underlined. - bool isNotWhiteSpace = ( TextViewProcessor::NoSeparator == wordLayout.mType ) || ( ( TextViewProcessor::WordSeparator == wordLayout.mType ) && style.IsUnderlineEnabled() ); - - if( isNotWhiteSpace ) - { - currentTextActorInfo.text = Text( character ); - } - else - { - currentTextActorInfo.text = Text(); - } - currentTextActorInfo.position = Vector3( characterLayout.mPosition.x + characterLayout.mOffset.x - rightToLeftOffset, - characterLayout.mPosition.y + characterLayout.mOffset.y, - characterLayout.mPosition.z ); - currentTextActorInfo.size = characterLayout.mSize * relayoutData.mShrinkFactor; - - currentTextActorInfo.color = style.GetTextColor(); - currentTextActorInfo.color.a = characterLayout.mColorAlpha; - - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - - if( createGlyphActors && isNotWhiteSpace ) - { - textActorCreated = true; - if( textActor ) - { - // Try to reuse first the text-actor of this character. - textActor.SetTextStyle( style ); - } - else - { - // If there is no text-actor, try to retrieve one from the cache. - textActor = relayoutData.mTextActorCache.RetrieveTextActor(); - - // If still there is no text-actor, create one. - if( !textActor ) - { - TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF ); - textActor = TextActor::New( Text(), parameters ); - textActor.SetRelayoutEnabled( false ); - } - else - { - textActor.SetTextStyle( style ); - } - } - characterLayout.mSetText = true; - currentTextActorInfo.characterLayout = &characterLayout; - - characterLayout.mGlyphActor = textActor; - } - - // Update the current text-actor. - currentTextActorInfo.textActor = textActor; -} - -/** - * Traverses the whole paragraph initializating renderable-actor handles and updating them with the new size and position. - * - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in,out] paragraph Layout info for the paragraph. - * @param[in,out] characterGlobalIndex Index to the character within the whole text. - * @param[in,out] lineLayoutInfoIndex Index to the table of lines. - * @param[in,out] createGlyphActors Whether to initialize renderable-actor handles. - */ -void UpdateTextActorInfoForParagraph( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - TextViewProcessor::ParagraphLayoutInfo& paragraphLayout, - std::size_t& characterGlobalIndex, - std::size_t& lineLayoutInfoIndex, - bool createGlyphActors ) -{ - CurrentTextActorInfo currentTextActorInfo; - currentTextActorInfo.characterLayout = NULL; - - const std::size_t lineLayoutInfoSize = relayoutData.mLines.size(); // Number of lines. - bool lineLayoutEnd = false; // Whether lineLayoutInfoIndex points at the last line. - bool textActorCreated = false; // Whether a text actor has been created for this the current group of characters traversed. - - TextStyle currentStyle; // style for the current text-actor. - - TextViewProcessor::GradientInfo* currentGradientInfo = NULL; // gradient color for the current text-actor. - // start point for the current text-actor. - // end point for the current text-actor. - - bool currentIsColorGlyph = false; // Whether current glyph is an emoticon. - - std::vector textActorsToRemove; // Keep a vector of text-actors to be included into the cache. - - // Retrieve the layout info to traverse. If there is right to left text it retrieves the right to left layout. - const bool isRightToLeftLayout = NULL != paragraphLayout.mRightToLeftLayout; - - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayout.mWordsLayoutInfo; - Text& text = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mText : paragraphLayout.mText; - Vector& textStyles = isRightToLeftLayout ? paragraphLayout.mRightToLeftLayout->mTextStyles : paragraphLayout.mTextStyles; - - // In case the previous right to left layout has been cleared, all text-actors have been removed as well. If this bool is set to true, text-actors will be created again. - createGlyphActors = createGlyphActors || ( ( isRightToLeftLayout ) ? paragraphLayout.mRightToLeftLayout->mPreviousLayoutCleared : false ); - - std::size_t characterParagraphIndex = 0u; // Index to the character (within the paragraph). - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - TextViewProcessor::WordLayoutInfo& wordLayout( *wordIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = wordLayout.mCharactersLayoutInfo.begin(), characterEndIt = wordLayout.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayout( *characterIt ); - - // Check if there is a new line. - const bool newLine = !lineLayoutEnd && ( characterGlobalIndex == relayoutData.mLines[lineLayoutInfoIndex].mCharacterGlobalIndex ); - - if( newLine ) - { - // Point to the next line. - ++lineLayoutInfoIndex; - if( lineLayoutInfoIndex >= lineLayoutInfoSize ) - { - // Arrived at last line. - lineLayoutEnd = true; // Avoids access out of bounds in the relayoutData.mLines vector. - } - textActorCreated = false; - } - - // Do not create a glyph-actor if there is no text. - const Character character = text[characterParagraphIndex]; - const TextStyle& style = *( *( textStyles.Begin() + characterParagraphIndex ) ); - - // Check if the character has the same gradient info than the current one. - bool differentGradientInfo = false; - if( characterLayout.mGradientInfo && currentGradientInfo ) - { - differentGradientInfo = ( characterLayout.mGradientInfo->mGradientColor != currentGradientInfo->mGradientColor ) || - ( characterLayout.mGradientInfo->mStartPoint != currentGradientInfo->mStartPoint ) || - ( characterLayout.mGradientInfo->mEndPoint != currentGradientInfo->mEndPoint ); - } - else if( ( NULL != currentGradientInfo ) || ( NULL != characterLayout.mGradientInfo ) ) - { - differentGradientInfo = true; - } - - if( ( createGlyphActors && !textActorCreated ) || - characterLayout.mIsColorGlyph || - differentGradientInfo || - ( characterLayout.mIsColorGlyph != currentIsColorGlyph ) || - ( style != currentStyle ) ) - { - characterLayout.mSetText = false; - characterLayout.mSetStyle = false; - - if( characterLayout.mIsColorGlyph ) - { - CreateEmoticon( visualParameters, - characterLayout, - character ); - - characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); - } - else - { - // There is a new style or a new line. - - CreateTextActor( visualParameters, - relayoutData, - paragraphLayout, - wordLayout, - characterLayout, - character, - style, - currentTextActorInfo, - createGlyphActors, - textActorCreated ); - - if( textActorCreated ) - { - characterLayout.mGlyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - characterLayout.mGlyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); - } - } - - // Update style to be checked with next characters. - currentStyle = style; - currentGradientInfo = characterLayout.mGradientInfo; - currentIsColorGlyph = characterLayout.mIsColorGlyph; - } - else - { - DALI_ASSERT_DEBUG( !characterLayout.mIsColorGlyph && "TextViewProcessor::InitializeTextActorInfo. An image-actor doesn't store more than one emoticon." ); - - // Same style than previous one. - - // Add the character to the current text-actor and update the size. - if( characterLayout.mIsVisible && ( TextViewProcessor::ParagraphSeparator != wordLayout.mType ) ) - { - currentTextActorInfo.text.Append( character ); - - currentTextActorInfo.position.y = std::min( currentTextActorInfo.position.y, ( characterLayout.mPosition.y + characterLayout.mOffset.y ) ); - currentTextActorInfo.size.width += characterLayout.mSize.width * relayoutData.mShrinkFactor; - currentTextActorInfo.size.height = std::max( currentTextActorInfo.size.height, characterLayout.mSize.height * relayoutData.mShrinkFactor ); - } - } - - if( ( createGlyphActors ) && - !characterLayout.mIsColorGlyph && - !textActorCreated ) - { - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - if( textActor ) - { - // There is a previously created text-actor for this character. - // If this character has another one put it into the cache. - textActor.SetText( "" ); - textActorsToRemove.push_back( textActor ); - } - - if( characterLayout.mGlyphActor ) - { - characterLayout.mGlyphActor.Reset(); - } - } - ++characterGlobalIndex; - ++characterParagraphIndex; - } // characters - } // words - - if( !currentTextActorInfo.text.IsEmpty() ) - { - if( currentTextActorInfo.textActor ) - { - if( ( NULL != currentTextActorInfo.characterLayout ) && - currentTextActorInfo.characterLayout->mSetText ) - { - currentTextActorInfo.textActor.SetText( currentTextActorInfo.text ); - currentTextActorInfo.characterLayout->mSetText = false; - } - currentTextActorInfo.textActor.SetPosition( currentTextActorInfo.position ); - currentTextActorInfo.textActor.SetSize( currentTextActorInfo.size ); - - SetVisualParameters( currentTextActorInfo, - visualParameters, - relayoutData, - paragraphLayout.mSize.height ); - } - } - - // Insert the spare text-actors into the cache. - relayoutData.mTextActorCache.InsertTextActors( textActorsToRemove ); -} - -void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - bool createGlyphActors ) -{ - if( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - // nothing to do if there is no paragraphs. - return; - } - - std::size_t characterGlobalIndex = 0u; // Index to the global character (within the whole text). - std::size_t lineLayoutInfoIndex = 0u; // Index to the line info. - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - - UpdateTextActorInfoForParagraph( visualParameters, - relayoutData, - paragraph, - characterGlobalIndex, - lineLayoutInfoIndex, - createGlyphActors ); - } // paragraphs - - // Set visual parameters for ellipsis renderable actors. - for( std::vector::iterator it = relayoutData.mEllipsizedGlyphActors.begin(), - endIt = relayoutData.mEllipsizedGlyphActors.end(); - it != endIt; - ++it ) - { - RenderableActor glyphActor = ( *it ); - - glyphActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); - glyphActor.SetAnchorPoint( AnchorPoint::BOTTOM_LEFT ); - - // Sets the sort modifier value. - // glyphActor.SetSortModifier( visualParameters.mSortModifier ); - - // Enables or disables the blending. - // glyphActor.SetBlendMode( !visualParameters.mSnapshotModeEnabled ? BlendingMode::ON : BlendingMode::OFF ); - } -} - -void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData, TextViewRelayout::TextUnderlineStatus& textUnderlineStatus ) -{ - // Traverse the whole text to find all groups of consecutive underlined characters in the same line. - // - // Note that relayoutData.mTextLayoutInfo contains layout info per paragraph but these paragraphs are the result of split the whole text every time a '\n' is found. - // According with the layout option, one of this paragraphs could be laid-out in more than one line. - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - - std::size_t characterIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraph.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraph.mRightToLeftLayout->mWordsLayoutInfo : paragraph.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - TextViewProcessor::WordLayoutInfo& word( *wordIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt, ++characterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& character( *characterIt ); - const TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) ); - - // Check if current character is the first of a new line - const bool isNewLine = ( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) && - ( textUnderlineStatus.mCharacterGlobalIndex == ( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ).mCharacterGlobalIndex ); - if( isNewLine ) - { - ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one. - } - - if( style.IsUnderlineEnabled() ) - { - if( !textUnderlineStatus.mCurrentUnderlineStatus || // Current character is underlined but previous one it wasn't. - isNewLine ) // Current character is underlined and is the first of current line. - { - // Create a new underline info for the current underlined characters. - UnderlineInfo underlineInfo; - underlineInfo.mMaxHeight = character.mSize.height; - underlineInfo.mMaxThickness = character.mUnderlineThickness; - underlineInfo.mPosition = character.mUnderlinePosition; - - textUnderlineStatus.mUnderlineInfo.push_back( underlineInfo ); - - textUnderlineStatus.mCurrentUnderlineStatus = true; // Set the current text is underlined. - } - else - { - // Retrieve last underline info and update it if current underline thickness is bigger. - UnderlineInfo& underlineInfo( *( textUnderlineStatus.mUnderlineInfo.end() - 1u ) ); - - underlineInfo.mMaxHeight = std::max( underlineInfo.mMaxHeight, character.mSize.height ); - - if( character.mUnderlineThickness > underlineInfo.mMaxThickness ) - { - underlineInfo.mMaxThickness = character.mUnderlineThickness; - underlineInfo.mPosition = character.mUnderlinePosition; - } - } - } - else - { - textUnderlineStatus.mCurrentUnderlineStatus = false; - } - - ++textUnderlineStatus.mCharacterGlobalIndex; - } // end characters. - } // end words. - } // end paragraphs. -} - -void SetUnderlineInfo( TextView::RelayoutData& relayoutData ) -{ - // Stores for each group of consecutive underlined characters in each line its maximum thicknes, its position of that thickness and the maximum character's height. - TextViewRelayout::TextUnderlineStatus textUnderlineStatus; - - // Traverse the whole text to find all groups of consecutive underlined characters in the same line. - CalculateUnderlineInfo( relayoutData, textUnderlineStatus ); - - if( textUnderlineStatus.mUnderlineInfo.empty() ) - { - // There is no underlined text. Just exit. - return; - } - - // At this point textUnderlineStatus.mUnderlineInfo has for each group of consecutive underlined characters their maximum thickness, position and maximum height. - // Traverse the whole text and set the previously stored underline info in the text style. - - std::vector::const_iterator underlineInfoIt = textUnderlineStatus.mUnderlineInfo.begin(); - std::vector::const_iterator underlineInfoEndIt = textUnderlineStatus.mUnderlineInfo.end(); - - UnderlineInfo underlineInfo; - - if( underlineInfoIt < underlineInfoEndIt ) - { - underlineInfo = ( *underlineInfoIt ); - } - - // Whether current text is underlined. - textUnderlineStatus.mCurrentUnderlineStatus = false; - textUnderlineStatus.mCharacterGlobalIndex = 0u; - textUnderlineStatus.mLineGlobalIndex = 0u; - - float currentLineHeight = 0.f; - float currentLineAscender = 0.f; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraph( *paragraphIt ); - std::size_t characterIndex = 0u; - - const bool isRightToLeftLayout = NULL != paragraph.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraph.mRightToLeftLayout->mWordsLayoutInfo : paragraph.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = wordsLayoutInfo.begin(), wordEndIt = wordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - TextViewProcessor::WordLayoutInfo& word( *wordIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt, ++characterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& character( *characterIt ); - TextStyle& style = *( *( paragraph.mTextStyles.Begin() + characterIndex ) ); - - // Check if current character is the first of a new line - - bool isNewLine = false; - - if( textUnderlineStatus.mLineGlobalIndex < relayoutData.mLines.size() ) - { - const Toolkit::TextView::LineLayoutInfo& lineLayoutInfo( *( relayoutData.mLines.begin() + textUnderlineStatus.mLineGlobalIndex ) ); - isNewLine = ( textUnderlineStatus.mCharacterGlobalIndex == lineLayoutInfo.mCharacterGlobalIndex ); - - if( isNewLine ) - { - currentLineHeight = lineLayoutInfo.mSize.height; - currentLineAscender = lineLayoutInfo.mAscender; - ++textUnderlineStatus.mLineGlobalIndex; // If it's a new line, point to the next one. - } - } - - if( style.IsUnderlineEnabled() ) - { - if( textUnderlineStatus.mCurrentUnderlineStatus ) - { - if( isNewLine ) - { - // Retrieves the thickness and position for the next piece of underlined text. - if( underlineInfoIt < underlineInfoEndIt ) - { - ++underlineInfoIt; - if( underlineInfoIt < underlineInfoEndIt ) - { - underlineInfo = *underlineInfoIt; - } - } - } - } - - textUnderlineStatus.mCurrentUnderlineStatus = true; - - // Before setting the position it needs to be adjusted to match the base line. - const float bearingOffset = ( currentLineHeight - currentLineAscender ) - ( character.mSize.height - character.mAscender ); - const float positionOffset = ( underlineInfo.mMaxHeight - character.mSize.height ) - bearingOffset; - - // Sets the underline's parameters. - style.SetUnderline( true, underlineInfo.mMaxThickness, underlineInfo.mPosition - positionOffset ); - - // Mark the character to be set the new style into the text-actor. - character.mSetStyle = true; - } - else - { - if( textUnderlineStatus.mCurrentUnderlineStatus ) - { - textUnderlineStatus.mCurrentUnderlineStatus = false; - - // Retrieves the thickness and position for the next piece of underlined text. - if( underlineInfoIt < underlineInfoEndIt ) - { - ++underlineInfoIt; - if( underlineInfoIt < underlineInfoEndIt ) - { - underlineInfo = *underlineInfoIt; - } - } - } - } - - ++textUnderlineStatus.mCharacterGlobalIndex; - } // end of characters. - } // end of word. - } // end of paragraphs. -} - -void RemoveGlyphActors( Actor textView, - const std::vector& glyphActors ) -{ - // Removes previously inserted renderable-actors. - // The SplitByNewLineChar::Relayout(), SplitByWord::Relayout() and SplitByChar::Relayout() functions add - // renderable-actors to the text-view. A handle to these renderable-actors are stored and passed to this function - // in order to remove 'only' renderable-actors added by these functions. - // Any other actor added by a programmer or application won't be removed. - - for( std::vector::const_reverse_iterator it = glyphActors.rbegin(), endIt = glyphActors.rend(); it != endIt; ++it ) - { - textView.Remove( *it ); - } -} - -void InsertToTextView( Actor textView, - TextView::RelayoutData& relayoutData ) -{ - // Add text-actors to the text-view. - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - // Retrieve the layout info to traverse. If there is right to left text it retrieves the right to left layout. - const bool isRightToLeftLayout = NULL != paragraphLayoutInfo.mRightToLeftLayout; - TextViewProcessor::WordLayoutInfoContainer& wordsLayoutInfo = isRightToLeftLayout ? paragraphLayoutInfo.mRightToLeftLayout->mWordsLayoutInfo : paragraphLayoutInfo.mWordsLayoutInfo; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = wordsLayoutInfo.begin(), - endWordLayoutIt = wordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - if( characterLayoutInfo.mIsVisible && characterLayoutInfo.mGlyphActor ) // White spaces and '\n' characters doesn't have a text-actor. - { - //Add to the text-view. - textView.Add( characterLayoutInfo.mGlyphActor ); - relayoutData.mGlyphActors.push_back( characterLayoutInfo.mGlyphActor ); - } - } // end character - } // end words - } // end paragraphs - - for( std::vector::iterator it = relayoutData.mEllipsizedGlyphActors.begin(), - endIt = relayoutData.mEllipsizedGlyphActors.end(); - it != endIt; - ++it ) - { - RenderableActor glyphActor = ( *it ); - - //Add to the text-view. - textView.Add( glyphActor ); - relayoutData.mGlyphActors.push_back( glyphActor ); - } - relayoutData.mEllipsizedGlyphActors.clear(); -} - -RenderableActor CreateGlyphActor( const Text& text, const TextStyle& style, TextActorCache& cache ) -{ - TextActor textActor = cache.RetrieveTextActor(); - - if( textActor ) - { - // Update the text-actor. - textActor.SetText( text ); - textActor.SetTextStyle( style ); - } - else - { - // The text-actor cache is empty. Create a new one. - TextActorParameters parameters( style, TextActorParameters::FONT_DETECTION_OFF ); - textActor = TextActor::New( text, parameters ); - } - - // Exclude from size negotiation - textActor.SetRelayoutEnabled( false ); - - return textActor; -} - -} // namespace TextViewRelayout - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/relayout-utilities.h b/dali-toolkit/internal/controls/text-view/relayout-utilities.h deleted file mode 100644 index 5150186..0000000 --- a/dali-toolkit/internal/controls/text-view/relayout-utilities.h +++ /dev/null @@ -1,517 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_RELAYOUT_UTILITIES_H__ -#define __DALI_TOOLKIT_INTERNAL_RELAYOUT_UTILITIES_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -//Forward declarations. -class TextActorCache; - -namespace TextViewRelayout -{ - -extern const float MINIMUM_FADE_BOUNDARY; // When the fade boundary is the same as the text-view boundary, this constant reduces it in order to avoid a zero division. - -/** - * Define how to wrap a paragraph in lines. - */ -enum HorizontalWrapType -{ - WrapByCharacter, ///< Wrap the paragraph per character (It may split a word in two). - WrapByWord, ///< Wrap the paragraph by word. - WrapByWordAndSplit, ///< Wrap the paragraph by word and split a word if it doesn't fit. - WrapByParagraphCharacter, ///< Wrap the paragraph when a '\n' is found. - WrapByParagraphCharacterAndSplit ///< Wrap the paragraph when a '\n' is found and split if it doesn't fit. -}; - -/** - * Different types of visibility tests (text-actor - text-view). - */ -enum VisibilityTestType -{ - FULLY_VISIBLE, ///< The text-actor is completely inside the text-view. - FULLY_VISIBLE_WIDTH, ///< The text-actor is completely between the right and the left boundaries of the text-view. - FULLY_VISIBLE_HEIGHT, ///< The text-actor is completely between the top and the bottom boundaries of the text-view. - PARTIALLY_VISIBLE, ///< The text-actor is partially inside the text-view. - PARTIALLY_VISIBLE_WIDTH, ///< The text-actor is partially inside the width of the text-view. It may be completely above and bellow the top and bottom boundaries of the text-view. - PARTIALLY_VISIBLE_HEIGHT ///< The text-actor is partially inside the height of the text-view. It may be completely on the left and on the right the left and right boundaries of the text-view. -}; - -/** - * Temporary parameters used in the relayout process. - */ -struct RelayoutParameters -{ - /** - * Default constructor. - * - * Initializes all members to their defaults. - */ - RelayoutParameters(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~RelayoutParameters(); - - Vector3 mPositionOffset; ///< Offset (position.x + size.width, position.y, position.z) of the previous text-actor. - Size mParagraphSize; ///< Current paragraphs's size. - Size mWordSize; ///< Current word's size. - Size mCharacterSize; ///< Current character's size. - TextViewProcessor::TextInfoIndices mIndices; ///< Current indices to paragraph, word and character. - std::size_t mCharacterGlobalIndex; ///< Index to a single character within the whole text. - bool mIsFirstCharacter:1; ///< Whether is the first character of the whole text. - bool mIsFirstCharacterOfWord:1; ///< Whether is the first character of the word. - bool mIsNewLine:1; ///< Whether the current character is the first character of a new line. - bool mIsNewParagraphCharacter:1; ///< Whether the current character is a new paragraph character. - bool mIsWhiteSpace:1; ///< Whether the current character is a white space. - bool mIsVisible:1; ///< Whether the current character is visible. -}; - -/** - * Parameters used to calculate the gradient of text-actors when fading is enabled. - */ -struct FadeParameters -{ - /** - * Default constructor. - * - * Initializes all members to their defaults. - */ - FadeParameters(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~FadeParameters(); - - float mRightFadeBoundary; ///< Distance from the right edge of the text-view to the right edge of the fade boundary. - float mRightFadeThreshold; ///< Point from where fade out starts (by right edge). - float mRightFadeBoundaryOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - float mRightFadeThresholdOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - Vector2 mRightAlphaCoeficients; ///< The fade out rect coeficients for the right side of the text-view. - float mLeftFadeBoundary; ///< Distance from the left edge of the text-view to the left edge of the fade boundary. - float mLeftFadeThreshold; ///< Point from where fade out starts (by left edge). - float mLeftFadeBoundaryOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - float mLeftFadeThresholdOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - Vector2 mLeftAlphaCoeficients; ///< The fade out rect coeficients for the left side of the text-view. - float mTopFadeBoundary; ///< Distance from the top edge of the text-view to the top edge of the fade boundary. - float mTopFadeThreshold; ///< Point from where fade out starts (by top edge). - float mTopFadeBoundaryOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - float mTopFadeThresholdOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - Vector2 mTopAlphaCoeficients; ///< The fade out rect coeficients for the top side of the text-view. - float mBottomFadeBoundary; ///< Distance from the bottom edge of the text-view to the bottom edge of the fade boundary. - float mBottomFadeThreshold; ///< Point from where fade out starts (by bottom edge). - float mBottomFadeBoundaryOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - float mBottomFadeThresholdOffset; ///< Same as above plus an offset if the value is zero. Used to avoid a zero division. - Vector2 mBottomAlphaCoeficients; ///< The fade out rect coeficients for the bottom side of the text-view. - bool mIsPartiallyVisible:1; ///< Whether the current character is partially visible. -}; - -/** - * Parameters used to calculate the ellipsize. - */ -struct EllipsizeParameters -{ - /** - * Default constructor. - * - * Initializes all members to their defaults. - */ - EllipsizeParameters(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~EllipsizeParameters(); - - Vector3 mPosition; ///< Position of the first character of the ellipsize text. - float mLineDescender; ///< Distance from the base line to the bottom. - float mLineWidth; ///< Current line's width. - Size mEllipsizeBoundary; ///< Where to start to ellipsize a line. - std::size_t mFirstIndex; ///< Global index within the whole text of the first character of the line. - std::size_t mLastIndex; ///< Global index within the whole text of the last character of the line. - bool mEllipsizeLine:1; ///< Whether current line must be ellipsized. - bool mIsLineWidthFullyVisible:1; ///< Whether current line fits in text-view's width. - bool mIsLineHeightFullyVisible:1; ///< Whether current line fits in text-view's height. - bool mIsNextLineFullyVisibleHeight:1; ///< Whether next line fits in text-view's height. - bool mCreateEllipsizedTextActors:1; ///< Whether to create text-actors for the ellipsized text. - bool mLineFits:1; ///< Whether the current line fits in the boundary of the text-view. - bool mWordFits:1; ///< Whether the current word fits in the boundary of the text-view. -}; - -/** - * Stores underline info for a group of consecutive characters in the same line. - */ -struct UnderlineInfo -{ - /** - * Default constructor. - * - * Initializes all members to their defaults. - */ - UnderlineInfo(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~UnderlineInfo(); - - float mMaxHeight; ///< The maximum height. - float mMaxThickness; ///< The maximum underline's thickness. - float mPosition; ///< The underline's position of the character with the maximum underline's thickness. -}; - -/** - * Stores underline info for each group of consecutive underlined characters. - * It also stores some status used when traversing the whole text. - */ -struct TextUnderlineStatus -{ - /** - * Default constructor. - * - * Initializes each member to its default. - */ - TextUnderlineStatus(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~TextUnderlineStatus(); - - std::vector mUnderlineInfo; ///< Underline info for each group of consecutive underlined characters. - std::size_t mCharacterGlobalIndex; ///< Global index (within the whole text) to current character. - std::size_t mLineGlobalIndex; ///< Index to current line. It takes into account the current layout configuration (is not the number of \n) - bool mCurrentUnderlineStatus:1; ///< Whether current character is underlined. -}; - -/** - * Stores layout information of a line. - */ -struct LineLayoutInfo -{ - /** - * Default constructor. - * - * Initializes each member to its default. - */ - LineLayoutInfo(); - - /** - * Empty destructor. - * - * @note Added to increase coverage. - */ - ~LineLayoutInfo(); - - float mLineLength; ///< The length of the portion of the paragraph which fits on the text-view width. - float mMaxCharHeight; ///< The maximum height of all characters of the portion of the paragraph which fits on the text-view width. - float mMaxAscender; ///< The maximum ascender of all characters of the portion of the paragraph which fits on the text-view width. -}; - -/** - * Calculates the layout info of the portion of the paragraph which fits on the text-view width. - * - * @param[in] parentWidth Text-view width - * @param[in] indices Indices to the word and character. - * @param[in] paragraphLayoutInfo Layout info for the paragraph. - * @param[in] splitPolicy Whether a paragraph is wraped by word, by character or by word and character. - * @param[in] shrinkFactor Shrink factor used. - * @param[out] layoutInfo Layout information of the part of the paragraph which fits in the text-view width. - */ -void CalculateLineLayout( float parentWidth, - const TextViewProcessor::TextInfoIndices& indices, - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo, - HorizontalWrapType splitPolicy, - float shrinkFactor, - LineLayoutInfo& layoutInfo ); - -/** - * Reorders the text layout of each line of each paragraph of the text. - * - * @param[in,out] relayoutData The text-view's data structures. - */ -void ReorderRightToLeftLayout( TextView::RelayoutData& relayoutData ); - -/** - * Calculates the \e x offset position for the whole text. - * - * @param[in] horizontalTextAlignment The horizontal alignment type. - * @param[in] parentWidth The parent's width. - * @param[in] wholeTextWidth The whole text's width. - * @return The \e x position offset. - */ -float CalculateXoffset( Toolkit::Alignment::Type horizontalTextAlignment, float parentWidth, float wholeTextWidth ); - -/** - * Calculates the \e y offset position for the whole text. - * - * @param[in] verticalTextAlignment The vertical alignment type. - * @param[in] parentHeight The parent's height. - * @param[in] wholeTextHeight The whole text's height. - * @return The \e y position offset. - */ -float CalculateYoffset( Toolkit::Alignment::Type verticalTextAlignment, float parentHeight, float wholeTextHeight ); - -/** - * Calculates the \e x offset position for one line. - * - * @param[in] justification The line justification type. - * @param[in] wholeTextWidth The whole text's width. - * @param[in] lineLength The line's length. - * @return The \e x position offset. - * - */ -float CalculateJustificationOffset( Toolkit::TextView::LineJustification justification, float wholeTextWidth, float lineLength ); - -/** - * Whether text-actor is visible for Fade and Ellipsize exceed policies. - * - * It does different visibility tests according the given parameter \e type. @see VisibilityTestType. - * - * @param[in] position Position of the character. - * @param[in] size Size of the character. - * @param[in] parentSize Parent's size. - * @param[in] type One of FULLY_VISIBLE, PARTIALLY_VISIBLE, PARTIALLY_VISIBLE_WIDTH or PARTIALLI_VISIBLE_HEIGHT. - * @return \e true if is visible. - */ -bool IsVisible( const Vector3& position, const Size& size, const Size& parentSize, VisibilityTestType type ); - -/** - * Calculates the coeficients of the rect equation for the two given points. - * - * @param[in] p0 A point of the rect. - * @param[in] p1 Another point of the rect. - * - * @return The \e gradient is returned in the \e x member and the \e constant \e term is returned in the \e y value. - */ -Vector2 CalculateRectParameters( const Vector2& p0, const Vector2& p1 ); - -/** - * Aligns the whole text within the text-view. - * - * @param[in] layoutParameters The layout parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateAlignment( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Calculates the bearing for the given character. - * - * @param[in,out] characterLayoutInfo Character layout info. - * @param[in,out] relayoutData The text-view's data structures. - */ -void CalculateBearing( TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - TextView::RelayoutData& relayoutData ); - -/** - * Updates the character's layout info table. - * - * This table is used to pass the size, the position and other layout info to other controls/actors. - * - * @param[in,out] minMaxXY The boundary box of the whole text. - * @param[in,out] wordLayoutInfo Word layout info. - * @param[in,out] characterLayoutInfo Character layout info. - * @param[in,out] relayoutParameters Temporary layout parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateLayoutInfoTable( Vector4& minMaxXY, - TextViewProcessor::WordLayoutInfo& wordLayoutInfo, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - RelayoutParameters& relayoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Calculates the text-actor visibility and fade parameters. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] characterLayoutInfo Character layout info. - * @param[in] style The style of the character. Used to get the color (and alpha) of the character. - * @param[in,out] relayoutParameters Temporary layout parameters. - * @param[in,out] fadeParameters Temporary fade parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void CalculateVisibilityForFade( const Internal::TextView::LayoutParameters& layoutParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - const TextStyle& style, - RelayoutParameters& relayoutParameters, - FadeParameters& fadeParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Calculates the text-actor visibility and creates eliipsize text-actors. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] characterLayoutInfo Character layout info. - * @param[in,out] ellipsizeParameters Temporary ellipsize parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void CalculateVisibilityForEllipsize( const Internal::TextView::LayoutParameters& layoutParameters, - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo, - EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Creates the actors needed for the ellipsized text. - * - * @param[in,out] ellipsizeParameters Temporary ellipsize parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void CreateEllipsizeTextActor( const EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Replace the text which exceeds the boundary by the ellipsis text. - * - * @param[in] layoutParameters The layout parameters. - * @param[in,out] ellipsisParameters Temporary ellipsis parameters. - * @param[in,out] relayoutData The text-view's data structures. - */ -void EllipsizeLine( const TextView::LayoutParameters& layoutParameters, - EllipsizeParameters& ellipsizeParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Traverse all text data structure setting its visibility to true. - * - * @param[in,out] relayoutData The text-view's data structures. - */ -void SetTextVisible( TextView::RelayoutData& relayoutData ); - -/** - * Calculates the visibility and fade parameters. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateVisibilityForFade( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); -/** - * Calculates the visibility for text ellipsize. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateVisibilityForEllipsize( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); -/** - * Calculates the visibility and fade parameters. - * - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData The text-view's data structures. - */ -void UpdateVisibility( const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Traverse all text initializing all non initialized text-actor handles - * and updating text-actor handles with new size, position, ... - * - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in] createGlyphActors Whether to create RenderableActor for text-actors or emojis. - */ -void UpdateTextActorInfo( const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData, - bool createGlyphActors ); - -/** - * Traverses the whole text and for each piece of underlined text, - * it calculates the maximum thickness and the position of that particular piece of underlined text. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void CalculateUnderlineInfo( TextView::RelayoutData& relayoutData ); - -/** - * Traverses the whole text and for each piece of underlined text, - * it sets the previously calculated maximum thickness and the position of that particular piece of underlined text. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void SetUnderlineInfo( TextView::RelayoutData& relayoutData ); - -/** - * Remove renderable-actor from the text-view. - * - * @param[in,out] textView The text-view. - * @param[in] glyphActors renderable-actors to be removed from the text-view. - */ -void RemoveGlyphActors( Actor textView, - const std::vector& glyphActors ); - -/** - * Inserts the text-actors into the text-view and the text-actor's list. - * - * @param[in,out] textView The text-view. - * @param[in,out] relayoutData The text-view's data structures. - */ -void InsertToTextView( Actor textView, - TextView::RelayoutData& relayoutData ); - -/** - * Retrieves a new glyph-actor from the cache of text-actors or creating a new one if it's empty. - * - * @param[in] text The text-actor's text. - * @param[in] style The text-actor's style. - * @param[in] cache The cache of text-actors. - * - * @return a RenderableActor with the text's glyph. - */ -RenderableActor CreateGlyphActor( const Text& text, const TextStyle& style, TextActorCache& cache ); - -} // namespace TextViewRelayout - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_RELAYOUT_UTILITIES_H__ diff --git a/dali-toolkit/internal/controls/text-view/split-by-char-policies.cpp b/dali-toolkit/internal/controls/text-view/split-by-char-policies.cpp deleted file mode 100644 index 5eb829f..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-char-policies.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 2014 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 - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByChar -{ - -namespace -{ - -Vector3 NoShrinkWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - - if( ( relayoutParameters.mIsNewLine || - relayoutParameters.mIsFirstCharacter || - ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) ) ) - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - // Calculate the line length and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByCharacter, - 1.f, // Shrink factor - subLineInfo ); - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - TextViewRelayout::RelayoutParameters relayoutParameters; - - // clear - relayoutData.mCharacterLayoutInfoTable.clear(); - relayoutData.mLines.clear(); - relayoutData.mTextSizeForRelayoutOption = Size(); - - // Calculate the text size for split by char. - Vector4 minMaxXY( std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::min(), - std::numeric_limits::min() ); - - relayoutData.mShrinkFactor = 1.f; // Shrink factor used when the exceed policy contains ShrinkToFit - - relayoutParameters.mPositionOffset = Vector3::ZERO; - relayoutParameters.mIsFirstCharacter = true; - relayoutParameters.mIndices.mParagraphIndex = 0u; - relayoutParameters.mCharacterGlobalIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - relayoutParameters.mIsNewLine = true; - relayoutParameters.mParagraphSize = paragraphLayoutInfo.mSize; - relayoutParameters.mIndices.mWordIndex = 0u; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType; - relayoutParameters.mIsNewParagraphCharacter = TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType; - - relayoutParameters.mIsFirstCharacterOfWord = true; - relayoutParameters.mWordSize = wordLayoutInfo.mSize; - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - relayoutParameters.mCharacterSize = characterLayoutInfo.mSize; - - switch( layoutParameters.mExceedPolicy ) - { - case TextView::OriginalShrink: - case TextView::SplitOriginal: - case TextView::SplitFade: - case TextView::SplitEllipsizeEnd: - case TextView::SplitShrink: - case TextView::ShrinkOriginal: - case TextView::ShrinkFade: - case TextView::Shrink: - case TextView::EllipsizeEndOriginal: - case TextView::EllipsizeEnd: // Fall Through - { - DALI_LOG_WARNING( "SplitByChar::CalculateSizeAndPosition() policy not implemented.\n" ); - break; - } - case TextView::OriginalFade: - case TextView::FadeOriginal: - case TextView::Original: - case TextView::Fade: // Fall Through - { - characterLayoutInfo.mPosition = NoShrinkWhenExceedPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f ); - break; - } - default: - { - DALI_LOG_WARNING( "SplitByChar::CalculateSizeAndPosition() policy combination not possible.\n" ); - } - } - - // Get last line info and calculate the bearing (used to align glyphs with the baseline). - TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData ); - - // updates min and max position to calculate the text size for split by char. - TextViewRelayout::UpdateLayoutInfoTable( minMaxXY, - wordLayoutInfo, - characterLayoutInfo, - relayoutParameters, - relayoutData ); - - ++relayoutParameters.mCharacterGlobalIndex; - relayoutParameters.mIsFirstCharacter = false; - relayoutParameters.mIsNewLine = false; - } // end characters - } // end words - } // end paragraphs - - if( relayoutData.mCharacterLayoutInfoTable.empty() ) - { - relayoutData.mTextSizeForRelayoutOption = Size(); - } - else - { - relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x; - relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y; - } - - // Check if the last character is a new paragraph character. In that case the height should be added. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( paragraphLayoutInfo.mWordsLayoutInfo.empty() ) // if it's empty, it means the last character is a new paragraph character. - { - relayoutData.mTextSizeForRelayoutOption.height += paragraphLayoutInfo.mSize.height; - } - } -} - -} // namespace - -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION ) - { - CalculateSizeAndPosition( layoutParameters, - relayoutData ); - - TextViewRelayout::ReorderRightToLeftLayout( relayoutData ); - - TextViewRelayout::SetUnderlineInfo( relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT ) - { - TextViewRelayout::UpdateAlignment( layoutParameters, - relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY ) - { - TextViewRelayout::UpdateVisibility( layoutParameters, - visualParameters, - relayoutData ); - } - - const bool initializeTextActors = relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS; - const bool updateTextActors = relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE; - if( initializeTextActors || updateTextActors ) - { - TextViewRelayout::UpdateTextActorInfo( visualParameters, - relayoutData, - initializeTextActors ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) - { - TextViewRelayout::InsertToTextView( textView, - relayoutData ); - } -} - -} // namespace SplitByChar - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/split-by-char-policies.h b/dali-toolkit/internal/controls/text-view/split-by-char-policies.h deleted file mode 100644 index a0624ca..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-char-policies.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_SPLIT_BY_CHAR_POLICIES_H__ -#define __DALI_TOOLKIT_INTERNAL_SPLIT_BY_CHAR_POLICIES_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByChar -{ - -/** - * Sets text-actor's size and position accordingly with the given text-view's size and layout parameters. - * Visible text-actors are added to the text-view. Non visible actors are not added. - * - * @param[in] textView The handle to the text-view actor. - * @param[in] relayoutOperationMask Mask which defines which operations need to be done in the relayout process. - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in] relayoutData The text-view's data structures which are modified by this function. - */ -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); - -} // namespace SplitByChar - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_SPLIT_BY_CHAR_POLICIES_H__ diff --git a/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.cpp b/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.cpp deleted file mode 100644 index f74966d..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2014 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 - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByNewLineChar -{ - -namespace -{ - -Vector3 SplitPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - - if( relayoutParameters.mIsNewLine || - relayoutParameters.mIsFirstCharacter || - ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) ) - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByParagraphCharacterAndSplit, - 1.f, // Shrink factor - subLineInfo ); - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // clear - relayoutData.mCharacterLayoutInfoTable.clear(); - relayoutData.mLines.clear(); - relayoutData.mTextSizeForRelayoutOption = Size(); - relayoutData.mShrinkFactor = 1.f; - - // Calculates the text size for split by char. - Vector4 minMaxXY( std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::min(), - std::numeric_limits::min() ); - - TextViewRelayout::RelayoutParameters relayoutParameters; - - if( TextView::ShrinkOriginal == layoutParameters.mExceedPolicy ) - { - if( relayoutData.mTextLayoutInfo.mWholeTextSize.width > relayoutData.mTextViewSize.width ) - { - relayoutData.mShrinkFactor = relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mWholeTextSize.width; - } - } - else if( TextView::Shrink == layoutParameters.mExceedPolicy ) - { - if( ( relayoutData.mTextLayoutInfo.mWholeTextSize.width > relayoutData.mTextViewSize.width ) || - ( relayoutData.mTextLayoutInfo.mWholeTextSize.height > relayoutData.mTextViewSize.height ) ) - { - relayoutData.mShrinkFactor = std::min( relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mWholeTextSize.width, - relayoutData.mTextViewSize.height / relayoutData.mTextLayoutInfo.mWholeTextSize.height ); - } - } - - relayoutParameters.mIsFirstCharacter = true; - relayoutParameters.mIndices.mParagraphIndex = 0u; - relayoutParameters.mPositionOffset = Vector3::ZERO; - relayoutParameters.mCharacterGlobalIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - relayoutParameters.mParagraphSize = paragraphLayoutInfo.mSize * relayoutData.mShrinkFactor; - - relayoutParameters.mIsNewLine = true; - relayoutParameters.mIndices.mWordIndex = 0u; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType; - relayoutParameters.mIsNewParagraphCharacter = TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType; - - relayoutParameters.mIsFirstCharacterOfWord = true; - relayoutParameters.mWordSize = wordLayoutInfo.mSize; - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - characterLayoutIt != endCharacterLayoutIt; - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - relayoutParameters.mCharacterSize = characterLayoutInfo.mSize; - - relayoutParameters.mCharacterSize = characterLayoutInfo.mSize; - - switch( layoutParameters.mExceedPolicy ) - { - case TextView::OriginalShrink: - case TextView::SplitShrink: - case TextView::ShrinkFade: // Fall Through - { - DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() policy not implemented.\n" ); - break; - } - case TextView::Original: // Fall Through - case TextView::ShrinkOriginal: // Fall Through - case TextView::Shrink: // Fall Through - case TextView::OriginalFade: // Fall Through - case TextView::FadeOriginal: // Fall Through - case TextView::Fade: // Fall Through - case TextView::EllipsizeEndOriginal: // Fall Through - case TextView::EllipsizeEnd: // Fall Through - { - if( relayoutParameters.mIsNewLine ) - { - relayoutParameters.mPositionOffset.x = 0.f; - relayoutParameters.mPositionOffset.y += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor; - } - - characterLayoutInfo.mPosition = relayoutParameters.mPositionOffset; - - relayoutParameters.mPositionOffset.x += characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor; - - if( relayoutParameters.mIsNewLine || - relayoutParameters.mIsFirstCharacter ) - { - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = relayoutParameters.mParagraphSize; // Size of this piece of paragraph. - lineInfo.mAscender = paragraphLayoutInfo.mAscender * relayoutData.mShrinkFactor; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - } - break; - } - case TextView::SplitOriginal: - case TextView::SplitFade: - case TextView::SplitEllipsizeEnd: // Fall Through - { - characterLayoutInfo.mPosition = SplitPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f ); - break; - } - default: - { - DALI_LOG_WARNING( "SplitByNewLineChar::CalculateSizeAndPosition() Layout configuration not possible.\n" ); - break; - } - } - - // Get last line info and calculate the bearing (used to align glyphs with the baseline). - TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData ); - - // updates min and max position to calculate the text size for split by new line char. - TextViewRelayout::UpdateLayoutInfoTable( minMaxXY, - wordLayoutInfo, - characterLayoutInfo, - relayoutParameters, - relayoutData ); - - ++relayoutParameters.mCharacterGlobalIndex; - relayoutParameters.mIsFirstCharacter = false; - relayoutParameters.mIsNewLine = false; - } // end characters - } // end words - } // end paragraphs - - if( relayoutData.mCharacterLayoutInfoTable.empty() ) - { - relayoutData.mTextSizeForRelayoutOption = Size(); - } - else - { - relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x; - relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y; - } - - // Check if the last character is a new paragraph character. In that case the height should be added. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( paragraphLayoutInfo.mWordsLayoutInfo.empty() ) // if it's empty, it means the last character is a new paragraph character. - { - relayoutData.mTextSizeForRelayoutOption.height += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor; - } - } -} - -} // namespace - -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION ) - { - CalculateSizeAndPosition( layoutParameters, - relayoutData ); - - TextViewRelayout::ReorderRightToLeftLayout( relayoutData ); - - TextViewRelayout::SetUnderlineInfo( relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT ) - { - TextViewRelayout::UpdateAlignment( layoutParameters, - relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY ) - { - TextViewRelayout::UpdateVisibility( layoutParameters, - visualParameters, - relayoutData ); - } - - const bool initializeTextActors = relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS; - const bool updateTextActors = relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE; - if( initializeTextActors || updateTextActors ) - { - TextViewRelayout::UpdateTextActorInfo( visualParameters, - relayoutData, - initializeTextActors ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) - { - TextViewRelayout::InsertToTextView( textView, - relayoutData ); - } -} - -} // namespace SplitByNewLineChar - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h b/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h deleted file mode 100644 index 4869d60..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-new-line-char-policies.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_SPLIT_BY_NEW_LINE_CHAR_POLICIES_H__ -#define __DALI_TOOLKIT_INTERNAL_SPLIT_BY_NEW_LINE_CHAR_POLICIES_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByNewLineChar -{ - -/** - * Sets text-actor's size and position accordingly with the given text-view's size and layout parameters. - * Visible text-actors are added to the text-view. Non visible actors are not added. - * - * @param[in] textView The handle to the text-view actor. - * @param[in] relayoutOperationMask Mask which defines which operations need to be done in the relayout process. - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in] relayoutData The text-view's data structures which are modified by this function. - */ -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); - -} // namespace SplitByNewLineChar - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_SPLIT_BY_NEW_LINE_CHAR_POLICIES_H__ diff --git a/dali-toolkit/internal/controls/text-view/split-by-word-policies.cpp b/dali-toolkit/internal/controls/text-view/split-by-word-policies.cpp deleted file mode 100644 index b5bd9f6..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-word-policies.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/* - * Copyright (c) 2014 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 - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByWord -{ - -namespace -{ - -Vector3 OriginalPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - - if( relayoutParameters.mIsNewLine || - relayoutParameters.mIsFirstCharacter || - ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + relayoutParameters.mWordSize.width > relayoutData.mTextViewSize.width ) ) ) - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - // Calculates the length of the portion of the paragraph which doesn't exceed the text-view's width and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByWord, - 1.f, // Shrink factor - subLineInfo ); - - if( subLineInfo.mLineLength < Math::MACHINE_EPSILON_1000 ) - { - // It may mean there is a word which is actually longer than the width of the text-view. - // In that case the length of this word is needed. - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - const TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + relayoutParameters.mIndices.mWordIndex ) ); - subLineInfo.mLineLength = wordLayoutInfo.mSize.width; - } - } - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -/** - * Calculates character position. - * @param[in] relayoutParameters Temporary layout parameters (previous size, previous position, ... ) - * @param[in] layoutParameters The layout parameters. - * @param[in] relayoutData The text-view's data structures. - * @return The character's position. - */ -Vector3 SplitWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - - if( ( relayoutParameters.mIsNewLine || relayoutParameters.mIsFirstCharacter ) || - ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + relayoutParameters.mWordSize.width > relayoutData.mTextViewSize.width ) ) || - ( wordOffset + relayoutParameters.mCharacterSize.width > relayoutData.mTextViewSize.width ) ) - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - // Calculates the line length and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByWordAndSplit, - 1.f, // Shrink factor. - subLineInfo ); - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -/** - * Calculates character position. - * @param[in] relayoutParameters Temporary layout parameters (previous size, previous position, ... ) - * @param[in] layoutParameters The layout parameters. - * @param[in] relayoutData The text-view's data structures. - * @return The character's position. - */ -Vector3 ShrinkWidthWhenExceedPosition( const TextViewRelayout::RelayoutParameters& relayoutParameters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - const float wordOffset = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.x ); - const float previousPositionY = ( relayoutParameters.mIsFirstCharacter ? 0.f : relayoutParameters.mPositionOffset.y ); - const Size wordSize = relayoutParameters.mWordSize * relayoutData.mShrinkFactor; - - if( ( relayoutParameters.mIsNewLine || relayoutParameters.mIsFirstCharacter ) || // isNewLine is true when '\n' is found. - ( relayoutParameters.mIsFirstCharacterOfWord && ( wordOffset + wordSize.width > relayoutData.mTextViewSize.width ) ) ) // The word doesn't fit in the parent width. - { - if( !relayoutParameters.mIsNewLine && - ( relayoutParameters.mIsWhiteSpace || relayoutParameters.mIsNewParagraphCharacter ) ) - { - // Current character is a white space. Don't want to move a white space to the next line. - // These white spaces are placed just in the edge. - return Vector3( relayoutData.mTextViewSize.width - relayoutParameters.mWordSize.width, relayoutParameters.mPositionOffset.y, 0.f ); - } - else - { - // Calculates the line length and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + relayoutParameters.mIndices.mParagraphIndex ) ); - - TextViewRelayout::CalculateLineLayout( relayoutData.mTextViewSize.width, - relayoutParameters.mIndices, - paragraphLayoutInfo, - TextViewRelayout::WrapByWord, - relayoutData.mShrinkFactor, - subLineInfo ); - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = relayoutParameters.mCharacterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - - return Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * relayoutData.mShrinkFactor, 0.f ); - } - } - else - { - return Vector3( wordOffset, previousPositionY, 0.f ); - } -} - -void CalculatePositionsForShrinkWhenExceed( TextView::RelayoutData& relayoutData, - const TextView::LayoutParameters& layoutParameters, - const float shrinkFactor, - float& newTextHeight ) -{ - const float parentWidth = relayoutData.mTextViewSize.width; - TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo; - - // Reset the text height. This value is returned in order to shrink further or not the text. - newTextHeight = 0.f; - - // Whether the first character is being processed. - bool isFirstChar = true; - - // Stores the size of the previous character. - Size previousSize; - // Stores the position of the previous character. - Vector3 previousPosition; - - // Reset the index of paragraphs. - TextViewProcessor::TextInfoIndices indices; - - // Whether the last character of the whole text is a new paragraph char. - // This information is used to increase or not the height of the whole text by one line. - // Increase the whole text's height by one line is useful i.e. in TextInput to place the cursor - // after pressing 'Enter' in the last paragraph. - bool isLastCharacterNewParagraphChar = false; - // Stores the height of the last character. This height used to be added to the whole text height if - // isLastCharacterNewParagraphChar is true. - float lastCharHeight = 0.f; - - relayoutData.mLines.clear(); - std::size_t characterGlobalIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt, ++indices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt ); - - // The next character is in a new line. - bool isNewLine = true; - - // Reset the index of words. - indices.mWordIndex = 0u; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt, ++indices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordIt ); - - // Reset the index of the character. - indices.mCharacterIndex = 0u; - - // Whether current character is the first of the word. - bool isFirstCharOfWord = true; - const float wordOffset = previousPosition.x + previousSize.width; - - isLastCharacterNewParagraphChar = ( TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType ); - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator charIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), charEndIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - charIt != charEndIt; - ++charIt, ++indices.mCharacterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *charIt ); - lastCharHeight = characterLayoutInfo.mSize.height * shrinkFactor; - - const float previousPositionY = isFirstChar ? 0.f : previousPosition.y; - - if( ( isNewLine || isFirstChar ) || - ( isFirstCharOfWord && ( wordOffset + wordLayoutInfo.mSize.width * shrinkFactor > parentWidth ) ) ) - { - isFirstChar = false; - - // Calculates the line length and the max character height for the current line. - TextViewRelayout::LineLayoutInfo subLineInfo; - subLineInfo.mLineLength = 0.f; - subLineInfo.mMaxCharHeight = 0.f; - subLineInfo.mMaxAscender = 0.f; - TextViewRelayout::CalculateLineLayout( parentWidth, - indices, - paragraphLayoutInfo, - TextViewRelayout::WrapByWord, - shrinkFactor, - subLineInfo ); - - characterLayoutInfo.mPosition = Vector3( 0.f, previousPositionY + subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor, 0.f ); - - newTextHeight += subLineInfo.mMaxCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor; - - Toolkit::TextView::LineLayoutInfo lineInfo; - lineInfo.mCharacterGlobalIndex = characterGlobalIndex; // Index to the first character of the next line. - lineInfo.mSize = Size( subLineInfo.mLineLength, subLineInfo.mMaxCharHeight ); // Size of this piece of paragraph. - lineInfo.mAscender = subLineInfo.mMaxAscender; // Ascender of this piece of paragraph. - relayoutData.mLines.push_back( lineInfo ); - } - else - { - characterLayoutInfo.mPosition = previousPosition + Vector3( previousSize.width, 0.f, 0.f ); - } - - // Get last line info and calculate the bearing. - const Toolkit::TextView::LineLayoutInfo& lineInfo( *( relayoutData.mLines.end() - 1u ) ); - const float bearingOffset = ( ( lineInfo.mSize.height - lineInfo.mAscender ) - ( characterLayoutInfo.mSize.height - characterLayoutInfo.mAscender ) ) * shrinkFactor; - - previousSize = characterLayoutInfo.mSize * shrinkFactor; - previousPosition = characterLayoutInfo.mPosition; - characterLayoutInfo.mPosition.y -= bearingOffset; - isFirstCharOfWord = false; - isNewLine = false; - - ++characterGlobalIndex; - } - } - } - - if( isLastCharacterNewParagraphChar ) - { - newTextHeight += lastCharHeight + layoutParameters.mLineHeightOffset * shrinkFactor; - } -} - -float RelayoutForShrinkToFit( TextView::RelayoutData& relayoutData, - const TextView::LayoutParameters& layoutParameters ) -{ - const Size& textViewSize = relayoutData.mTextViewSize; - TextViewProcessor::TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo; - - // First step is assure the longest word fits in the text view width. - float shrinkFactor = ( textLayoutInfo.mMaxWordWidth > textViewSize.width ? textViewSize.width / textLayoutInfo.mMaxWordWidth : 1.f ); - - // Out parameter. Will store the new text height after relayout the text. - float newTextHeight = 0.f; - - // Relayout the text for the given character's sizes. - CalculatePositionsForShrinkWhenExceed( relayoutData, - layoutParameters, - shrinkFactor, - newTextHeight ); - - if( newTextHeight > textViewSize.height ) - { - // After relayouting, the text exceeds the text view height. - // Find a new scale factor to fit all the text in the text view size is needed. - - // The next algorithm does some iterations to calculate an acceptable scale factor. - // Some magic numbers are defined. - - const float MIN_RATIO( 0.90f ); // The algorithm finishes if the ratio - const float MAX_RATIO( 1.00f ); // new_text_height / text_view_height is between this two values - const unsigned int MAX_ITERATIONS( 8u ); // or max_iteration is reached. - - float ratio = newTextHeight / textViewSize.height; - - float maxScaleFactor = shrinkFactor; // bigger scale factors than maxScaleFactor will produce a too big text. - float minScaleFactor = shrinkFactor * ( textViewSize.height / newTextHeight ); // smaller scale factors than minScaleFactor will produce a too small text. - - for( unsigned int iterations = 0u; ( ( MIN_RATIO > ratio ) || ( ratio > MAX_RATIO ) ) && ( iterations < MAX_ITERATIONS ); ++iterations ) - { - // Calculates the new scale factor. - // The new scale factor is always between the min and max scale factors. - // If ratio < 1 it means the text is too small and a bigger scale factor is needed. In this case the algorithm selects a new scale factor close to - // minScaleFactor. Alternatively if the text is too big a new scale factor close to maxScaleFactor is selected. - // This allows the text shrink or grow smoothly. - shrinkFactor = minScaleFactor + ( ratio < 1.f ? 0.4f : 0.6f ) * ( maxScaleFactor - minScaleFactor ); - - CalculatePositionsForShrinkWhenExceed( relayoutData, // Relayout the text for the given character's sizes. - layoutParameters, - shrinkFactor, - newTextHeight ); - - // Calculates the new text size ratio. It allows update the min and max scale factors. - // If the ratio is not good enough a new scale factor between min and max could be used in next iteration. - ratio = newTextHeight / textViewSize.height; - if( ratio < 1.f ) - { - minScaleFactor = shrinkFactor; - } - else - { - maxScaleFactor = shrinkFactor; - } - } - - if( ratio > MAX_RATIO ) - { - // The algorithm didn't find an acceptable scale factor. - // In that case the text is shrunk to fit in the boundaries of the text view actor. - shrinkFactor = minScaleFactor; - - CalculatePositionsForShrinkWhenExceed( relayoutData, - layoutParameters, - shrinkFactor, - newTextHeight ); - } - } - - return shrinkFactor; -} - -void CalculateSizeAndPosition( const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - TextViewRelayout::RelayoutParameters relayoutParameters; - - // clear - relayoutData.mCharacterLayoutInfoTable.clear(); - relayoutData.mLines.clear(); - relayoutData.mTextSizeForRelayoutOption = Size(); - - // Calculates the text size for split by char. - Vector4 minMaxXY( std::numeric_limits::max(), - std::numeric_limits::max(), - std::numeric_limits::min(), - std::numeric_limits::min() ); - - relayoutData.mShrinkFactor = 1.f; // Shrink factor used when the exceed policy contains ShrinkToFit - - if( TextView::Shrink == layoutParameters.mExceedPolicy ) - { - // Relays-out the text for the shrink to fit policy. - relayoutData.mShrinkFactor = RelayoutForShrinkToFit( relayoutData, layoutParameters ); - } - else if( TextView::ShrinkOriginal == layoutParameters.mExceedPolicy ) - { - relayoutData.mShrinkFactor = ( relayoutData.mTextLayoutInfo.mMaxWordWidth > relayoutData.mTextViewSize.width ? relayoutData.mTextViewSize.width / relayoutData.mTextLayoutInfo.mMaxWordWidth : 1.f ); - } - - relayoutParameters.mPositionOffset = Vector3::ZERO; - relayoutParameters.mIsFirstCharacter = true; - relayoutParameters.mIndices.mParagraphIndex = 0u; - relayoutParameters.mCharacterGlobalIndex = 0u; - - for( TextViewProcessor::ParagraphLayoutInfoContainer::iterator paragraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), - endParagraphLayoutIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphLayoutIt != endParagraphLayoutIt; - ++paragraphLayoutIt, ++relayoutParameters.mIndices.mParagraphIndex ) - { - TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphLayoutIt ); - - relayoutParameters.mIsNewLine = true; - relayoutParameters.mParagraphSize = paragraphLayoutInfo.mSize; - relayoutParameters.mIndices.mWordIndex = 0u; - - for( TextViewProcessor::WordLayoutInfoContainer::iterator wordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), - endWordLayoutIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - wordLayoutIt != endWordLayoutIt; - ++wordLayoutIt, ++relayoutParameters.mIndices.mWordIndex ) - { - TextViewProcessor::WordLayoutInfo& wordLayoutInfo( *wordLayoutIt ); - relayoutParameters.mIsWhiteSpace = TextViewProcessor::WordSeparator == wordLayoutInfo.mType; - relayoutParameters.mIsNewParagraphCharacter = TextViewProcessor::ParagraphSeparator == wordLayoutInfo.mType; - - relayoutParameters.mIsFirstCharacterOfWord = true; - relayoutParameters.mWordSize = wordLayoutInfo.mSize; - relayoutParameters.mIndices.mCharacterIndex = 0u; - - for( TextViewProcessor::CharacterLayoutInfoContainer::iterator characterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endCharacterLayoutIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - ( characterLayoutIt != endCharacterLayoutIt ); - ++characterLayoutIt, ++relayoutParameters.mIndices.mCharacterIndex ) - { - TextViewProcessor::CharacterLayoutInfo& characterLayoutInfo( *characterLayoutIt ); - - relayoutParameters.mCharacterSize = characterLayoutInfo.mSize; - - switch( layoutParameters.mExceedPolicy ) - { - case TextView::OriginalShrink: - case TextView::SplitShrink: - case TextView::ShrinkFade: - { - DALI_LOG_WARNING( "SplitByWord::CalculateSizeAndPosition() policy not implemented.\n" ); - break; - } - case TextView::Original: - case TextView::OriginalFade: - case TextView::FadeOriginal: - case TextView::Fade: - case TextView::EllipsizeEndOriginal: - case TextView::EllipsizeEnd: // Fall Through - { - characterLayoutInfo.mPosition = OriginalPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f ); - break; - } - case TextView::SplitOriginal: - case TextView::SplitFade: - case TextView::SplitEllipsizeEnd: - { - characterLayoutInfo.mPosition = SplitWhenExceedPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width, 0.f, 0.f ); - break; - } - case TextView::ShrinkOriginal: - { - characterLayoutInfo.mPosition = ShrinkWidthWhenExceedPosition( relayoutParameters, - layoutParameters, - relayoutData ); - - relayoutParameters.mPositionOffset = characterLayoutInfo.mPosition + Vector3( characterLayoutInfo.mSize.width * relayoutData.mShrinkFactor, 0.f, 0.f ); - break; - } - case TextView::Shrink: - { - // Does nothing. All the job has been done in the RelayoutForShrinkToFit() function. - break; - } - default: - { - DALI_LOG_WARNING( "SplitByWord::CalculateSizeAndPosition() policy combination not possible.\n" ); - } - } - - // Get last line info and calculate the bearing (used to align glyphs with the baseline). - if( TextView::Shrink != layoutParameters.mExceedPolicy ) - { - TextViewRelayout::CalculateBearing( characterLayoutInfo, relayoutData ); - } - - // updates min and max position to calculate the text size for split by word. - TextViewRelayout::UpdateLayoutInfoTable( minMaxXY, - wordLayoutInfo, - characterLayoutInfo, - relayoutParameters, - relayoutData ); - - ++relayoutParameters.mCharacterGlobalIndex; - relayoutParameters.mIsFirstCharacter = false; - relayoutParameters.mIsFirstCharacterOfWord = false; - relayoutParameters.mIsNewLine = false; - } // end characters - } // end words - } // end paragraphs - - if( relayoutData.mCharacterLayoutInfoTable.empty() ) - { - relayoutData.mTextSizeForRelayoutOption = Size(); - } - else - { - relayoutData.mTextSizeForRelayoutOption.width = minMaxXY.z - minMaxXY.x; - relayoutData.mTextSizeForRelayoutOption.height = minMaxXY.w - minMaxXY.y; - } - - // Check if the last character is a new paragraph character. In that case the height should be added. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - const TextViewProcessor::ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( paragraphLayoutInfo.mWordsLayoutInfo.empty() ) // if it's empty, it means the last character is a new paragraph character. - { - relayoutData.mTextSizeForRelayoutOption.height += paragraphLayoutInfo.mSize.height * relayoutData.mShrinkFactor; - } - } -} - -} // namespace - -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ) -{ - if( relayoutOperationMask & TextView::RELAYOUT_SIZE_POSITION ) - { - CalculateSizeAndPosition( layoutParameters, - relayoutData ); - - TextViewRelayout::ReorderRightToLeftLayout( relayoutData ); - - TextViewRelayout::SetUnderlineInfo( relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_ALIGNMENT ) - { - TextViewRelayout::UpdateAlignment( layoutParameters, - relayoutData ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_VISIBILITY ) - { - TextViewRelayout::UpdateVisibility( layoutParameters, - visualParameters, - relayoutData ); - } - const bool initializeTextActors = relayoutOperationMask & TextView::RELAYOUT_INITIALIZE_TEXT_ACTORS; - const bool updateTextActors = relayoutOperationMask & TextView::RELAYOUT_TEXT_ACTOR_UPDATE; - if( initializeTextActors || updateTextActors ) - { - TextViewRelayout::UpdateTextActorInfo( visualParameters, - relayoutData, - initializeTextActors ); - } - - if( relayoutOperationMask & TextView::RELAYOUT_INSERT_TO_TEXT_VIEW ) - { - TextViewRelayout::InsertToTextView( textView, - relayoutData ); - } -} - -} // namespace SplitByWord - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/split-by-word-policies.h b/dali-toolkit/internal/controls/text-view/split-by-word-policies.h deleted file mode 100644 index df4ce3a..0000000 --- a/dali-toolkit/internal/controls/text-view/split-by-word-policies.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_SPLIT_BY_WORD_POLICIES_H__ -#define __DALI_TOOLKIT_INTERNAL_SPLIT_BY_WORD_POLICIES_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace SplitByWord -{ - -/** - * Sets text-actor's size and position accordingly with the given text-view's size and layout parameters. - * Visible text-actors are added to the text-view. Non visible actors are not added. - * - * @param[in] textView The handle to the text-view actor. - * @param[in] relayoutOperationMask Mask which defines which operations need to be done in the relayout process. - * @param[in] layoutParameters The layout parameters. - * @param[in] visualParameters Some visual parameters (fade, sort modifier and blending). - * @param[in] relayoutData The text-view's data structures which are modified by this function. - */ -void Relayout( Actor textView, - TextView::RelayoutOperationMask relayoutOperationMask, - const TextView::LayoutParameters& layoutParameters, - const TextView::VisualParameters& visualParameters, - TextView::RelayoutData& relayoutData ); - -} // namespace SplitByWord - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_SPLIT_BY_WORD_POLICIES_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-actor-cache.cpp b/dali-toolkit/internal/controls/text-view/text-actor-cache.cpp deleted file mode 100644 index f33cccc..0000000 --- a/dali-toolkit/internal/controls/text-view/text-actor-cache.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// CLASS HEADER -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -TextActorCache::TextActorCache() -: mTextActors() -{ -} - -TextActorCache::~TextActorCache() -{ -} - -void TextActorCache::InsertTextActors( const std::vector& textActors ) -{ - mTextActors.insert( mTextActors.end(), textActors.rbegin(), textActors.rend() ); -} - -TextActor TextActorCache::RetrieveTextActor() -{ - // Text-actors are inserted in the order needed to retrieve always the last one. - - // Returns a non initialized handle if the cache is empty. - TextActor textActor; - - if( !mTextActors.empty() ) - { - textActor = mTextActors.back(); - mTextActors.pop_back(); - } - - return textActor; -} - -void TextActorCache::ClearTexts() -{ - for( std::vector::iterator it = mTextActors.begin(); it != mTextActors.end(); ++it ) - { - (*it).SetText(""); - } -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-actor-cache.h b/dali-toolkit/internal/controls/text-view/text-actor-cache.h deleted file mode 100644 index c826c27..0000000 --- a/dali-toolkit/internal/controls/text-view/text-actor-cache.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_ACTOR_CACHE_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_ACTOR_CACHE_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * Stores text-actors to be reused. - * - * Is it asumed that the first text-actor of a group of text-actors added to the cache is the first one to be rehused. - */ -class TextActorCache -{ - -public: - /** - * Default constructor. - */ - TextActorCache(); - - /** - * Destructor. - */ - ~TextActorCache(); - - /** - * Inserts the given text-actors into the cache. - * - * First text-actor of the vector is the first one to be reused. - * - * @param[in] textActors The text-actors to be inserted into the cache. - */ - void InsertTextActors( const std::vector& textActors ); - - /** - * Retrieves a text-actor from the cache. - * - * @return A handle to a text-actor. It returns a non initialized handle if the cache has no text-actors. - */ - TextActor RetrieveTextActor(); - - /** - * Clears the text of the text-actor in the cache. - */ - void ClearTexts(); - -private: - std::vector mTextActors; ///< Stores cached text-actors. -}; - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_ACTOR_CACHE_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp b/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp deleted file mode 100644 index d6b4146..0000000 --- a/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2014 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 - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ - -BidirectionalParagraphInfo::BidirectionalParagraphInfo() -: mDirection( FRIBIDI_TYPE_ON ), - mCharactersTypeBuffer(), - mLevelsBuffer(), - mLogicalUnicodeBuffer() -{ -} - -BidirectionalParagraphInfo::~BidirectionalParagraphInfo() -{ -} - -BidirectionalParagraphInfo::BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info ) -: mDirection( info.mDirection ), - mCharactersTypeBuffer( info.mCharactersTypeBuffer ), - mLevelsBuffer( info.mLevelsBuffer ), - mLogicalUnicodeBuffer( info.mLogicalUnicodeBuffer ) -{ -} - -BidirectionalParagraphInfo& BidirectionalParagraphInfo::operator=( const BidirectionalParagraphInfo& info ) -{ - if( this != &info ) - { - mDirection = info.mDirection; - mCharactersTypeBuffer = info.mCharactersTypeBuffer; - mLevelsBuffer = info.mLevelsBuffer; - mLogicalUnicodeBuffer = info.mLogicalUnicodeBuffer; - } - - return *this; -} - -bool BidirectionalParagraphInfo::IsRightToLeftParagraph() const -{ - bool isRightToLeft = false; - - switch( mDirection ) - { - case FRIBIDI_PAR_LTR: // Left-To-Right paragraph. - case FRIBIDI_PAR_ON: // DirectiOn-Neutral paragraph. - case FRIBIDI_PAR_WLTR: // Weak Left To Right paragraph. - { - isRightToLeft = false; - break; - } - case FRIBIDI_PAR_RTL: // Right-To-Left paragraph. - case FRIBIDI_PAR_WRTL: // Weak Right To Left paragraph. - { - isRightToLeft = true; - break; - } - } - - return isRightToLeft; -} - -BidirectionalLineInfo::BidirectionalLineInfo() -: mCharacterParagraphIndex(), - mNumberOfCharacters(), - mText(), - mVisualToLogicalMap(), - mLogicalToVisualMap() -{ -} - -BidirectionalLineInfo::~BidirectionalLineInfo() -{ -} - -BidirectionalLineInfo::BidirectionalLineInfo( const BidirectionalLineInfo& info ) -: mCharacterParagraphIndex( info.mCharacterParagraphIndex ), - mNumberOfCharacters( info.mNumberOfCharacters ), - mText( info.mText ), - mVisualToLogicalMap( info.mVisualToLogicalMap ), - mLogicalToVisualMap( info.mLogicalToVisualMap ) -{ -} - -BidirectionalLineInfo& BidirectionalLineInfo::operator=( const BidirectionalLineInfo& info ) -{ - if( this != &info ) - { - mCharacterParagraphIndex = info.mCharacterParagraphIndex; - mNumberOfCharacters = info.mNumberOfCharacters; - mText = info.mText; - mVisualToLogicalMap = info.mVisualToLogicalMap; - mLogicalToVisualMap = info.mLogicalToVisualMap; - } - - return *this; -} - -bool BeginsRightToLeftCharacter( const Text& text ) -{ - for( size_t i = 0u, length = text.GetLength(); i < length; ++i ) - { - Character::CharacterDirection direction = text[i].GetCharacterDirection(); - if( direction != Character::Neutral ) - { - return ( direction == Character::RightToLeft || direction == Character::RightToLeftWeak ); - } - } - - return false; -} - -bool ContainsRightToLeftCharacter( const Dali::Text& text ) -{ - for( size_t i = 0u, length = text.GetLength(); i < length; ++i ) - { - Character::CharacterDirection direction = ( text[i] ).GetCharacterDirection(); - if( ( Character::RightToLeft == direction ) || ( Character::RightToLeftWeak == direction ) ) - { - return true; - } - } - - return false; -} - -void ProcessBidirectionalText( Text& paragraph, BidirectionalParagraphInfo* info ) -{ - if( paragraph.IsEmpty() ) - { - // nothing to do if the paragraph is empty. - return; - } - - const std::size_t stringSize = paragraph.GetText().size(); - - // Text buffer in logical order. Coded in unicode. - info->mLogicalUnicodeBuffer.resize( stringSize + 1u, 0u ); - FriBidiChar* logicalUnicodeBufferPointer = &info->mLogicalUnicodeBuffer[0u]; - - // Converts from utf8 to unicode. - const std::size_t length = fribidi_charset_to_unicode( FRIBIDI_CHAR_SET_UTF8, paragraph.GetText().c_str(), stringSize, logicalUnicodeBufferPointer ); - - // Character type buffer. - info->mCharactersTypeBuffer.resize( length, 0u ); - - // Levels buffer. - info->mLevelsBuffer.resize( length, 0u ); - - // Joining type buffer. - std::vector joiningTypeBuffer; - joiningTypeBuffer.resize( length, 0u ); - - // Pointers to the buffers. - FriBidiCharType* charactersTypeBufferPointer = &info->mCharactersTypeBuffer[0u]; - FriBidiLevel* levelsBufferPointer = &info->mLevelsBuffer[0u]; - FriBidiJoiningType* joiningTypeBufferPointer = &joiningTypeBuffer[0u]; - - // Retrieves the type of each character. - fribidi_get_bidi_types( logicalUnicodeBufferPointer, length, charactersTypeBufferPointer ); - - // Retrieves the paragraph direction. - info->mDirection = fribidi_get_par_direction( charactersTypeBufferPointer, length ); - - // Retrieve the embedding levels. - fribidi_get_par_embedding_levels( charactersTypeBufferPointer, length, &info->mDirection, levelsBufferPointer ); - - // Retrieve the joining types. - fribidi_get_joining_types( logicalUnicodeBufferPointer, length, joiningTypeBufferPointer ); - - fribidi_join_arabic( charactersTypeBufferPointer, length, levelsBufferPointer, joiningTypeBufferPointer ); - - const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC; - - fribidi_shape( flags, levelsBufferPointer, length, joiningTypeBufferPointer, logicalUnicodeBufferPointer ); - - std::vector bidiTextConverted; - - bidiTextConverted.resize( length * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6. - // Currently Dali doesn't support this UTF-8 extension. Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character. - - fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, logicalUnicodeBufferPointer, length, &bidiTextConverted[0] ); - - paragraph = Text( &bidiTextConverted[0u] ); -} - -void ReorderLine( BidirectionalParagraphInfo* paragraphInfo, - BidirectionalLineInfo* lineInfo ) -{ - const FriBidiFlags flags = FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC; - - lineInfo->mVisualToLogicalMap.Resize( lineInfo->mNumberOfCharacters, 0u ); - lineInfo->mLogicalToVisualMap.Resize( lineInfo->mNumberOfCharacters, 0u ); - - std::vector visualUnicodeBuffer; - visualUnicodeBuffer.insert( visualUnicodeBuffer.end(), - paragraphInfo->mLogicalUnicodeBuffer.begin() + lineInfo->mCharacterParagraphIndex, - paragraphInfo->mLogicalUnicodeBuffer.begin() + ( lineInfo->mCharacterParagraphIndex + lineInfo->mNumberOfCharacters ) ); - - // Pointers to the buffers. - FriBidiCharType* charactersTypeBufferPointer = ¶graphInfo->mCharactersTypeBuffer[lineInfo->mCharacterParagraphIndex]; - FriBidiLevel* levelsBufferPointer = ¶graphInfo->mLevelsBuffer[lineInfo->mCharacterParagraphIndex]; - FriBidiChar* visualUnicodeBufferPointer = &visualUnicodeBuffer[0u]; - FriBidiStrIndex* visualToLogicalMapPointer = &lineInfo->mVisualToLogicalMap[0u]; - - // Initialize the visual to logical mapping table to the identity. Otherwise fribidi_reorder_line fails to retrieve a valid mapping table. - for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index ) - { - lineInfo->mVisualToLogicalMap[ index ] = index; - } - - fribidi_reorder_line( flags, - charactersTypeBufferPointer, - lineInfo->mNumberOfCharacters, - 0u, - paragraphInfo->mDirection, - levelsBufferPointer, - visualUnicodeBufferPointer, - visualToLogicalMapPointer ); - - // Fill the logical to visual mapping table. - for( std::size_t index = 0u; index < lineInfo->mNumberOfCharacters; ++index ) - { - lineInfo->mLogicalToVisualMap[ lineInfo->mVisualToLogicalMap[ index ] ] = index; - } - - std::vector bidiTextConverted; - - bidiTextConverted.resize( lineInfo->mNumberOfCharacters * 4u + 1u ); // Maximum bytes to represent one UTF-8 character is 6. - // Currently Dali doesn't support this UTF-8 extension. - // Dali only supports 'regular' UTF-8 which has a maximum of 4 bytes per character. - - fribidi_unicode_to_charset( FRIBIDI_CHAR_SET_UTF8, visualUnicodeBufferPointer, lineInfo->mNumberOfCharacters, &bidiTextConverted[0u] ); - - lineInfo->mText = Text( &bidiTextConverted[0u] ); -} - -} // namespace TextProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h b/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h deleted file mode 100644 index 1ed24cd..0000000 --- a/dali-toolkit/internal/controls/text-view/text-processor-bidirectional-info.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__ -#define __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -// EXTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ - -/** - * Stores the text containing right to left characters and info for each character needed by fribidi to reorder a line. - */ -struct BidirectionalParagraphInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - BidirectionalParagraphInfo(); - - /** - * Default destructor. - */ - ~BidirectionalParagraphInfo(); - - /** - * Copy constructor. - */ - BidirectionalParagraphInfo( const BidirectionalParagraphInfo& info ); - - /** - * Assignment operator. - */ - BidirectionalParagraphInfo& operator=( const BidirectionalParagraphInfo& info ); - - - /** - * @return Whether the paragraph is right to left. - */ - bool IsRightToLeftParagraph() const; - - FriBidiParType mDirection; ///< The paragraph direction. - std::vector mCharactersTypeBuffer; ///< Character type buffer. - std::vector mLevelsBuffer; ///< Levels buffer. - std::vector mLogicalUnicodeBuffer; ///< Text buffer in logical order. Coded in unicode. -}; - -/** - * Stores the reordered text, the conversion tables for a paragraph's line, - * the index to the first character of the line and the number of characters. - */ -struct BidirectionalLineInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - BidirectionalLineInfo(); - - /** - * Default destructor. - */ - ~BidirectionalLineInfo(); - - /** - * Copy constructor. - */ - BidirectionalLineInfo( const BidirectionalLineInfo& info ); - - /** - * Assignment operator. - */ - BidirectionalLineInfo& operator=( const BidirectionalLineInfo& info ); - - std::size_t mCharacterParagraphIndex; ///< Index within the paragraph of the first character of the line. - std::size_t mNumberOfCharacters; ///< Number of characters of the line. - Text mText; ///< Text in visual order. - Vector mVisualToLogicalMap; ///< The character position map from the visual output text to the logical input text. - Vector mLogicalToVisualMap; ///< The character position map from the logical input text to the visual output text. -}; - -/** - * Whether the text begins with right-to-left (bidirectional) character. - * @param [in] text The given text. - * @return \e true if the text begins right-to-left character. - */ -bool BeginsRightToLeftCharacter( const Text& text ); - -/** - * Whether the text contains any right-to-left (bidirectional) character. - * @param [in] text The given text. - * @return \e true if the text contains right-to-left character. - */ -bool ContainsRightToLeftCharacter( const Text& text ); - -/** - * Processes a bidirectional paragraph's text. - * - * It stores the paragraph's direction (the direction of the first non neutral character), - * the direction of all characters, and the ligatures in case of arabic glyphs. - * - * It doesn't reorder the paragraph as this task must be done per line. - * The stored info is needed to reorder each line of the paragraph. - * - * @param[in] paragraph The paragraph to be processed. - * @param[out] info Struct containing the needed info to reorder each line of the paragraph. - */ -void ProcessBidirectionalText( Text& paragraph, - BidirectionalParagraphInfo* info ); - -/** - * Reorders one line of the paragraph according the Unicode Bidirectional Algorithm. - * - * The result is the text in the visual order and the conversion tables: logical <--> visual order - * - * @param[in] paragraphInfo Struct containing the needed info to reorder each line of the paragraph. - * @param[in,out] lineInfo Struct containing (in) A character index pointing the first character of the line and the number of characters, (out) the reordered line and the conversion tables. - */ -void ReorderLine( BidirectionalParagraphInfo* paragraphInfo, - BidirectionalLineInfo* lineInfo ); - -} // namespace TextProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_TEXT_PROCESSOR_BIDIRECTIONAL_INFO_H__ - diff --git a/dali-toolkit/internal/controls/text-view/text-processor.cpp b/dali-toolkit/internal/controls/text-view/text-processor.cpp deleted file mode 100644 index 99b7b59..0000000 --- a/dali-toolkit/internal/controls/text-view/text-processor.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2014 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 - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ - -void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray, - std::vector& paragraphs, - std::vector< Vector >& styles ) -{ - // Stores the text for a paragraph. - Text paragraph; - - // Stores the styles for each character of the paragraph. - Vector stylesForParagraph; - - // Traverses all styled texts of the array. - for( MarkupProcessor::StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it ) - { - const MarkupProcessor::StyledText& styledText( *it ); - - // Traverses all the characters of the styled text (It may have more than one). - for( size_t i = 0u, length = styledText.mText.GetLength(); i < length; ++i ) - { - const Dali::Character character = styledText.mText[i]; - - if( character.IsNewLine() ) // LF - { - // The character is a new paragraph character. - - // Append the new paragraph character. - paragraph.Append( character ); - - // Creates a new text style for the character and insert it to the vector of styles for that paragraph. - TextStyle* style = new TextStyle( styledText.mStyle ); - stylesForParagraph.PushBack( style ); - - // Inserts the paragraph and the styles to the vector of paragraphs and the vector of styles. - paragraphs.push_back( paragraph ); - styles.push_back( stylesForParagraph ); - - // Clears the text and the vector of styles for the next paragraph. - paragraph = Text(); - stylesForParagraph.Clear(); - } - else - { - // The character is not a new paragraph character. - - // Append it to the paragraph's text - paragraph.Append( character ); - - // Add the style to the vector of styles for that paragraph. - TextStyle* style = new TextStyle( styledText.mStyle ); - stylesForParagraph.PushBack( style ); - } - } - } - - // This paragraph could be empty if the last character of the previous paragraph is a 'new paragraph' character - // and is the last of the text. - paragraphs.push_back( paragraph ); - styles.push_back( stylesForParagraph ); -} - -void SplitInWords( const Dali::Text& paragraph, - Vector& positions ) -{ - const std::size_t length = paragraph.GetLength(); - - // Magic number: Let's soupose there is ~6 characters per word. Used to do less memory reallocation inside Vector. - const size_t magicNumberOfWords = ( length / 6u ) + 1u; - - // Find the positions of the new paragraph characters. - positions.Reserve( magicNumberOfWords ); - - // Find the position of all white spaces. A new paragraph character is also considered a white space but it doesn't matter at this point. - paragraph.Find( Text::WHITE_SPACE, 0u, length - 1u, positions ); -} - -/** - * Wheather the character of the text pointed by the given offset is a white space. - * - * @param[in] text The text. - * @param[in] offset Offset pointing the character. - * - * @return \e true if the character pointed by the offset is a white space. - */ -bool IsWhiteSpace( const MarkupProcessor::StyledTextArray& text, size_t offset ) -{ - DALI_ASSERT_DEBUG( offset < text.size() ); - - // assume 1 Character per StyledText - return ( *( text.begin() + offset ) ).mText[0u].IsWhiteSpace(); -} - -void FindNearestWord( const MarkupProcessor::StyledTextArray& text, size_t offset, size_t& start, size_t& end) -{ - const size_t size(text.size()); - offset = std::min(offset, size-1u); - - size_t i(offset); - size_t j(offset); - - // if currently looking at whitespace, then search left and right for non-whitespace. - if(IsWhiteSpace(text, offset)) - { - // scan left until non-white space / beginning of string. - while(i > 0u && IsWhiteSpace(text, i)) - { - i--; - } - - // scan right until non-white space / end of string. - while(j < size && IsWhiteSpace(text, j)) - { - j++; - } - } - - // check if r.h.s. word is closer than l.h.s. word - if( (j - offset) < // distance to closest right word < - (offset - i) ) // distance to closest left word - { - // point left and right markers on start of right word - i = j; - } - else - { - // point left and right markers on end of left word - j = i; - } - - // expand left and right markers to encompase entire word - while(i > 0u && !IsWhiteSpace(text, i-1u)) - { - i--; - } - - while(j < size && !IsWhiteSpace(text, j)) - { - j++; - } - - // If both markers at same position and is whitespace then word is a whitespace word - if ( i == j ) - { - while(j < size && IsWhiteSpace(text, j)) - { - j++; - } - - while(i > 0 && IsWhiteSpace(text, i-1)) - { - i--; - } - } - - start = i; - end = j; -} - -} // namespace TextProcessor - -} // namespace Internal - -} // namespace DaliToolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-processor.h b/dali-toolkit/internal/controls/text-view/text-processor.h deleted file mode 100644 index 9814c09..0000000 --- a/dali-toolkit/internal/controls/text-view/text-processor.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __DALI_TOOLKIT_TEXT_PROCESSOR_H__ -#define __DALI_TOOLKIT_TEXT_PROCESSOR_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ -// Forward declarations. -struct BidirectionalParagraphInfo; - -/** - * Splits the given text in paragraphs. - * - * @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but - * not necessarily the case for text in TextView) - * - * @param [in] styledTextArray The given text. - * @param [out] paragraphs The text split in paragraphs. - * @param [out] styles The styles of each character of each paragraph. - */ -void SplitInParagraphs( const MarkupProcessor::StyledTextArray& styledTextArray, - std::vector& paragraphs, - std::vector< Vector >& styles ); - -/** - * Finds the position of all word separators (currently white spaces and new paragraph characters '\n') in the given text. - * - * @param [in] paragraph The given paragraph. - * @param [out] positions Positions within the paragraph of all word sepatators. - */ -void SplitInWords( const Text& paragraph, - Vector& positions ); - -/** - * Finds the nearest word in a string to a specified - * offset (in Characters). - * - * @note Assumes the StyledTextArray has 1 Character per Text element. (which is the case for text in TextInput, but - * not necessarily the case for text in TextView) - * - * @param[in] text The text to search through. - * @param[in] offset The current offset position to begin search from. - * @param[out] start The start position of nearest word - * @param[out] end The end position of nearest word - */ -void FindNearestWord( const MarkupProcessor::StyledTextArray& text, size_t offset, size_t& start, size_t& end); - -} // namespace TextProcessor - -} // namespace Internal - -} // namespace DaliToolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_TEXT_PROCESSOR_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp b/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp deleted file mode 100644 index ddcf00f..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-character-processor.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -///////////////////// -// Layout info. -///////////////////// - -GradientInfo::GradientInfo() -: mGradientColor(), - mStartPoint(), - mEndPoint() -{ -} - -GradientInfo::~GradientInfo() -{ -} - -GradientInfo::GradientInfo( const GradientInfo& info ) -: mGradientColor( info.mGradientColor ), - mStartPoint( info.mStartPoint ), - mEndPoint( info.mEndPoint ) -{ -} - -GradientInfo& GradientInfo::operator=( const GradientInfo& info ) -{ - if( this != &info ) - { - mGradientColor = info.mGradientColor; - mStartPoint = info.mStartPoint; - mEndPoint = info.mEndPoint; - } - - return *this; -} - -CharacterLayoutInfo::CharacterLayoutInfo() -: mSize(), - mBearing( 0.f ), - mAscender( 0.f ), - mUnderlineThickness( 0.f ), - mUnderlinePosition( 0.f ), - mPosition(), - mOffset(), - mGlyphActor(), - mColorAlpha( 1.f ), - mGradientInfo( NULL ), - mIsVisible( true ), - mSetText( false ), - mSetStyle( false ), - mIsColorGlyph( false ) -{ -} - -CharacterLayoutInfo::~CharacterLayoutInfo() -{ - // Deletes the gradient info. - delete mGradientInfo; -} - -CharacterLayoutInfo::CharacterLayoutInfo( const CharacterLayoutInfo& character ) -: mSize( character.mSize ), - mBearing( character.mBearing ), - mAscender( character.mAscender ), - mUnderlineThickness( character.mUnderlineThickness ), - mUnderlinePosition( character.mUnderlinePosition ), - mPosition( character.mPosition ), - mOffset( character.mOffset ), - mGlyphActor( character.mGlyphActor ), - mColorAlpha( character.mColorAlpha ), - mGradientInfo( ( NULL == character.mGradientInfo ) ? NULL : new GradientInfo( *character.mGradientInfo ) ), // Copies the gradient info. - mIsVisible( character.mIsVisible ), - mSetText( character.mSetText ), - mSetStyle( character.mSetStyle ), - mIsColorGlyph( character.mIsColorGlyph ) -{ -} - -CharacterLayoutInfo& CharacterLayoutInfo::operator=( const CharacterLayoutInfo& character ) -{ - mSize = character.mSize; - mAscender = character.mAscender; - mBearing = character.mBearing; - mUnderlineThickness = character.mUnderlineThickness; - mUnderlinePosition = character.mUnderlinePosition; - - mPosition = character.mPosition; - mOffset = character.mOffset; - - mGlyphActor = character.mGlyphActor; - - mColorAlpha = character.mColorAlpha; - - // Copies the gradient info. - if( NULL == character.mGradientInfo ) - { - // The source doesn't have. Deletes the current one. - delete mGradientInfo; - mGradientInfo = NULL; - } - else - { - // The source has gradient info. - if( NULL != mGradientInfo ) - { - // It it has, copy to it. - *mGradientInfo = *character.mGradientInfo; - } - else - { - // If it doesn't have, create a new one. - mGradientInfo = new GradientInfo( *character.mGradientInfo ); - } - } - - mIsVisible = character.mIsVisible; - mSetText = character.mSetText; - mSetStyle = character.mSetStyle; - mIsColorGlyph = character.mIsColorGlyph; - - return *this; -} - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-impl.cpp b/dali-toolkit/internal/controls/text-view/text-view-impl.cpp deleted file mode 100644 index a5b28ef..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-impl.cpp +++ /dev/null @@ -1,2321 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace -{ - -const char* MULTILINE_POLICY_NAME[] = {"SplitByNewLineChar", "SplitByWord", "SplitByChar"}; -const char* EXCEED_POLICY_NAME[] = {"Original", "Truncate", "Fade", "Split","ShrinkToFit","EllipsizeEnd"}; -const char* LINE_JUSTIFICATION_NAME[] = {"Left","Center","Right","Justified"}; - -// Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k. -const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f; - -// Type Registration -BaseHandle Create() -{ - return Toolkit::TextView::New(); -} - -// Setup properties, signals and actions using the type-registry. -DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextView, Toolkit::Control, Create ); - -DALI_PROPERTY_REGISTRATION( TextView, "markup-enabled", BOOLEAN, MARKUP_ENABLED ) -DALI_PROPERTY_REGISTRATION( TextView, "text", STRING, TEXT ) -DALI_PROPERTY_REGISTRATION( TextView, "multiline-policy", STRING, MULTILINE_POLICY ) -DALI_PROPERTY_REGISTRATION( TextView, "width-exceed-policy", STRING, WIDTH_EXCEED_POLICY ) -DALI_PROPERTY_REGISTRATION( TextView, "height-exceed-policy", STRING, HEIGHT_EXCEED_POLICY ) -DALI_PROPERTY_REGISTRATION( TextView, "line-justification", STRING, LINE_JUSTIFICATION ) -DALI_PROPERTY_REGISTRATION( TextView, "fade-boundary", VECTOR4, FADE_BOUNDARY ) -DALI_PROPERTY_REGISTRATION( TextView, "line-height-offset", FLOAT, LINE_HEIGHT_OFFSET ) -DALI_PROPERTY_REGISTRATION( TextView, "horizontal-alignment", STRING, HORIZONTAL_ALIGNMENT ) -DALI_PROPERTY_REGISTRATION( TextView, "vertical-alignment", STRING, VERTICAL_ALIGNMENT ) - -DALI_SIGNAL_REGISTRATION( TextView, "scrolled", SIGNAL_TEXT_SCROLLED ) - -DALI_TYPE_REGISTRATION_END() - -/** - * Whether the text-view-processor operation sets, inserts, replaces, removes text. - * - * @param[in] metadata The text-view-processor operation. - * - * @return \e true if the given text-view-processor operation is modifying the text. - */ -bool IsTextViewProcessorRelayoutOperation( const TextView::TextViewProcessorMetadata& metadata ) -{ - return ( ( metadata.mType == TextView::TextSet ) || - ( metadata.mType == TextView::TextInserted ) || - ( metadata.mType == TextView::TextReplaced ) || - ( metadata.mType == TextView::TextRemoved ) || - ( metadata.mType == TextView::NewStyle )); -} - -/** - * Whether the text-view-processor operation sets a new line height offset. - * - * @param[in] metadata The text-view-processor operation. - * - * @return \e true if the given text-view-processor operation sets a new line height offset. - */ -bool IsTextViewProcessorLineHeightOffsetOperation( const TextView::TextViewProcessorMetadata& metadata ) -{ - return ( metadata.mType == TextView::NewLineHeight ); -} - -/** - * Whether the text-view-processor operation sets a new style. - * - * @param[in] metadata The text-view-processor operation. - * - * @return \e true if the given text-view-processor operation sets a new style. - */ -bool IsTextViewProcessorNewStyleOperation( const TextView::TextViewProcessorMetadata& metadata ) -{ - return ( metadata.mType == TextView::NewStyle ); -} - -} // namespace - -TextView::TextViewProcessorMetadata::TextViewProcessorMetadata() -: mType( TextView::TextSet ), - mPosition( 0u ), - mNumberOfCharacters( 0u ), - mText(), - mStyleMask(TextStyle::NONE) -{ -} - -Toolkit::TextView TextView::New() -{ - // Create the implementation, temporarily owned on stack - IntrusivePtr textView = new TextView(); - - // Pass ownership to CustomActor - Toolkit::TextView handle( *textView ); - - // Second-phase init of the implementation - // This can only be done after the CustomActor connection has been made... - textView->Initialize(); - - // Disables by default the offscreen rendering. - textView->SetSnapshotModeEnabled( false ); - - return handle; -} - -void TextView::SetText( const std::string& text ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() ); - - // Calls SetText() with the styled text array. - SetText( styledText ); -} - -void TextView::SetText( const MarkupProcessor::StyledTextArray& text ) -{ - // mTextViewProcessorOperations stores the InsertTextAt and RemoveTextFrom operations to transform the initial text to mCurrentStyledText. - // Once again, if a new text is set, any previous call to InsertTextAt or RemoveTextFrom can be discarted. - - std::vector::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorRelayoutOperation ); - mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() ); - - // Creates metadata with the Set operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::TextSet; - metadata.mText = text; - - // Store metadata. - mTextViewProcessorOperations.push_back( metadata ); - - // Updates current styled text. - mCurrentStyledText = text; - - // Request to be relaid out - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; -} - -void TextView::InsertTextAt( std::size_t position, const std::string& text ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() ); - - // Calls InsertTextAt() with the styled text array. - InsertTextAt( position, styledText ); -} - -void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text ) -{ - std::string textStr; - MarkupProcessor::GetPlainString( text, textStr ); - - if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) || - TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) ) - { - // Temporary fix. Creates the whole layout if there is rtl text. - - MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText; - textToSet.insert( textToSet.begin() + position, text.begin(), text.end() ); - SetText( textToSet ); - } - else - { - // Creates metadata with the Insert operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::TextInserted; - metadata.mPosition = position; - metadata.mText = text; - - // Store metadata. - mTextViewProcessorOperations.push_back( metadata ); - - // Updates current styled text. - mCurrentStyledText.insert( mCurrentStyledText.begin() + position, text.begin(), text.end() ); - - // Request to be relaid out - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - } -} - -void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( text, styledText, IsMarkupProcessingEnabled() ); - - // Calls ReplaceTextFromTo() with the styled text array. - ReplaceTextFromTo( position, numberOfCharacters, styledText ); -} - -void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text ) -{ - std::string textStr; - MarkupProcessor::GetPlainString( text, textStr ); - - if( TextProcessor::ContainsRightToLeftCharacter( Text( textStr ) ) || - TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) ) - { - // Temporary fix. Creates the whole layout if there is rtl text. - - // Updates current styled text. - MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText; - - MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position; - textToSet.erase( it, it + numberOfCharacters ); - it = textToSet.begin() + position; - textToSet.insert( it, text.begin(), text.end() ); - - SetText( textToSet ); - } - else - { - // Creates metadata with the Insert operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::TextReplaced; - metadata.mPosition = position; - metadata.mNumberOfCharacters = numberOfCharacters; - metadata.mText = text; - - // Store metadata. - mTextViewProcessorOperations.push_back( metadata ); - - // Updates current styled text. - MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position; - mCurrentStyledText.erase( it, it + numberOfCharacters ); - it = mCurrentStyledText.begin() + position; - mCurrentStyledText.insert( it, text.begin(), text.end() ); - - // Request to be relaid out - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - } -} - -void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ) -{ - if( TextProcessor::ContainsRightToLeftCharacter( Text( GetText() ) ) ) - { - // Temporary fix. Creates the whole layout if there is rtl text. - - // Updates current styled text. - MarkupProcessor::StyledTextArray textToSet = mCurrentStyledText; - MarkupProcessor::StyledTextArray::iterator it = textToSet.begin() + position; - textToSet.erase( it, it + numberOfCharacters ); - - SetText( textToSet ); - } - else - { - // Creates metadata with the Remove operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::TextRemoved; - metadata.mPosition = position; - metadata.mNumberOfCharacters = numberOfCharacters; - - // Store metadata. - mTextViewProcessorOperations.push_back( metadata ); - - // Updates current styled text. - MarkupProcessor::StyledTextArray::iterator it = mCurrentStyledText.begin() + position; - mCurrentStyledText.erase( it, it + numberOfCharacters ); - - // Request to be relaid out - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - } -} - -std::string TextView::GetText() const -{ - // Traverses the styled text array getting only the text. - // Note that for some languages a 'character' could be represented by more than one 'char' - - std::string text; - for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); it != endIt; ++it ) - { - text.append( (*it).mText.GetText() ); - } - - return text; -} - -void TextView::SetLineHeightOffset( PointSize offset ) -{ - if( fabsf( mLayoutParameters.mLineHeightOffset - offset ) > Math::MACHINE_EPSILON_1000 ) - { - // Removes any previous operation which modifies the line height offset. - std::vector::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorLineHeightOffsetOperation ); - mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() ); - - // Creates metadata with the new line height operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::NewLineHeight; - - mTextViewProcessorOperations.push_back( metadata ); - - // Updates line height offset. - mLayoutParameters.mLineHeightOffset = offset; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_SIZE_POSITION | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } -} - -PointSize TextView::GetLineHeightOffset() const -{ - return PointSize( mLayoutParameters.mLineHeightOffset ); -} - -void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask ) -{ - if( !mCurrentStyledText.empty() ) - { - const bool checkFontName = mask & TextStyle::FONT; - const bool checkFontSize = mask & TextStyle::SIZE; - const bool checkFontStyle = mask & TextStyle::STYLE; - - // Check first if metrics have changed. - bool metricsChanged = false; - for( MarkupProcessor::StyledTextArray::const_iterator it = mCurrentStyledText.begin(), endIt = mCurrentStyledText.end(); ( it != endIt ) && !metricsChanged; ++it ) - { - const MarkupProcessor::StyledText& styledText( *it ); - - metricsChanged = ( checkFontName && ( styledText.mStyle.GetFontName() != style.GetFontName() ) ) || - ( checkFontStyle && ( styledText.mStyle.GetFontStyle() != style.GetFontStyle() ) ) || - ( checkFontSize && ( fabsf( styledText.mStyle.GetFontPointSize() - style.GetFontPointSize() ) > Math::MACHINE_EPSILON_1000 ) ); - } - - if( metricsChanged ) - { - MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask ); - - // If metrics change, new text measurements are needed. - SetText( mCurrentStyledText ); - } - else - { - // Deletes any previous operation which sets a new style. - std::vector::iterator it = std::remove_if( mTextViewProcessorOperations.begin(), mTextViewProcessorOperations.end(), IsTextViewProcessorNewStyleOperation ); - mTextViewProcessorOperations.erase( it, mTextViewProcessorOperations.end() ); - - // Creates metadata with the new style operation. - TextViewProcessorMetadata metadata; - metadata.mType = TextView::NewStyle; - - MarkupProcessor::StyledText text; - text.mStyle = style; - metadata.mText.push_back( text ); - metadata.mStyleMask = mask; - - mTextViewProcessorOperations.push_back( metadata ); - - MarkupProcessor::SetTextStyle( mCurrentStyledText, style, mask ); - - RelayoutRequest(); - - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_TEXT_ACTOR_UPDATE ); - } - } - } - - // Sets the new style to the ellipsize text - // TODO: fix this as a call to SetEllipsizeText will trigger the creation of new text actors. - if( 0u < mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Count() ) - { - for( Vector::Iterator it = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.Begin(), - endIt = mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles.End(); - it != endIt; - ++it ) - { - (*it)->Copy( style, mask ); - } - - SetEllipsizeText( mRelayoutData.mTextLayoutInfo.mEllipsisText, mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles ); - } -} - -void TextView::SetTextAlignment( Toolkit::Alignment::Type align ) -{ - if( align != ( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ) ) - { - Toolkit::Alignment::Type horizontalAlignment( ( align & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft : - ( align & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter : - ( align & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) ); - Toolkit::Alignment::Type verticalAlignment( ( align & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop : - ( align & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter : - ( align & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) ); - - mLayoutParameters.mHorizontalAlignment = horizontalAlignment; - mLayoutParameters.mVerticalAlignment = verticalAlignment; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY ); - } - } -} - -Toolkit::Alignment::Type TextView::GetTextAlignment() const -{ - return static_cast( mLayoutParameters.mHorizontalAlignment | mLayoutParameters.mVerticalAlignment ); -} - -void TextView::SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ) -{ - if( policy != mLayoutParameters.mMultilinePolicy ) - { - mLayoutParameters.mMultilinePolicy = policy; - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed on order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - - RelayoutRequest(); - } -} - -Toolkit::TextView::MultilinePolicy TextView::GetMultilinePolicy() const -{ - return mLayoutParameters.mMultilinePolicy; -} - -void TextView::SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ) -{ - // The layout info could be invalid depending on the current exceed policy and the new one. - // i.e. if the current policy is Split and the new one is ShrinkToFit then - // the layout info generated for each char is not needed. - if( policy != mLayoutParameters.mWidthExceedPolicy ) - { - mLayoutParameters.mWidthExceedPolicy = policy; - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - - RelayoutRequest(); - } -} - -Toolkit::TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const -{ - return mLayoutParameters.mWidthExceedPolicy; -} - -void TextView::SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ) -{ - if( policy != mLayoutParameters.mHeightExceedPolicy ) - { - mLayoutParameters.mHeightExceedPolicy = policy; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_SIZE_POSITION | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } -} - -Toolkit::TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const -{ - return mLayoutParameters.mHeightExceedPolicy; -} - -void TextView::SetLineJustification( Toolkit::TextView::LineJustification justification ) -{ - if( justification != mLayoutParameters.mLineJustification ) - { - mLayoutParameters.mLineJustification = justification; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_SIZE_POSITION | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } -} - -Toolkit::TextView::LineJustification TextView::GetLineJustification() const -{ - return mLayoutParameters.mLineJustification; -} - -void TextView::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ) -{ - if( ( fadeBoundary.mLeft != mVisualParameters.mFadeBoundary.mLeft ) || - ( fadeBoundary.mRight != mVisualParameters.mFadeBoundary.mRight ) || - ( fadeBoundary.mTop != mVisualParameters.mFadeBoundary.mTop ) || - ( fadeBoundary.mBottom != mVisualParameters.mFadeBoundary.mBottom ) ) - { - mVisualParameters.mFadeBoundary = fadeBoundary; - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } -} - -const Toolkit::TextView::FadeBoundary& TextView::GetFadeBoundary() const -{ - return mVisualParameters.mFadeBoundary; -} - -void TextView::SetEllipsizeText( const std::string& ellipsizeText ) -{ - // Creates a styled text with the markup or plain string. - MarkupProcessor::StyledTextArray styledText; - MarkupProcessor::GetStyledTextArray( ellipsizeText, styledText, IsMarkupProcessingEnabled() ); - - // Creates the ellipsis layout info and sets the text and styles. - SetEllipsizeText( styledText ); -} - -void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText ) -{ - // Converts the styled text array into a Text and a vector of TextStyles. - Text text; - Vector styles; - for( MarkupProcessor::StyledTextArray::const_iterator it = ellipsizeText.begin(), endIt = ellipsizeText.end(); it != endIt; ++it ) - { - const MarkupProcessor::StyledText& styledText( *it ); - - text.Append( styledText.mText ); - styles.PushBack( new TextStyle( styledText.mStyle ) ); - } - - // Creates the ellipsis layout info and sets the text and styles. - SetEllipsizeText( text, styles ); -} - -void TextView::SetEllipsizeText( const Text& ellipsizeText, const Vector& ellipsizeStyles ) -{ - // Sets the text and styles for the ellipsis text. - mRelayoutData.mTextLayoutInfo.mEllipsisText = ellipsizeText; - mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsizeStyles; - - // Creates the ellipsis layout info. - CreateEllipsizeLayout(); - - // Request to be relaid out - RelayoutRequest(); - - mRelayoutOperations = RELAYOUT_ALL; -} - -std::string TextView::GetEllipsizeText() const -{ - return mRelayoutData.mTextLayoutInfo.mEllipsisText.GetText(); -} - -void TextView::GetTextLayoutInfo() -{ - const bool relayoutSizeAndPositionNeeded = mRelayoutOperations & RELAYOUT_SIZE_POSITION; - const bool relayoutAlignmentNeeded = mRelayoutOperations & RELAYOUT_ALIGNMENT; - const bool relayoutVisibilityNeeded = mRelayoutOperations & RELAYOUT_VISIBILITY; - - if( relayoutSizeAndPositionNeeded || relayoutAlignmentNeeded || relayoutVisibilityNeeded ) - { - Vector3 textViewSize = GetControlSize(); - - if( ( ( textViewSize.width < Math::MACHINE_EPSILON_1000 ) || - ( textViewSize.height < Math::MACHINE_EPSILON_1000 ) ) && - ( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) && - ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) && - ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) ) - { - // In case the control size is not set but the layout settings are the default (split by new line character and original exceed policies) - // the text natural size can be used. - textViewSize = GetNaturalSize(); - } - - if( ( textViewSize.width > Math::MACHINE_EPSILON_1000 ) && - ( textViewSize.height > Math::MACHINE_EPSILON_1000 ) ) - { - // Check if the text-view has glyph-actors. - const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty(); - - RelayoutOperationMask mask = NO_RELAYOUT; - if( relayoutSizeAndPositionNeeded ) - { - mask = static_cast( mask | RELAYOUT_SIZE_POSITION ); - } - if( relayoutAlignmentNeeded ) - { - mask = static_cast( mask | RELAYOUT_ALIGNMENT ); - } - if( relayoutVisibilityNeeded ) - { - mask = static_cast( mask | RELAYOUT_VISIBILITY ); - } - - if( hasGlyphActors ) - { - // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo() - // add them to the text-actor cache. - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - mRelayoutData.mGlyphActors.clear(); - } - - // Relays-out but doesn't add glyph-actors to the text-view. - DoRelayOut( textViewSize.GetVectorXY(), mask ); - - if( hasGlyphActors ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } - } -} - -void TextView::GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo ) -{ - GetTextLayoutInfo(); - - textLayoutInfo.mCharacterLayoutInfoTable = mRelayoutData.mCharacterLayoutInfoTable; - textLayoutInfo.mLines = mRelayoutData.mLines; - - textLayoutInfo.mCharacterLogicalToVisualMap = mRelayoutData.mCharacterLogicalToVisualMap; - textLayoutInfo.mCharacterVisualToLogicalMap = mRelayoutData.mCharacterVisualToLogicalMap; - - textLayoutInfo.mTextSize = mRelayoutData.mTextSizeForRelayoutOption; - - textLayoutInfo.mScrollOffset = mVisualParameters.mCameraScrollPosition; -} - -void TextView::SetSortModifier( float depthOffset ) -{ - mVisualParameters.mSortModifier = depthOffset; - - for( std::vector::iterator it = mRelayoutData.mGlyphActors.begin(), endIt = mRelayoutData.mGlyphActors.end(); - it != endIt; - ++it ) - { - // ( *it ).SetSortModifier( depthOffset ); - } - - if( mOffscreenImageActor ) - { - // mOffscreenImageActor.SetSortModifier( depthOffset ); - } -} - -void TextView::SetSnapshotModeEnabled( bool enable ) -{ - if( enable != mVisualParameters.mSnapshotModeEnabled ) - { - // Remove first all glyph-actors - if( !mRelayoutData.mGlyphActors.empty() ) - { - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - } - - mVisualParameters.mSnapshotModeEnabled = enable; - if( !mLockPreviousSnapshotMode ) - { - // mPreviousSnapshotModeEnabled stores the snapshot mode value before SetScrollEnabled( true ) is - // called. However, if SetSnapshotModeEnabled() is called after SetScrollEnabled() then the stored value - // is updated. - // As SetSnapshotModeEnabled() is also called from SetScrollEnabled(), the mLockPreviousSnapshotMode prevents - // to smash the stored value. - mPreviousSnapshotModeEnabled = enable; - } - - if( mVisualParameters.mSnapshotModeEnabled ) - { - // Create a root actor and an image actor for offscreen rendering. - mOffscreenRootActor = Layer::New(); - mOffscreenImageActor = ImageActor::New(); - - mOffscreenRootActor.SetColorMode( USE_OWN_COLOR ); - mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION ); - mOffscreenRootActor.SetInheritOrientation( false ); - mOffscreenRootActor.SetInheritScale( false ); - mOffscreenRootActor.SetDepthTestDisabled( true ); - - mOffscreenRootActor.SetPosition( 0.f, 0.f, 0.f ); - - mOffscreenImageActor.SetAnchorPoint( ParentOrigin::CENTER ); - mOffscreenImageActor.SetParentOrigin( ParentOrigin::CENTER ); - mOffscreenImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA, - BlendingFactor::ONE, BlendingFactor::ONE ); - - Actor self = Self(); - self.Add( mOffscreenRootActor ); - self.Add( mOffscreenImageActor ); - mOffscreenImageActor.SetScale( Vector3( 1.f, -1.f, 1.f ) ); - } - else - { - Actor self = Self(); - - if( mOffscreenRootActor ) - { - self.Remove( mOffscreenRootActor ); - } - - if( mOffscreenImageActor ) - { - self.Remove( mOffscreenImageActor ); - } - - DestroyOffscreenRenderingResources(); - } - - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - RelayoutRequest(); - } -} - -bool TextView::IsSnapshotModeEnabled() const -{ - return mVisualParameters.mSnapshotModeEnabled; -} - -void TextView::SetMarkupProcessingEnabled( bool enable ) -{ - mMarkUpEnabled = enable; -} - -bool TextView::IsMarkupProcessingEnabled() const -{ - return mMarkUpEnabled; -} - -void TextView::SetScrollEnabled( bool enable ) -{ - if( enable != mVisualParameters.mScrollEnabled ) - { - mVisualParameters.mScrollEnabled = enable; - - if( mVisualParameters.mScrollEnabled ) - { - // Offscreen rendering is needed to enable text scroll. - - // Stores previous value of the snapshot mode. - mPreviousSnapshotModeEnabled = IsSnapshotModeEnabled(); - - { - // SetSnapshotModeEnabled() modifies the mPreviousSnapshotModeEnabled just in case it's called after SetScrollEnabled(), - // this lock prevents to modify the mPreviousSnapshotModeEnabled when SetSnapshotModeEnabled() from this method. - Lock lock( mLockPreviousSnapshotMode ); - SetSnapshotModeEnabled( true ); - } - - // Creates the pan gesture detector and attach the text-view. - mPanGestureDetector = PanGestureDetector::New(); - mPanGestureDetector.DetectedSignal().Connect( this, &TextView::OnTextPan ); - mPanGestureDetector.Attach( Self() ); - } - else - { - // Removes the pan gesture detector. - if( mPanGestureDetector ) - { - mPanGestureDetector.Detach( Self() ); - mPanGestureDetector.DetectedSignal().Disconnect( this, &TextView::OnTextPan ); - mPanGestureDetector.Reset(); - } - - // Restores the previous state for snapshot mode. - SetSnapshotModeEnabled( mPreviousSnapshotModeEnabled ); - } - } -} - -bool TextView::IsScrollEnabled() const -{ - return mVisualParameters.mScrollEnabled; -} - -void TextView::SetScrollPosition( const Vector2& position ) -{ - if( position != mVisualParameters.mCameraScrollPosition ) - { - // Guard against destruction during signal emission - // Note that Emit() methods are called indirectly from within DoSetScrollPosition() - Toolkit::TextView handle( GetOwner() ); - - DoSetScrollPosition( position ); - - // Check if the new scroll position has been trimmed. - mVisualParameters.mScrollPositionTrimmed = ( position != mVisualParameters.mCameraScrollPosition ); - } -} - -const Vector2& TextView::GetScrollPosition() const -{ - return mVisualParameters.mCameraScrollPosition; -} - -bool TextView::IsScrollPositionTrimmed() const -{ - return mVisualParameters.mScrollPositionTrimmed; -} - -Toolkit::TextView::ScrolledSignalType& TextView::ScrolledSignal() -{ - return mScrolledSignal; -} - -bool TextView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) -{ - Dali::BaseHandle handle( object ); - - bool connected( true ); - Toolkit::TextView textView = Toolkit::TextView::DownCast( handle ); - - if( 0 == strcmp( signalName.c_str(), SIGNAL_TEXT_SCROLLED ) ) - { - textView.ScrolledSignal().Connect( tracker, functor ); - } - else - { - // signalName does not match any signal - connected = false; - } - - return connected; -} - -TextView::LayoutParameters::LayoutParameters() -: mMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ), - mExceedPolicy( TextView::Original ), - mWidthExceedPolicy( Toolkit::TextView::Original ), - mHeightExceedPolicy( Toolkit::TextView::Original ), - mHorizontalAlignment( Toolkit::Alignment::HorizontalCenter ), - mVerticalAlignment( Toolkit::Alignment::VerticalCenter ), - mLineJustification( Toolkit::TextView::Left ), - mLineHeightOffset( 0.f ), - mMarkUpEnabled( false ) -{ -} - -TextView::LayoutParameters::~LayoutParameters() -{ -} - -TextView::LayoutParameters::LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy, - Toolkit::TextView::ExceedPolicy widthExceedPolicy, - Toolkit::TextView::ExceedPolicy heightExceedPolicy, - Toolkit::Alignment::Type alignmentType, - Toolkit::TextView::LineJustification lineJustification, - float lineHeightOffset, - bool markUpEnabled ) -: mMultilinePolicy( multilinePolicy ), - mExceedPolicy( TextView::Original ), - mWidthExceedPolicy( widthExceedPolicy ), - mHeightExceedPolicy( heightExceedPolicy ), - mHorizontalAlignment(), - mVerticalAlignment(), - mLineJustification( lineJustification ), - mLineHeightOffset( lineHeightOffset ), - mMarkUpEnabled( markUpEnabled ) -{ - // Sets alignment - Toolkit::Alignment::Type horizontalAlignment( ( alignmentType & Toolkit::Alignment::HorizontalLeft ? Toolkit::Alignment::HorizontalLeft : - ( alignmentType & Toolkit::Alignment::HorizontalCenter ? Toolkit::Alignment::HorizontalCenter : - ( alignmentType & Toolkit::Alignment::HorizontalRight ? Toolkit::Alignment::HorizontalRight : Toolkit::Alignment::HorizontalCenter ) ) ) ); - Toolkit::Alignment::Type verticalAlignment( ( alignmentType & Toolkit::Alignment::VerticalTop ? Toolkit::Alignment::VerticalTop : - ( alignmentType & Toolkit::Alignment::VerticalCenter ? Toolkit::Alignment::VerticalCenter : - ( alignmentType & Toolkit::Alignment::VerticalBottom ? Toolkit::Alignment::VerticalBottom : Toolkit::Alignment::VerticalCenter ) ) ) ); - - mHorizontalAlignment = horizontalAlignment; - mVerticalAlignment = verticalAlignment; -} - -TextView::LayoutParameters::LayoutParameters( const TextView::LayoutParameters& layoutParameters ) -: mMultilinePolicy( layoutParameters.mMultilinePolicy ), - mExceedPolicy( TextView::Original ), - mWidthExceedPolicy( layoutParameters.mWidthExceedPolicy ), - mHeightExceedPolicy( layoutParameters.mHeightExceedPolicy ), - mHorizontalAlignment( layoutParameters.mHorizontalAlignment ), - mVerticalAlignment( layoutParameters.mVerticalAlignment ), - mLineJustification( layoutParameters.mLineJustification ), - mLineHeightOffset( layoutParameters.mLineHeightOffset ), - mMarkUpEnabled( layoutParameters.mMarkUpEnabled ) -{ -} - -TextView::LayoutParameters& TextView::LayoutParameters::operator=( const TextView::LayoutParameters& layoutParameters ) -{ - mMultilinePolicy = layoutParameters.mMultilinePolicy; - mWidthExceedPolicy = layoutParameters.mWidthExceedPolicy; - mHeightExceedPolicy = layoutParameters.mHeightExceedPolicy; - mHorizontalAlignment = layoutParameters.mHorizontalAlignment; - mVerticalAlignment = layoutParameters.mVerticalAlignment; - mLineJustification = layoutParameters.mLineJustification; - mLineHeightOffset = layoutParameters.mLineHeightOffset; - mMarkUpEnabled = layoutParameters.mMarkUpEnabled; - - return *this; -} - -TextView::VisualParameters::VisualParameters() -: mFadeBoundary(), - mSortModifier( 0.f ), - mCameraScrollPosition( 0.f, 0.f ), - mSnapshotModeEnabled( false ), - mScrollEnabled( false ), - mScrollPositionTrimmed( false ) -{ -} - -TextView::VisualParameters::VisualParameters( const VisualParameters& visualParameters ) -: mFadeBoundary( visualParameters.mFadeBoundary ), - mSortModifier( visualParameters.mSortModifier ), - mCameraScrollPosition( visualParameters.mCameraScrollPosition ), - mSnapshotModeEnabled( visualParameters.mSnapshotModeEnabled ), - mScrollEnabled( visualParameters.mScrollEnabled ), - mScrollPositionTrimmed( visualParameters.mScrollPositionTrimmed ) -{ -} - -TextView::VisualParameters& TextView::VisualParameters::operator=( const TextView::VisualParameters& visualParameters ) -{ - mFadeBoundary = visualParameters.mFadeBoundary; - mSortModifier = visualParameters.mSortModifier; - mCameraScrollPosition = visualParameters.mCameraScrollPosition; - mSnapshotModeEnabled = visualParameters.mSnapshotModeEnabled; - mScrollEnabled = visualParameters.mScrollEnabled; - mScrollPositionTrimmed = visualParameters.mScrollPositionTrimmed; - - return *this; -} - -TextView::RelayoutData::RelayoutData() -: mTextViewSize(), - mShrinkFactor( 1.f ), - mTextLayoutInfo(), - mCharacterLogicalToVisualMap(), - mCharacterVisualToLogicalMap(), - mGlyphActors(), - mCharacterLayoutInfoTable(), - mLines(), - mTextSizeForRelayoutOption() -{ -} - -TextView::RelayoutData::RelayoutData( const TextView::RelayoutData& relayoutData ) -: mTextViewSize( relayoutData.mTextViewSize ), - mShrinkFactor( relayoutData.mShrinkFactor ), - mTextLayoutInfo( relayoutData.mTextLayoutInfo ), - mCharacterLogicalToVisualMap( relayoutData.mCharacterLogicalToVisualMap ), - mCharacterVisualToLogicalMap( relayoutData.mCharacterVisualToLogicalMap ), - mGlyphActors( relayoutData.mGlyphActors ), - mCharacterLayoutInfoTable( relayoutData.mCharacterLayoutInfoTable ), - mLines( relayoutData.mLines ), - mTextSizeForRelayoutOption( relayoutData.mTextSizeForRelayoutOption ) -{ -} - -TextView::RelayoutData& TextView::RelayoutData::operator=( const TextView::RelayoutData& relayoutData ) -{ - mTextViewSize = relayoutData.mTextViewSize; - mShrinkFactor = relayoutData.mShrinkFactor; - mTextLayoutInfo = relayoutData.mTextLayoutInfo; - mCharacterLogicalToVisualMap = relayoutData.mCharacterLogicalToVisualMap; - mCharacterVisualToLogicalMap = relayoutData.mCharacterVisualToLogicalMap; - mGlyphActors = relayoutData.mGlyphActors; - mCharacterLayoutInfoTable = relayoutData.mCharacterLayoutInfoTable; - mLines = relayoutData.mLines; - mTextSizeForRelayoutOption = relayoutData.mTextSizeForRelayoutOption; - - return *this; -} - -TextView::TextView() -: Control( REQUIRES_STYLE_CHANGE_SIGNALS ), - mCurrentStyledText(), - mTextViewProcessorOperations(), - mLayoutParameters( Toolkit::TextView::SplitByNewLineChar, - Toolkit::TextView::Original, - Toolkit::TextView::Original, - static_cast( Toolkit::Alignment::HorizontalCenter | Toolkit::Alignment::VerticalCenter ), - Toolkit::TextView::Left, - PointSize( 0.f ), - false ), - mVisualParameters(), - mRelayoutData(), - mRelayoutOperations( NO_RELAYOUT ), - mOffscreenRootActor(), - mOffscreenImageActor(), - mOffscreenCameraActor(), - mCurrentOffscreenSize(), - mFrameBufferImage(), - mRenderTask(), - mPanGestureDetector(), - mLockPreviousSnapshotMode( false ), - mPreviousSnapshotModeEnabled( false ), - mMarkUpEnabled( false ) -{ - // Creates the ellipsis layout info. - CreateEllipsizeLayout(); -} - -TextView::~TextView() -{ - // Destroys offscreen rendering resources. - DestroyOffscreenRenderingResources(); - - // Destroys scroll pan gesture detector. - if( mPanGestureDetector ) - { - mPanGestureDetector.Reset(); - } -} - -Vector3 TextView::GetNaturalSize() -{ - if( !mTextViewProcessorOperations.empty() ) - { - // There are SetText, Inserts or Removes to do. It means the current layout info is not updated. - - if( !mRelayoutData.mGlyphActors.empty() ) - { - // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo() - // add them to the text-actor cache. - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - mRelayoutData.mGlyphActors.clear(); - - mRelayoutOperations = static_cast( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - - PerformTextViewProcessorOperations(); - } - - return Vector3( mRelayoutData.mTextLayoutInfo.mWholeTextSize.width, mRelayoutData.mTextLayoutInfo.mWholeTextSize.height, 0.f ); -} - -float TextView::GetHeightForWidth( float width ) -{ - float height = 0.f; - - if( ( Toolkit::TextView::SplitByNewLineChar == mLayoutParameters.mMultilinePolicy ) && - ( Toolkit::TextView::Original == mLayoutParameters.mWidthExceedPolicy ) && - ( Toolkit::TextView::Original == mLayoutParameters.mHeightExceedPolicy ) ) - { - // If multiline and exceed policies are 'SplitByNewLineChar' and 'Original' is better get the height from the - // natural size. GetNaturalSize() for this configuration is faster than DoRelayOut(). - height = GetNaturalSize().height; - } - else - { - // Check if the given width is different than the current one. - const bool differentWidth = ( fabsf( width - mRelayoutData.mTextViewSize.width ) > Math::MACHINE_EPSILON_1000 ); - - // Check if the text-view has glyph-actors. - const bool hasGlyphActors = !mRelayoutData.mGlyphActors.empty(); - - // Check which layout operations need to be done. - const bool relayoutSizeAndPositionNeeded = ( mRelayoutOperations & RELAYOUT_SIZE_POSITION ) || differentWidth; - - if( relayoutSizeAndPositionNeeded ) - { - if( hasGlyphActors ) - { - // Remove glyph-actors from the text-view as some text-operation like CreateTextInfo() - // add them to the text-actor cache. - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - mRelayoutData.mGlyphActors.clear(); - } - - // Use the given width. - const Vector2 textViewSize( width, GetControlSize().height ); - - // Relays-out but doesn't add glyph-actors to the text-view. - DoRelayOut( textViewSize, RELAYOUT_SIZE_POSITION ); - } - - // Retrieve the text height after relayout the text. - height = mRelayoutData.mTextSizeForRelayoutOption.height; - - if( differentWidth ) - { - // Revert the relayout operation mask - mRelayoutOperations = static_cast( mRelayoutOperations | RELAYOUT_SIZE_POSITION ); - } - - if( hasGlyphActors ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - - if( differentWidth || hasGlyphActors ) - { - RelayoutRequest(); - } - } - - return height; -} - -float TextView::GetWidthForHeight( float height ) -{ - // TODO: Needs implementing properly, for now just return the natural width. - return GetNaturalSize().width; -} - - -void TextView::OnInitialize() -{ - // The actor handle needs to be inialised for this to work - Self().SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS ); -} - - -void TextView::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange ) -{ - // Creates the ellipsis layout info. - CreateEllipsizeLayout(); - - SetText( mCurrentStyledText ); -} - -void TextView::OnControlSizeSet( const Vector3& size ) -{ - if( size.GetVectorXY() != mRelayoutData.mTextViewSize ) - { - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - mRelayoutOperations = RELAYOUT_ALL; - - // Request to be relaid out - RelayoutRequest(); - } -} - -void TextView::OnRelayout( const Vector2& size, RelayoutContainer& container ) -{ - if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) - { - // Not worth to relayout if width or height is equal to zero. - return; - } - - if( size != mRelayoutData.mTextViewSize ) - { - // if new size is different than the prevoius one, set positions and maybe sizes of all glyph-actor is needed. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_REMOVE_TEXT_ACTORS | - RELAYOUT_SIZE_POSITION | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_INSERT_TO_TEXT_VIEW ); - } - } - - if( ( Toolkit::TextView::Fade == mLayoutParameters.mWidthExceedPolicy ) || - ( Toolkit::TextView::Fade == mLayoutParameters.mHeightExceedPolicy ) ) - { - if( mRelayoutOperations & RELAYOUT_ALIGNMENT ) - { - // If the text of the alignment changes and a fade exceed policy is set, - // some characters may need new TextActor. - mRelayoutOperations = RELAYOUT_ALL; - } - } - - // Remove glyph-actors from text-view - if( !mRelayoutData.mGlyphActors.empty() && ( mRelayoutOperations & RELAYOUT_REMOVE_TEXT_ACTORS ) ) - { - TextViewRelayout::RemoveGlyphActors( GetRootActor(), mRelayoutData.mGlyphActors ); - mRelayoutData.mGlyphActors.clear(); - } - - if( NO_RELAYOUT != mRelayoutOperations ) - { - // Relays-out and add glyph-actors to the text-view. - DoRelayOut( size, mRelayoutOperations ); - ProcessSnapshot( size ); - } - - // Quite likely the texts of the text-actors are not going to be reused, so clear them. - mRelayoutData.mTextActorCache.ClearTexts(); -} - -void TextView::PerformTextViewProcessorOperations() -{ - // Traverse the relayout operation vector ... - - // Optimizes some operations. - OptimizeTextViewProcessorOperations(); - - for( std::vector::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it ) - { - const TextViewProcessorMetadata& relayoutMetadata( *it ); - - switch( relayoutMetadata.mType ) - { - case TextView::TextSet: - { - TextViewProcessor::CreateTextInfo( relayoutMetadata.mText, - mLayoutParameters, - mRelayoutData ); - break; - } - case TextView::TextInserted: - { - TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition, - relayoutMetadata.mText, - mLayoutParameters, - mRelayoutData ); - break; - } - case TextView::TextReplaced: - { - TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition, - relayoutMetadata.mNumberOfCharacters, - relayoutMetadata.mText, - mLayoutParameters, - mRelayoutData ); - break; - } - case TextView::TextRemoved: - { - TextViewProcessor::UpdateTextInfo( relayoutMetadata.mPosition, - relayoutMetadata.mNumberOfCharacters, - mLayoutParameters, - mRelayoutData, - TextViewProcessor::CLEAR_TEXT ); // clears the text of the text-actors. - break; - } - case TextView::NewLineHeight: - { - TextViewProcessor::UpdateTextInfo( mLayoutParameters.mLineHeightOffset, - mRelayoutData.mTextLayoutInfo ); - break; - } - case TextView::NewStyle: - { - TextViewProcessor::UpdateTextInfo( ( *relayoutMetadata.mText.begin() ).mStyle, - relayoutMetadata.mStyleMask, - mRelayoutData ); - break; - } - } - } - - // Clear all operations when they are done. - mTextViewProcessorOperations.clear(); -} - -void TextView::OptimizeTextViewProcessorOperations() -{ - // TODO: check if some operation can be discarted. i.e. InsertTextAt( 0, "a" ); RemoveTextFrom( 0, 1 ); - - // At the moment it only replaces a 'remove 1 character' followed by 'insert 1 character' in the same position by a 'replace' operation. - // This sequence is used by text-input with predictive text. Change this two operations by a replace allows the text-view processor to - // use the cache without clearing the text-actors. - - std::vector textViewProcessorOperations; - - for( std::vector::const_iterator it = mTextViewProcessorOperations.begin(), endIt = mTextViewProcessorOperations.end(); it != endIt; ++it ) - { - const TextViewProcessorMetadata& relayoutMetadata( *it ); - - switch( relayoutMetadata.mType ) - { - case TextView::TextRemoved: - { - bool optimizationDone = false; - - if( it + 1u != endIt ) - { - const TextViewProcessorMetadata& nextRelayoutMetadata( *( it + 1u ) ); - if( TextView::TextInserted == nextRelayoutMetadata.mType ) - { - if( relayoutMetadata.mPosition == nextRelayoutMetadata.mPosition ) - { - optimizationDone = true; - TextViewProcessorMetadata newRelayoutMetadata; - newRelayoutMetadata.mType = TextView::TextReplaced; - newRelayoutMetadata.mPosition = relayoutMetadata.mPosition; - newRelayoutMetadata.mNumberOfCharacters = relayoutMetadata.mNumberOfCharacters; - newRelayoutMetadata.mText = nextRelayoutMetadata.mText; - textViewProcessorOperations.push_back( newRelayoutMetadata ); - - // do not access the TextInserted operation in next iteration. - ++it; - } - } - } - - if( !optimizationDone ) - { - textViewProcessorOperations.push_back( relayoutMetadata ); - } - break; - } - default: - { - textViewProcessorOperations.push_back( relayoutMetadata ); - } - } - } - - mTextViewProcessorOperations = textViewProcessorOperations; -} - -void TextView::DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask ) -{ - // Traverse the relayout operation vector. It fills the natural size, layout and glyph-actor data structures. - if( !mTextViewProcessorOperations.empty() ) - { - PerformTextViewProcessorOperations(); - } - - CombineExceedPolicies(); - - Actor rootActor; - if( mVisualParameters.mSnapshotModeEnabled ) - { - rootActor = mOffscreenRootActor; - } - else - { - rootActor = Self(); - } - - mRelayoutData.mTextViewSize = textViewSize; - switch( mLayoutParameters.mMultilinePolicy ) - { - case Toolkit::TextView::SplitByNewLineChar: // multiline policy == SplitByNewLineChar. - { - SplitByNewLineChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData ); - break; - } // SplitByNewLineChar - - case Toolkit::TextView::SplitByWord: // multiline policy == SplitByWord. - { - SplitByWord::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData ); - break; - } // SplitByWord - - case Toolkit::TextView::SplitByChar: // multiline policy == SplitByChar. - { - SplitByChar::Relayout( rootActor, relayoutOperationMask, mLayoutParameters, mVisualParameters, mRelayoutData ); - break; - } // SplitByChar - } // switch( mMultilinePolicy ) - - // Remove done operations from the mask. - mRelayoutOperations = static_cast( mRelayoutOperations & ~relayoutOperationMask ); -} - -void TextView::ProcessSnapshot( const Size& textViewSize ) -{ - if( mVisualParameters.mSnapshotModeEnabled ) - { - // If layout options change, it's needed generate a new image. - - if( mOffscreenRootActor ) - { - // Set the root actor visible. - // The root actor is set to non visible after the render task is processed. - mOffscreenRootActor.SetVisible( true ); - - // The offscreen root actor must have same size as text view. Otherwise, text alignment won't work. - mOffscreenRootActor.SetSize( textViewSize ); - } - - if( ( mRelayoutData.mTextSizeForRelayoutOption.width > Math::MACHINE_EPSILON_1000 ) && - ( mRelayoutData.mTextSizeForRelayoutOption.height > Math::MACHINE_EPSILON_1000 ) ) - { - // Set the image actor visible. - // The image actor is set to non visible if there is no text to render. - mOffscreenImageActor.SetVisible( true ); - - // Calculates the offscreen image's size. It takes into account different points: - // * If text has italics, add a small offset is needed in order to not to cut the text next to the right edge. - // * There is a maximum texture size the graphic subsystem can load on the memory. - // * If the scroll is enabled, the offscreen image's size is never bigger than the text-view's size. - - const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, - mVisualParameters.mScrollEnabled ? textViewSize.width : std::max( mRelayoutData.mTextSizeForRelayoutOption.width, textViewSize.width ) + mRelayoutData.mTextLayoutInfo.mMaxItalicsOffset ), - std::min( MAX_OFFSCREEN_RENDERING_SIZE, - mVisualParameters.mScrollEnabled ? textViewSize.height : std::max( mRelayoutData.mTextSizeForRelayoutOption.height, textViewSize.height ) ) ); - - const bool sizeChanged = offscreenSize != mCurrentOffscreenSize; - - if( sizeChanged ) - { - // Creates a frame buffer for offscreen rendering when the size is negotiated. - mFrameBufferImage = FrameBufferImage::New( offscreenSize.width, - offscreenSize.height, - Pixel::RGBA8888 ); - - // Stores current text-view size to avoid create new Dali resources if text changes. - mCurrentOffscreenSize = offscreenSize; - - if( !mOffscreenCameraActor ) - { - // Creates a new camera actor. - mOffscreenCameraActor = CameraActor::New(); - mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER ); - mOffscreenCameraActor.SetAnchorPoint( AnchorPoint::CENTER ); - mOffscreenCameraActor.SetOrientation(Degree(180.f), Vector3::YAXIS); - - mOffscreenCameraActor.SetType( Dali::Camera::FREE_LOOK ); // Inherits position from the offscreen root actor. - - mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text - } - - // Calculate camera parameters for current text size. - mOffscreenCameraActor.SetOrthographicProjection( offscreenSize ); - } - - if( mVisualParameters.mScrollEnabled ) - { - // Updates the offscreen camera position with the new scroll offset. - mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x ); - mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y ); - } - else - { - // Text's size could be bigger than text-view's size. In that case the camera must be aligned to cover the whole text. - AlignOffscreenCameraActor( textViewSize, offscreenSize ); - } - - if( !mRenderTask ) - { - // Creates a new render task. - mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask(); - - mRenderTask.SetSourceActor( mOffscreenRootActor ); - mRenderTask.SetInputEnabled( false ); - mRenderTask.SetClearColor( Color::TRANSPARENT ); - mRenderTask.SetClearEnabled( true ); - mRenderTask.SetExclusive( true ); - - // Connects the signal to the TextView::RenderTaskFinished method in order to make the root actor non visible when the render task is processed. - mRenderTask.FinishedSignal().Connect( this, &TextView::RenderTaskFinished ); - } - - if( sizeChanged ) - { - mRenderTask.SetCameraActor( mOffscreenCameraActor ); - mRenderTask.SetTargetFrameBuffer( mFrameBufferImage ); - } - - // Process the render task only once every time the text changes or the text-view's size canges. - mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); - } - else - { - // If there is no text just make any previous generated image invisible instead to process a render task with no text. - mOffscreenImageActor.SetVisible( false ); - } - } -} - -void TextView::AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize ) -{ - float xPosition = 0.f; - float yPosition = 0.f; - Vector3 parentOrigin = ParentOrigin::CENTER; - Vector3 anchorPoint = AnchorPoint::CENTER; - - switch( mLayoutParameters.mHorizontalAlignment ) - { - case Toolkit::Alignment::HorizontalLeft: - { - xPosition = 0.5f * ( offscreenSize.width - textViewSize.width ); - parentOrigin.x = 0.f; - anchorPoint.x = 0.f; - break; - } - case Toolkit::Alignment::HorizontalCenter: - { - // nothing to do. - break; - } - case Toolkit::Alignment::HorizontalRight: - { - xPosition = 0.5f * ( textViewSize.width - offscreenSize.width ); - parentOrigin.x = 1.f; - anchorPoint.x = 1.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." ) - } - } - - switch( mLayoutParameters.mVerticalAlignment ) - { - case Toolkit::Alignment::VerticalTop: - { - yPosition = 0.5f * ( offscreenSize.height - textViewSize.height ); - parentOrigin.y = 0.f; - anchorPoint.y = 0.f; - break; - } - case Toolkit::Alignment::VerticalCenter: - { - // nothing to do. - break; - } - case Toolkit::Alignment::VerticalBottom: - { - yPosition = 0.5f * ( textViewSize.height - offscreenSize.height ); - parentOrigin.y = 1.f; - anchorPoint.y = 1.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::AlignOffscreenCameraActor: Invalid alignment option." ) - } - } - - mOffscreenCameraActor.SetX( xPosition ); - mOffscreenCameraActor.SetY( yPosition ); - - mOffscreenImageActor.SetParentOrigin( parentOrigin ); - mOffscreenImageActor.SetAnchorPoint( anchorPoint ); -} - -void TextView::RenderTaskFinished( Dali::RenderTask& renderTask ) -{ - // not to process the offscreen root actor by setting its visibility to false. - mOffscreenRootActor.SetVisible( false ); - - // Sets the new size and the new frame buffer to the image actor. - // Image actor must have same size as text. Otherwise text can be truncated. - mOffscreenImageActor.SetSize( mCurrentOffscreenSize ); - mOffscreenImageActor.SetImage( mFrameBufferImage ); -} - -void TextView::DestroyOffscreenRenderingResources() -{ - if( mRenderTask ) - { - mRenderTask.FinishedSignal().Disconnect( this, &TextView::RenderTaskFinished ); - - if( Stage::IsInstalled() ) - { - Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask ); - } - - mRenderTask.Reset(); - } - - // Remove and reset the root actor, image actor and camera actor as text-view is not rendering offscreen. - if( mOffscreenCameraActor ) - { - mOffscreenRootActor.Remove( mOffscreenCameraActor ); - - mOffscreenCameraActor.Reset(); - } - - if( mOffscreenRootActor ) - { - mOffscreenRootActor.Reset(); - } - - if( mOffscreenImageActor ) - { - mOffscreenImageActor.Reset(); - } - - mCurrentOffscreenSize = Size( 0.f, 0.f ); - - if( mFrameBufferImage ) - { - mFrameBufferImage.Reset(); - } -} - -void TextView::OnTextPan( Actor actor, const PanGesture& gesture ) -{ - if( 1u == gesture.numberOfTouches ) - { - DoSetScrollPosition( mVisualParameters.mCameraScrollPosition - gesture.displacement ); - } -} - -void TextView::TrimScrollPosition() -{ - const Vector3& textViewSize = GetControlSize(); - - // Before use the text's size, relayout the text is needed to get the actual text size. - GetTextLayoutInfo(); - - // Calculates the range within the text could be scrolled. (When the text is aligned in the center). - float maxHorizontalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.width - textViewSize.width ) ); - float maxVerticalDisplacement = std::max( 0.f, 0.5f * ( mRelayoutData.mTextSizeForRelayoutOption.height - textViewSize.height ) ); - float minHorizontalDisplacement = -maxHorizontalDisplacement; - float minVerticalDisplacement = -maxVerticalDisplacement; - - // Updates the range if the text is aligned on the right or left. - switch( mLayoutParameters.mHorizontalAlignment ) - { - case Toolkit::Alignment::HorizontalLeft: - { - maxHorizontalDisplacement *= 2.f; - minHorizontalDisplacement = 0.f; - break; - } - case Toolkit::Alignment::HorizontalCenter: - { - // nothing to do. - break; - } - case Toolkit::Alignment::HorizontalRight: - { - maxHorizontalDisplacement = 0.f; - minHorizontalDisplacement *= 2.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." ) - } - } - - // Updates the range if the text is aligned on the top or bottom. - switch( mLayoutParameters.mVerticalAlignment ) - { - case Toolkit::Alignment::VerticalTop: - { - maxVerticalDisplacement *= 2.f; - minVerticalDisplacement = 0.f; - break; - } - case Toolkit::Alignment::VerticalCenter: - { - //nothing to do - break; - } - case Toolkit::Alignment::VerticalBottom: - { - maxVerticalDisplacement = 0.f; - minVerticalDisplacement *= 2.f; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::TrimScrollPosition: Invalid alignment option." ) - } - } - - // Trims the scroll position to be within the range. - mVisualParameters.mCameraScrollPosition.x = std::min( maxHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x ); - mVisualParameters.mCameraScrollPosition.x = std::max( minHorizontalDisplacement, mVisualParameters.mCameraScrollPosition.x ); - - mVisualParameters.mCameraScrollPosition.y = std::min( maxVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y ); - mVisualParameters.mCameraScrollPosition.y = std::max( minVerticalDisplacement, mVisualParameters.mCameraScrollPosition.y ); -} - -void TextView::DoSetScrollPosition( const Vector2& position ) -{ - // Stores old scroll position. - Vector2 delta( mVisualParameters.mCameraScrollPosition ); - - // Updates the scroll position - mVisualParameters.mCameraScrollPosition = position; - - // Ensures the text-view is covered with text. - TrimScrollPosition(); - - // Calculate the difference with the previous scroll position - delta.x = mVisualParameters.mCameraScrollPosition.x - delta.x; - delta.y = mVisualParameters.mCameraScrollPosition.y - delta.y; - - if( mOffscreenRootActor ) - { - // If there is a render-task it needs to be refreshed. Therefore glyph-actors need to be - // set to visible. - mOffscreenRootActor.SetVisible( true ); - } - - if( mOffscreenCameraActor ) - { - // Update the offscreen camera with the new scroll position. - mOffscreenCameraActor.SetX( mVisualParameters.mCameraScrollPosition.x ); - mOffscreenCameraActor.SetY( mVisualParameters.mCameraScrollPosition.y ); - } - - if( mRenderTask ) - { - // Refresh the render-task. - mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); - } - - // Emit the signal. - Toolkit::TextView handle( GetOwner() ); - mScrolledSignal.Emit( handle, delta ); -} - -void TextView::CombineExceedPolicies() -{ - // Calculates the combination of exceed policies. - - switch( mLayoutParameters.mWidthExceedPolicy ) - { - case Toolkit::TextView::Original: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = Original; - break; - } - case Toolkit::TextView::Fade: - { - mLayoutParameters.mExceedPolicy = OriginalFade; - break; - } - case Toolkit::TextView::ShrinkToFit: - { - mLayoutParameters.mExceedPolicy = OriginalShrink; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - case Toolkit::TextView::Split: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = SplitOriginal; - break; - } - case Toolkit::TextView::Fade: - { - mLayoutParameters.mExceedPolicy = SplitFade; - break; - } - case Toolkit::TextView::ShrinkToFit: - { - mLayoutParameters.mExceedPolicy = SplitShrink; - break; - } - case Toolkit::TextView::EllipsizeEnd: - { - mLayoutParameters.mExceedPolicy = SplitEllipsizeEnd; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - case Toolkit::TextView::Fade: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = FadeOriginal; - break; - } - case Toolkit::TextView::Fade: - { - mLayoutParameters.mExceedPolicy = Fade; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - case Toolkit::TextView::ShrinkToFit: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = ShrinkOriginal; - break; - } - case Toolkit::TextView::Fade: - { - mLayoutParameters.mExceedPolicy = ShrinkFade; - break; - } - case Toolkit::TextView::ShrinkToFit: - { - mLayoutParameters.mExceedPolicy = Shrink; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - case Toolkit::TextView::EllipsizeEnd: - { - switch( mLayoutParameters.mHeightExceedPolicy ) - { - case Toolkit::TextView::Original: - { - mLayoutParameters.mExceedPolicy = EllipsizeEndOriginal; - break; - } - case Toolkit::TextView::EllipsizeEnd: - { - mLayoutParameters.mExceedPolicy = EllipsizeEnd; - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width and height exceed policies combination" ); - } - } - break; - } - default: - { - DALI_ASSERT_ALWAYS( !"TextView::CombineExceedPolicies() Invalid width exceed policy" ); - } - } -} - -Actor TextView::GetRootActor() const -{ - // Get the root actor, if text-view was rendering offscreen, or the text-view itself. - - Actor rootActor; - - if( mVisualParameters.mSnapshotModeEnabled ) - { - rootActor = mOffscreenRootActor; - } - else - { - rootActor = Self(); - } - - return rootActor; -} - -void TextView::CreateEllipsizeLayout() -{ - // Creates the ellipsis layout info for the ellipsis text and styles. - mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = TextViewProcessor::WordLayoutInfo(); - mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo.mCharactersLayoutInfo.resize( mRelayoutData.mTextLayoutInfo.mEllipsisText.GetLength(), TextViewProcessor::CharacterLayoutInfo() ); - TextViewProcessor::CreateWordTextInfo( mRelayoutData.mTextLayoutInfo.mEllipsisText, - mRelayoutData.mTextLayoutInfo.mEllipsisTextStyles, - mRelayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo ); -} - -void TextView::OnMarkupEnabledPeopertySet( Property::Value propertyValue ) -{ - bool newValue( propertyValue.Get() ); - if( newValue != IsMarkupProcessingEnabled() ) - { - SetMarkupProcessingEnabled( newValue ); - if( newValue ) - { - // If markup processing has been enabled, Ensure current text is reprocessed. - const std::string& currentText( GetText() ); - if( ! currentText.empty() ) - { - SetText( currentText ); - } - } - } -} - -void TextView::OnMultilinePolicyPropertySet( Property::Value propertyValue ) -{ - std::string policyName( propertyValue.Get() ); - if(policyName == "SplitByNewLineChar") - { - SetMultilinePolicy(Toolkit::TextView::SplitByNewLineChar); - } - else if(policyName == "SplitByWord") - { - SetMultilinePolicy(Toolkit::TextView::SplitByWord); - } - else if(policyName == "SplitByChar") - { - SetMultilinePolicy(Toolkit::TextView::SplitByChar); - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnMultilinePolicyPropertySet(). Invalid Property value." ); - } -} - -void TextView::OnWidthExceedPolicyPropertySet( Property::Value propertyValue ) -{ - std::string policyName( propertyValue.Get() ); - if(policyName == "Original") - { - SetWidthExceedPolicy(Toolkit::TextView::Original); - } - else if(policyName == "Fade") - { - SetWidthExceedPolicy(Toolkit::TextView::Fade); - } - else if(policyName == "Split") - { - SetWidthExceedPolicy(Toolkit::TextView::Split); - } - else if(policyName == "ShrinkToFit") - { - SetWidthExceedPolicy(Toolkit::TextView::ShrinkToFit); - } - else if(policyName == "EllipsizeEnd") - { - SetWidthExceedPolicy(Toolkit::TextView::EllipsizeEnd); - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnWidthExceedPolicyPropertySet(). Invalid Property value." ); - } -} - -void TextView::OnHeightExceedPolicyPropertySet( Property::Value propertyValue ) -{ - std::string policyName( propertyValue.Get() ); - if(policyName == "Original") - { - SetHeightExceedPolicy(Toolkit::TextView::Original); - } - else if(policyName == "Fade") - { - SetHeightExceedPolicy(Toolkit::TextView::Fade); - } - else if(policyName == "Split") - { - SetHeightExceedPolicy(Toolkit::TextView::Split); - } - else if(policyName == "ShrinkToFit") - { - SetHeightExceedPolicy(Toolkit::TextView::ShrinkToFit); - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnHeightExceedPolicyPropertySet(). Invalid Property value." ); - } -} - -void TextView::OnLineJustificationPropertySet( Property::Value propertyValue ) -{ - std::string policyName( propertyValue.Get() ); - if(policyName == "Left") - { - SetLineJustification(Toolkit::TextView::Left); - } - else if(policyName == "Center") - { - SetLineJustification(Toolkit::TextView::Center); - } - else if(policyName == "Right") - { - SetLineJustification(Toolkit::TextView::Right); - } - else if(policyName == "Justified") - { - SetLineJustification(Toolkit::TextView::Justified); - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnLineJustificationPropertySet(). Invalid Property value." ); - } -} - -void TextView::OnFadeBoundaryPropertySet( Property::Value propertyValue ) -{ - Vector4 value( propertyValue.Get() ); - DALI_ASSERT_ALWAYS( ( value.x >= 0.f ) && ( value.y >= 0.f ) && ( value.z >= 0.f ) && ( value.w >= 0.f ) - && "TextView::OnFadeBoundaryPropertySet(). Negative value is invalid. " ); - - Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( static_cast( value.x ) ), - PixelSize( static_cast( value.y ) ), - PixelSize( static_cast( value.z ) ), - PixelSize( static_cast( value.w ) ) ); - - SetFadeBoundary( fadeBoundary ); -} - -void TextView::OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue ) -{ - std::string value( propertyValue.Get() ); - - if( propertyIndex == Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT ) - { - if(value == "HorizontalLeft") - { - mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalLeft; - } - else if( value == "HorizontalCenter") - { - mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalCenter; - } - else if( value == "HorizontalRight") - { - mLayoutParameters.mHorizontalAlignment = Toolkit::Alignment::HorizontalRight; - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." ); - } - } - else if( propertyIndex == Toolkit::TextView::Property::VERTICAL_ALIGNMENT ) - { - if( value == "VerticalTop" ) - { - mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalTop; - } - else if( value == "VerticalCenter") - { - mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalCenter; - } - else if( value == "VerticalBottom") - { - mLayoutParameters.mVerticalAlignment = Toolkit::Alignment::VerticalBottom; - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnAlignmentPropertySet(). Invalid Property value." ); - } - } - - RelayoutRequest(); - - // If a GetTextLayoutInfo() or GetHeightForWidth() arrives, relayout the text synchronously is needed in order to retrieve the right values. - if( RELAYOUT_ALL != mRelayoutOperations ) - { - mRelayoutOperations = static_cast( mRelayoutOperations | - RELAYOUT_TEXT_ACTOR_UPDATE | - RELAYOUT_ALIGNMENT | - RELAYOUT_VISIBILITY ); - } -} - -std::string TextView::OnHorizontalAlignmentPropertyGet() -{ - if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalLeft ) - { - return "HorizontalLeft"; - } - else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalCenter ) - { - return "HorizontalCenter"; - } - else if( mLayoutParameters.mHorizontalAlignment == Toolkit::Alignment::HorizontalRight ) - { - return "HorizontalRight"; - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnHorizontalAlignmentPropertyGet(). Invalid value." ); - } -} - -std::string TextView::OnVerticalAlignmentPropertyGet() -{ - if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalTop ) - { - return "VerticalTop"; - } - else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalCenter ) - { - return "VerticalCenter"; - } - else if( mLayoutParameters.mVerticalAlignment == Toolkit::Alignment::VerticalBottom ) - { - return "VerticalBottom"; - } - else - { - DALI_ASSERT_ALWAYS( !"TextView::OnVerticalAlignmentPropertyGet(). Invalid value." ); - } -} - -void TextView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) -{ - Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) ); - - if( textView ) - { - TextView& textViewImpl( GetImpl( textView ) ); - switch( index ) - { - case Toolkit::TextView::Property::MARKUP_ENABLED: - { - textViewImpl.OnMarkupEnabledPeopertySet( value ); - break; - } - case Toolkit::TextView::Property::TEXT: - { - textViewImpl.SetText( value.Get() ); - break; - } - case Toolkit::TextView::Property::MULTILINE_POLICY: - { - textViewImpl.OnMultilinePolicyPropertySet( value ); - break; - } - case Toolkit::TextView::Property::WIDTH_EXCEED_POLICY: - { - textViewImpl.OnWidthExceedPolicyPropertySet( value ); - break; - } - case Toolkit::TextView::Property::HEIGHT_EXCEED_POLICY: - { - textViewImpl.OnHeightExceedPolicyPropertySet( value ); - break; - } - case Toolkit::TextView::Property::LINE_JUSTIFICATION: - { - textViewImpl.OnLineJustificationPropertySet( value ); - break; - } - case Toolkit::TextView::Property::FADE_BOUNDARY: - { - textViewImpl.OnFadeBoundaryPropertySet( value ); - break; - } - case Toolkit::TextView::Property::LINE_HEIGHT_OFFSET: - { - Dali::PointSize pointSize( value.Get() ); - textViewImpl.SetLineHeightOffset(pointSize); - break; - } - case Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT: - case Toolkit::TextView::Property::VERTICAL_ALIGNMENT: - { - textViewImpl.OnAlignmentPropertySet( index, value ); - break; - } - } - } -} - -Property::Value TextView::GetProperty( BaseObject* object, Property::Index index ) -{ - Property::Value value; - - Toolkit::TextView textView = Toolkit::TextView::DownCast( Dali::BaseHandle( object ) ); - - if( textView ) - { - TextView& textViewImpl( GetImpl( textView ) ); - switch( index ) - { - case Toolkit::TextView::Property::MARKUP_ENABLED: - { - value = textViewImpl.IsMarkupProcessingEnabled(); - break; - } - case Toolkit::TextView::Property::TEXT: - { - value = textViewImpl.GetText(); - break; - } - case Toolkit::TextView::Property::MULTILINE_POLICY: - { - value = MULTILINE_POLICY_NAME[ textViewImpl.GetMultilinePolicy() ]; - break; - } - case Toolkit::TextView::Property::WIDTH_EXCEED_POLICY: - { - value = EXCEED_POLICY_NAME[ textViewImpl.GetWidthExceedPolicy() ]; - break; - } - case Toolkit::TextView::Property::HEIGHT_EXCEED_POLICY: - { - value = EXCEED_POLICY_NAME[ textViewImpl.GetHeightExceedPolicy() ]; - break; - } - case Toolkit::TextView::Property::LINE_JUSTIFICATION: - { - value = LINE_JUSTIFICATION_NAME[ textViewImpl.GetLineJustification() ]; - break; - } - case Toolkit::TextView::Property::FADE_BOUNDARY: - { - Toolkit::TextView::FadeBoundary boundary = textViewImpl.GetFadeBoundary(); - value = Vector4( static_cast( boundary.mLeft.value ), - static_cast( boundary.mRight.value ), - static_cast( boundary.mTop.value ), - static_cast( boundary.mBottom.value ) ); - break; - } - case Toolkit::TextView::Property::LINE_HEIGHT_OFFSET: - { - value = textViewImpl.GetLineHeightOffset().value; - break; - } - case Toolkit::TextView::Property::HORIZONTAL_ALIGNMENT: - { - value = textViewImpl.OnHorizontalAlignmentPropertyGet(); - break; - } - case Toolkit::TextView::Property::VERTICAL_ALIGNMENT: - { - value = textViewImpl.OnVerticalAlignmentPropertyGet(); - break; - } - } - } - return value; -} - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-impl.h b/dali-toolkit/internal/controls/text-view/text-view-impl.h deleted file mode 100644 index 270d32b..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-impl.h +++ /dev/null @@ -1,770 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_H__ - -/* - * Copyright (c) 2014 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 -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -/** - * TextView is a custom control for text aligning and multiline support - */ -class TextView : public Control -{ -public: - - /** - * Internal exceed policy with the valid combinations. - */ - enum ExceedPolicy - { - Original, ///< Original size (even if it exceeds the witdh or the height). - OriginalFade, ///< Original size if it exceeds the width but faded if it exceeds the height. - OriginalShrink, ///< Shrunk if it exceeds the height. - SplitOriginal, ///< Split if it exceeds the width but no action if it exceeds the height. - SplitFade, ///< Split if it exceeds the width and faded if it exceeds the height. - SplitShrink, ///< Split if it exceeds the width and shrunk if it exceeds the height. - SplitEllipsizeEnd, ///< Split if it exceeds the width and ellipsize if it exceeds the height. - Fade, ///< Faded if it exceeds any boundary. - FadeOriginal, ///< Faded if it exceeds the width but no action if it exceeds the height. - ShrinkOriginal, ///< Shrunk if it exceeds the width but no action if it exceeds the height. - ShrinkFade, ///< Shrunk if it exceeds the width and faded if it exceeds the height. - Shrink, ///< Shrunk if it exceeds any boundary. - EllipsizeEndOriginal, ///< Ellipsized by the end if it exceeds the width but no action if it exceeds the height. - EllipsizeEnd ///< Ellipsized by the end if it exceeds the width and/or the height. - }; - - // Between two OnRelayout methods, several calls to InsertTextAt, RemoveTextFrom or SetText can happen. - // TextViewProcessorMetadata stores the type of operation. A vector stores all operations between two OnRelayout calls. - - enum TextViewProcessorMetadataType - { - TextSet, ///< Sets new text. - TextInserted, ///< Inserts text into current text. - TextReplaced, ///< Replaces some text from current text. - TextRemoved, ///< Removes some text from current text. - NewLineHeight, ///< Sets a new line height offset. - NewStyle ///< Sets a new style to the whole text. - }; - - /** - * Stores info about which data structures need to be modified when the OnRelayout() method is called - */ - struct TextViewProcessorMetadata - { - TextViewProcessorMetadata(); - - TextViewProcessorMetadataType mType; ///< Stores the type of operation. - std::size_t mPosition; ///< Character position within the text. - std::size_t mNumberOfCharacters; ///< Number of characters to be removed/replaced. - MarkupProcessor::StyledTextArray mText; ///< The new text. - TextStyle::Mask mStyleMask; ///< The style mask. - }; - - /** - * Defines which operations have to be done in the relayout process. - */ - enum RelayoutOperationMask - { - NO_RELAYOUT = 0x0, ///< Does nothing. - RELAYOUT_REMOVE_TEXT_ACTORS = 0x1, ///< Removes current text-actors from the text-view. - RELAYOUT_SIZE_POSITION = 0x2, ///< Calculates size and position of the text but it doesn't calculate alignment. - RELAYOUT_ALIGNMENT = 0x4, ///< Aligns the whole text. - RELAYOUT_VISIBILITY = 0x8, ///< Calculates the visibility. - RELAYOUT_INITIALIZE_TEXT_ACTORS = 0x10, ///< Initialize text-actors (create handles). - RELAYOUT_TEXT_ACTOR_UPDATE = 0x20, ///< Updates text-actors (set size, position, style, ...) - RELAYOUT_INSERT_TO_TEXT_VIEW = 0x40, ///< Adds the text-actors to the text-view. - RELAYOUT_ALL = 0xFF ///< Does all operations. - }; - - ////////////////////////////////////////////// - - /** - * Create a new TextView. - * @return A smart-pointer to the newly allocated TextView. - */ - static Toolkit::TextView New(); - - /** - * @copydoc SetText( const std::string& text ) - */ - void SetText( const std::string& text ); - - /** - * @copydoc SetText( const StyledTextArray& text ) - */ - void SetText( const MarkupProcessor::StyledTextArray& text ); - - /** - * @copydoc InsertTextAt( std::size_t position, const std::string& text ) - */ - void InsertTextAt( std::size_t position, const std::string& text ); - - /** - * @copydoc InsertTextAt( std::size_t position, const std::string& text ) - */ - void InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text ); - - /** - * @copydoc RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ) - */ - void RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ); - - /** - * @copydoc ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ) - */ - void ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ); - - /** - * @copydoc ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ) - */ - void ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text ); - - /** - * @copydoc GetText() - */ - std::string GetText() const; - - /** - * @copydoc SetLineHeightOffset() - */ - void SetLineHeightOffset( PointSize offset ); - - /** - * @copydoc GetLineHeightOffset() - */ - PointSize GetLineHeightOffset() const; - - /** - * @copydoc SetStyleToCurrentText() - */ - void SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask ); - - /** - * @copydoc SetTextAlignment( Toolkit::Alignment::Type align ) - */ - void SetTextAlignment( Toolkit::Alignment::Type align ); - - /** - * @copydoc GetTextAlignment() - */ - Toolkit::Alignment::Type GetTextAlignment() const; - - /** - * @copydoc SetMultilinePolicy() - */ - void SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ); - - /** - * @copydoc GetMultilinePolicy() - */ - Toolkit::TextView::MultilinePolicy GetMultilinePolicy() const; - - /** - * @copydoc SetWidthExceedPolicy() - */ - void SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @copydoc GetWidthExceedPolicy() - */ - Toolkit::TextView::ExceedPolicy GetWidthExceedPolicy() const; - - /** - * @copydoc SetHeightExceedPolicy() - */ - void SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @copydoc GetHeightExceedPolicy() - */ - Toolkit::TextView::ExceedPolicy GetHeightExceedPolicy() const; - - /** - * @copydoc SetLineJustification() - */ - void SetLineJustification( Toolkit::TextView::LineJustification justification ); - - /** - * @copydoc GetLineJustification() - */ - Toolkit::TextView::LineJustification GetLineJustification() const; - - /** - * @copydoc SetFadeBoundary() - */ - void SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ); - - /** - * @copydoc GetFadeBoundary() - */ - const Toolkit::TextView::FadeBoundary& GetFadeBoundary() const; - - /** - * @copydoc SetEllipsizeText() - */ - void SetEllipsizeText( const std::string& ellipsizeText ); - - /** - * @copydoc SetEllipsizeText() - */ - void SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText ); - - /** - * @copydoc SetEllipsizeText() - */ - void SetEllipsizeText( const Text& ellipsizeText, const Vector& ellipsizeStyles ); - - /** - * @copydoc GetEllipsizeText() - */ - std::string GetEllipsizeText() const; - - /** - * Checks if relayout the text is needed. If it is, it relais out the text - * by calling DoRelayOut(). - */ - void GetTextLayoutInfo(); - - /** - * Calls GetTextLayoutInfo() and fills the given data structure. - * - * @see GetTextLayoutInfo() - */ - void GetTextLayoutInfo( Toolkit::TextView::TextLayoutInfo& textLayoutInfo ); - - /** - * @copydoc SetSortModifier() - */ - void SetSortModifier( float depthOffset ); - - /** - * @copydoc SetSnapshotModeEnabled() - */ - void SetSnapshotModeEnabled( bool enable ); - - /** - * @copydoc IsSnapshotModeEnabled() - */ - bool IsSnapshotModeEnabled() const; - - /** - * @brief Sets whether markup processing should be carried out. - * - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ); - - /** - * @brief Returns whether markup processing is enabled or not - * - * @return true is markup processing is enabled - */ - bool IsMarkupProcessingEnabled() const; - - /** - * @copydoc SetScrollEnabled() - */ - void SetScrollEnabled( bool enable ); - - /** - * @copydoc IsScrollEnabled() - */ - bool IsScrollEnabled() const; - - /** - * @copydoc SetScrollPosition() - * @see DoSetScrollPosition() - */ - void SetScrollPosition( const Vector2& position ); - - /** - * @copydoc GetScrollPosition() - */ - const Vector2& GetScrollPosition() const; - - /** - * @copydoc IsScrollPositionTrimmed() - */ - bool IsScrollPositionTrimmed() const; - - /** - * @copydoc ScrolledSignal() - */ - Toolkit::TextView::ScrolledSignalType& ScrolledSignal(); - - /** - * Connects a callback function with the object's signals. - * @param[in] object The object providing the signal. - * @param[in] tracker Used to disconnect the signal. - * @param[in] signalName The signal to connect to. - * @param[in] functor A newly allocated FunctorDelegate. - * @return True if the signal was connected. - * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor. - */ - static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ); - - // Properties - - /** - * Called when a property of an object of this type is set. - * @param[in] object The object whose property is set. - * @param[in] index The property index. - * @param[in] value The new property value. - */ - static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ); - - /** - * Called to retrieve a property of an object of this type. - * @param[in] object The object whose property is to be retrieved. - * @param[in] index The property index. - * @return The current value of the property. - */ - static Property::Value GetProperty( BaseObject* object, Property::Index index ); - - -private: // From Control - - /** - * @copydoc Toolkit::Control::OnInitialize() - */ - virtual void OnInitialize(); - - /** - * @copydoc Toolkit::Control::OnFontChange( ) - */ - virtual void OnFontChange( bool defaultFontChange, bool defaultFontSizeChange ); - - /** - * @copydoc Toolkit::Control::OnControlSizeSet() - */ - virtual void OnControlSizeSet( const Vector3& size ); - - /** - * @copydoc Toolkit::Control::OnRelayout() - */ - virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); - - /** - * Retrieves the text-view's natural size. - * - * @return The natural size. - */ - virtual Vector3 GetNaturalSize(); - - /** - * Retrieves the text-view's \e height for a given \e width. - * - * @param[in] width The given \e width. - * - * @return The \e height for the given \e width. - */ - virtual float GetHeightForWidth( float width ); - - /** - * Retrieves the text-view's \e width for a given \e height. - * - * @param[in] height The given \e height. - * - * @return The \e width for the given \e height. - */ - virtual float GetWidthForHeight( float height ); - -protected: - - /** - * Construct a new TextView. - */ - TextView(); - - /** - * A reference counted object may only be deleted by calling Unreference() - */ - virtual ~TextView(); - -private: - - // Undefined - TextView( const TextView& ); - - // Undefined - TextView& operator=( const TextView& rhs ); - - /** - * Executes synchronously relayout operations such as set, insert, remove or replace text, etc. - */ - void PerformTextViewProcessorOperations(); - - /** - * Optimizes some text-view processor operations. - */ - void OptimizeTextViewProcessorOperations(); - - /** - * Synchronously relays-out all text-actors. - * - * Perform text-view-processor operations, sets the new size and position of text-actors and adds them to the text-view. - * - * @param[in] textViewSize The new text-view's size. - * @param[in] relayoutOperationMask Defines which operations need to be done in the relayout process. - */ - void DoRelayOut( const Size& textViewSize, RelayoutOperationMask relayoutOperationMask ); - - /** - * Process Snapshot. It refresh the render-task in order to generate a new snapshot image. - * - * ProcessSnapshot is called from OnRelayout() only if text has been relaid out. - * It creates a new image buffer only if the size of the text has changed. - * - * @param[in] textViewSize The new text-view's size. - */ - void ProcessSnapshot( const Size& textViewSize ); - - /** - * Aligns the offscreen rendering camera actor to cover the whole text and the resulting image actor accordingly with the text view's alignment. - * - * @param[in] textViewSize The text view's size. - * @param[in] offscreenSize The offscreen's frame buffer's size. - */ - void AlignOffscreenCameraActor( const Size& textViewSize, const Size& offscreenSize ); - - /** - * Callback called when the render task has processed. - * - * It makes the root actor invisible. - * - * @param[in] renderTask The processed render task. - */ - void RenderTaskFinished( Dali::RenderTask& renderTask ); - - /** - * Destroys offscreen rendering resources. - * - * It disconects the render task finished signal from the TextView::RenderTaskFinished() method, - * removes the render task from the render task list and resets the offscreen camera actor, root actor, - * image actor and the frame buffer. - */ - void DestroyOffscreenRenderingResources(); - - /** - * Called when text-view is scrolled. - * - * Sets the new scroll position. @see DoSetScrollPosition() - * - * @param[in] actor Handle of the text-view. - * @param[in] gesture Data structure with the parameters of the gesture. - */ - void OnTextPan( Actor actor, const PanGesture& gesture ); - - /** - * Ensures the text-view's boundaries are fully covered of text. - * - * i.e. if the text-view's size is 100x100 and the text's size is 150x100, the scroll position - * can be in the range -50,0 and 50,0. - */ - void TrimScrollPosition(); - - /** - * Called from SetScrollPosition() and OnTextPan() - * - * Updates the stored scroll position ensuring the text-view is always covered with text by calling - * TrimScrollPosition(), calculates the difference with the previous one and emits the Toolkit::TextView::SignalScrolled() signal. - * - * @param[in] position The new scroll position. - */ - void DoSetScrollPosition( const Vector2& position ); - - /** - * Combines width and height exceed policies. - * - * This method is a big switch() which combines two exceed policies into one. - * The aim is avoid this switch inside the relayout code. - * - * i.e. Width policy = Split. Height policy = Original. Internally the policy is SplitOriginal. - */ - void CombineExceedPolicies(); - - /** - * Retrieves the text-view's root actor which stores all text-actors. - * It could be the text-view itself or an actor used in the snapshot mode. - * - * @return the root actor. - */ - Actor GetRootActor() const; - - /** - * Creates the ellipsize text layout. - */ - void CreateEllipsizeLayout(); - - /** - * Handle SetProperty for markup processing. - * @param[in] propertyValue The new property value. - */ - void OnMarkupEnabledPeopertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for multiline policy. - * @param[in] propertyValue The new property value. - */ - void OnMultilinePolicyPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for width exceed policy. - * @param[in] propertyValue The new property value. - */ - void OnWidthExceedPolicyPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for height exceed policy. - * @param[in] propertyValue The new property value. - */ - void OnHeightExceedPolicyPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for line justification. - * @param[in] propertyValue The new property value. - */ - void OnLineJustificationPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for fade boundary. - * @param[in] propertyValue The new property value. - */ - void OnFadeBoundaryPropertySet( Property::Value propertyValue ); - - /** - * Handles SetProperty for alignment property. - * @param[in] propertyIndex The property index. - * @param[in] propertyValue The new property value. - */ - void OnAlignmentPropertySet( Property::Index propertyIndex, Property::Value propertyValue ); - - /** - * Handles GetProperty for horizontal alignment property. - * @return The property value of horizontal alignment. - */ - std::string OnHorizontalAlignmentPropertyGet(); - - /** - * Handles GetProperty for vertical alignment property. - * @return The property value of vertical alignment. - */ - std::string OnVerticalAlignmentPropertyGet(); - -public: - - /** - * The parameters which affects the layout of the text. - */ - struct LayoutParameters - { - /** - * Default constructor. - */ - LayoutParameters(); - - /** - * Default destructor. - */ - ~LayoutParameters(); - - /** - * Constructor - */ - LayoutParameters( Toolkit::TextView::MultilinePolicy multilinePolicy, - Toolkit::TextView::ExceedPolicy widthExceedPolicy, - Toolkit::TextView::ExceedPolicy heightExceedPolicy, - Toolkit::Alignment::Type alignment, - Toolkit::TextView::LineJustification lineJustification, - float lineHeightOffset, - bool markUpEnabled ); - - /** - * Copy constructor - */ - LayoutParameters( const LayoutParameters& layoutParameters ); - - /** - * Assignment operator. - */ - LayoutParameters& operator=( const LayoutParameters& layoutParameters ); - - Toolkit::TextView::MultilinePolicy mMultilinePolicy; ///< Stores the multiline policy. - TextView::ExceedPolicy mExceedPolicy; ///< Stores a combination of both policies. - Toolkit::TextView::ExceedPolicy mWidthExceedPolicy; ///< Stores the text width exceed policy. - Toolkit::TextView::ExceedPolicy mHeightExceedPolicy; ///< Stores the text height exceed policy. - Toolkit::Alignment::Type mHorizontalAlignment; ///< Stores the horizontal alignment for the whole text. - Toolkit::Alignment::Type mVerticalAlignment; ///< Stores the vertical alignment for the whole text. - Toolkit::TextView::LineJustification mLineJustification; ///< Stores the line justification. - float mLineHeightOffset; ///< Line height offset to be addded to the font line height (measured in PointSize). - bool mMarkUpEnabled:1; ///< Is markup string scanning enabled. - }; - - /** - * Some parameters which affects the text view visualization. - */ - struct VisualParameters - { - /** - * Default constructor. - */ - VisualParameters(); - - /** - * Copy constructor. - */ - VisualParameters( const VisualParameters& visualParameters ); - - /** - * Assignment operator. - */ - VisualParameters& operator=( const VisualParameters& visualParameters ); - - Toolkit::TextView::FadeBoundary mFadeBoundary; ///< Fade boundary used in fade mode. - float mSortModifier; ///< Stores the sort modifier for all text-actors. - Vector2 mCameraScrollPosition; ///< The scroll offset. - bool mSnapshotModeEnabled:1; ///< Whether text-view is rendered offscreen. - bool mScrollEnabled:1; ///< Whether the text scroll is enabled. - bool mScrollPositionTrimmed:1; ///< Whether the last scroll position set was trimmed. - }; - - /** - * The results of the relayout process. - */ - struct RelayoutData - { - /** - * Default constructor. - */ - RelayoutData(); - - /** - * Copy constructor - */ - RelayoutData( const RelayoutData& relayoutData ); - - /** - * Assignment operator. - */ - RelayoutData& operator=( const RelayoutData& relayoutData ); - - Size mTextViewSize; ///< The text-view's size used to relaid-out the text. - float mShrinkFactor; ///< Shrink factor used when the exceed policy contains ShrinkToFit. - TextViewProcessor::TextLayoutInfo mTextLayoutInfo; ///< Stores metrics, layout info (size, direction, type of word) and text-actor info for the whole text. - std::vector mCharacterLogicalToVisualMap; ///< Reorder map that stores each character's visual (output) index according to its logical (input) index - std::vector mCharacterVisualToLogicalMap; ///< Reorder map that stores each character's logical (input) index according to its visual (output) index - std::vector mGlyphActors; ///< Stores handles of those text-actors which are currently added to the text-view. - std::vector mEllipsizedGlyphActors; ///< Stores handles of those text-actors which are used to ellipsize the text. - Toolkit::TextView::CharacterLayoutInfoContainer mCharacterLayoutInfoTable; ///< Stores layout info per character sorted by the character's visual index. - Toolkit::TextView::LineLayoutInfoContainer mLines; ///< Stores an index to the first character of each line. - Size mTextSizeForRelayoutOption; ///< Stores the text size after relayout. - TextActorCache mTextActorCache; ///< Stores previously created text-actors to be reused. - }; - -private: - - MarkupProcessor::StyledTextArray mCurrentStyledText; ///< text currently displayed by the view - std::vector mTextViewProcessorOperations; ///< Stores all relayout operations which arrive between two consecutive OnRelayout() calls. - - LayoutParameters mLayoutParameters; ///< Stores some layout parameters in a struct. To be passed in layout functions. - VisualParameters mVisualParameters; ///< Some parameters which afects text-view visualization. - RelayoutData mRelayoutData; ///< struct with text-view's data structures used to pass all of them in one parameter. - RelayoutOperationMask mRelayoutOperations; ///< Which relayout operations have to be done. - - Layer mOffscreenRootActor; ///< Root actor for offscreen rendering. - ImageActor mOffscreenImageActor; ///< Image actor for offscreen rendering. - CameraActor mOffscreenCameraActor; ///< Camera actor for offscreen rendering. - Size mCurrentOffscreenSize; ///< Current used ofscreen size. - FrameBufferImage mFrameBufferImage; ///< Frame buffer used for offscreen rendering. - RenderTask mRenderTask; ///< Used to generate an offscreen rendering. - - PanGestureDetector mPanGestureDetector; ///< Pan gesture for text scrolling. - - /** - * Helper class used to prevent the modification of some members. - */ - struct Lock - { - Lock( bool& lock ) - : mLock( lock ) - { - mLock = true; - } - - ~Lock() - { - mLock = false; - } - - bool& mLock; - }; - - bool mLockPreviousSnapshotMode; ///< Whether previous stored snapshot mode should be modified. - bool mPreviousSnapshotModeEnabled:1; ///< Stores the previous snapshot mode value. - bool mMarkUpEnabled:1; ///< enable to scan for mark-up - - Toolkit::TextView::ScrolledSignalType mScrolledSignal; ///< Signal emitted when text is scrolled. -}; - -} // namespace Internal - -// Helpers for public-api forwarding methods - -inline Internal::TextView& GetImpl( TextView& textView ) -{ - DALI_ASSERT_ALWAYS( textView ); - - RefObject& handle = textView.GetImplementation(); - - return static_cast< Internal::TextView& >( handle ); -} - -inline const Internal::TextView& GetImpl( const TextView& textView ) -{ - DALI_ASSERT_ALWAYS( textView ); - - const RefObject& handle = textView.GetImplementation(); - - return static_cast< const Internal::TextView& >( handle ); -} - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_ITEM_VIEW_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.cpp b/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.cpp deleted file mode 100644 index 70a0309..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.cpp +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (c) 2014 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 - -// INTERNAL INCLUDES -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -///////////////////// -// Layout info. -///////////////////// - -void RightToLeftParagraphLayout::Clear() -{ - mWordsLayoutInfo.clear(); - mText = Text(); - mTextStyles.Clear(); -} - -ParagraphLayoutInfo::ParagraphLayoutInfo() -: mSize(), - mAscender( 0.f ), - mLineHeightOffset( 0.f ), - mFirstCharacter( 0u ), - mNumberOfCharacters( 0u ), - mWordsLayoutInfo(), - mText(), - mTextStyles(), - mRightToLeftLayout( NULL ), - mBidirectionalParagraphInfo( NULL ), - mBidirectionalLinesInfo() -{ -} - -ParagraphLayoutInfo::~ParagraphLayoutInfo() -{ - if( NULL != mRightToLeftLayout ) - { - // TextStyle pointers are the same than the ones stored at ParagraphLayoutInfo::mTextStyles. - // Do not delete them, just clear the vector. - mRightToLeftLayout->mTextStyles.Clear(); - - delete mRightToLeftLayout; - } - - // Clears text styles. It destroys TextStyle objects. - ClearStyles(); - - // Deletes the bidirectional info for the whole paragraph. - delete mBidirectionalParagraphInfo; - - // Clears the bidirectional info for all lines. Destroys the BidirectionalLineInfo objects. - ClearBidirectionalInfo(); -} - -ParagraphLayoutInfo::ParagraphLayoutInfo( const ParagraphLayoutInfo& paragraph ) -: mSize( paragraph.mSize ), - mAscender( paragraph.mAscender ), - mLineHeightOffset( paragraph.mLineHeightOffset ), - mFirstCharacter( paragraph.mFirstCharacter ), - mNumberOfCharacters( paragraph.mNumberOfCharacters ), - mWordsLayoutInfo( paragraph.mWordsLayoutInfo ), - mText( paragraph.mText ), - mTextStyles(), - mRightToLeftLayout( NULL ), - // Copies bidirectional info for the whole paragraph. - mBidirectionalParagraphInfo( ( NULL == paragraph.mBidirectionalParagraphInfo ) ? NULL : new TextProcessor::BidirectionalParagraphInfo( *paragraph.mBidirectionalParagraphInfo ) ), - mBidirectionalLinesInfo() -{ - // Copies styles. - for( Vector::ConstIterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it ) - { - mTextStyles.PushBack( new TextStyle( *(*it) ) ); - } - - // Copies bidirectional info for each line. - for( Vector::ConstIterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - mBidirectionalLinesInfo.PushBack( new TextProcessor::BidirectionalLineInfo( *( *it ) ) ); - } -} - -ParagraphLayoutInfo& ParagraphLayoutInfo::operator=( const ParagraphLayoutInfo& paragraph ) -{ - mSize = paragraph.mSize; - mAscender = paragraph.mAscender; - mLineHeightOffset = paragraph.mLineHeightOffset; - mFirstCharacter = paragraph.mFirstCharacter; - mNumberOfCharacters = paragraph.mNumberOfCharacters; - mWordsLayoutInfo = paragraph.mWordsLayoutInfo; - mText = paragraph.mText; - - // If it has styles, destroy them. - ClearStyles(); - - // Copies styles. - for( Vector::ConstIterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it ) - { - mTextStyles.PushBack( new TextStyle( *(*it) ) ); - } - - // Copies the paragraph's bidirectiona info. - if( NULL == paragraph.mBidirectionalParagraphInfo ) - { - // The source doesn't have bidirectiona info. Deletes the current one. - delete mBidirectionalParagraphInfo; - mBidirectionalParagraphInfo = NULL; - } - else - { - // The source has bidirectional info. - if( NULL != mBidirectionalParagraphInfo ) - { - // It it has, copy to it. - *mBidirectionalParagraphInfo = *paragraph.mBidirectionalParagraphInfo; - } - else - { - // If it doesn't have, create a new one. - mBidirectionalParagraphInfo = new TextProcessor::BidirectionalParagraphInfo( *paragraph.mBidirectionalParagraphInfo ); - } - } - - // If it has bidirectiona info per line, destroy them. - ClearBidirectionalInfo(); - - // Copies bidirectional info per line. - for( Vector::ConstIterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - mBidirectionalLinesInfo.PushBack( new TextProcessor::BidirectionalLineInfo( *( *it ) ) ); - } - - return *this; -} - -void ParagraphLayoutInfo::ClearBidirectionalInfo() -{ - // Destroys the bidirectional infor per line. - for( Vector::Iterator it = mBidirectionalLinesInfo.Begin(), endIt = mBidirectionalLinesInfo.End(); it != endIt; ++it ) - { - delete *it; - } - mBidirectionalLinesInfo.Clear(); -} - -void ParagraphLayoutInfo::ClearStyles() -{ - // Destroys the styles. - for( Vector::Iterator it = mTextStyles.Begin(), endIt = mTextStyles.End(); it != endIt; ++it ) - { - delete *it; - } - mTextStyles.Clear(); -} - -void CreateParagraphInfo( TextView::RelayoutData& relayoutData, - ParagraphLayoutInfo& paragraphLayoutInfo ) -{ - if( TextProcessor::ContainsRightToLeftCharacter( paragraphLayoutInfo.mText ) ) - { - // If the text is bidirectional, the characters will be converted and reordered - // as specified by the Unicode Bidirectional Algorithm. - - paragraphLayoutInfo.mBidirectionalParagraphInfo = new TextProcessor::BidirectionalParagraphInfo(); - - TextProcessor::ProcessBidirectionalText( paragraphLayoutInfo.mText, paragraphLayoutInfo.mBidirectionalParagraphInfo ); - } - - // Split the paragraph in words. It retrieves the positions of white spaces and the last '\n' if there is one. - Vector positions; - TextProcessor::SplitInWords( paragraphLayoutInfo.mText, positions ); - - const std::size_t lastCharacterIndex = paragraphLayoutInfo.mText.GetLength() - 1u; - const bool isLastCharacterParagraphSeparator = paragraphLayoutInfo.mText.IsNewLine( lastCharacterIndex ); - - // The number of words is ~the number of white spaces found + 1u. - // White spaces are also words. - // New line characters are also white spaces. If the last character is a white space the +1 is not needed. - const std::size_t numberOfWords = 2u * positions.Count() + ( isLastCharacterParagraphSeparator ? 0u : 1u ); - - // Reserve space for all the words. - paragraphLayoutInfo.mWordsLayoutInfo.resize( numberOfWords, WordLayoutInfo() ); - - // Traverses all positions creating and setting all character layout info objects to every word. - std::size_t wordIndex = 0u; - Vector::ConstIterator positionIt = positions.Begin(); - Vector::ConstIterator positionEndIt = positions.End(); - std::size_t from = 0u; - for( std::size_t positionIndex = 0u, size = positions.Count() + 1u; positionIndex < size; ++positionIndex ) - { - const bool isEndPosition = positionIt == positionEndIt; - const std::size_t to = isEndPosition ? lastCharacterIndex + 1u : *positionIt; - - if( from < to ) - { - // The word is not a white space. - WordLayoutInfo& wordLayoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex ); - ++wordIndex; - // Sets the index within the paragraph to the first character of the word. - wordLayoutInfo.mFirstCharacter = from; - // Creates character layout info objects. - wordLayoutInfo.mCharactersLayoutInfo.resize( ( to - from ), CharacterLayoutInfo() ); - } - - if( !isEndPosition ) - { - // Create a word for the white space. - WordLayoutInfo& wordLayoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex ); - ++wordIndex; - // Sets the index within the paragraph to the white space. - wordLayoutInfo.mFirstCharacter = to; - wordLayoutInfo.mType = WordSeparator; - - CharacterLayoutInfo characterLayoutInfo; - wordLayoutInfo.mCharactersLayoutInfo.push_back( characterLayoutInfo ); - } - - from = to + 1u; - - if( !isEndPosition ) - { - // next white space position. - ++positionIt; - } - else - { - // All white space positiona have been traversed. - // It may be some extra words. i.e if the text is \n. - // Erase them. - paragraphLayoutInfo.mWordsLayoutInfo.erase( paragraphLayoutInfo.mWordsLayoutInfo.begin() + wordIndex, paragraphLayoutInfo.mWordsLayoutInfo.end() ); - - // Check if the last character is a new paragraph character. - if( isLastCharacterParagraphSeparator ) - { - ( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ).mType = ParagraphSeparator; - } - } - } - - // Traverse all words and fill the layout info. - for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it ) - { - WordLayoutInfo& wordLayoutInfo( *it ); - - CreateWordTextInfo( paragraphLayoutInfo.mText, - paragraphLayoutInfo.mTextStyles, - wordLayoutInfo ); - - // Update layout info for the current paragraph. - UpdateSize( paragraphLayoutInfo.mSize, wordLayoutInfo.mSize ); - paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, wordLayoutInfo.mAscender ); - paragraphLayoutInfo.mNumberOfCharacters += wordLayoutInfo.mCharactersLayoutInfo.size(); - - // Update the max word width figure. - relayoutData.mTextLayoutInfo.mMaxWordWidth = std::max( relayoutData.mTextLayoutInfo.mMaxWordWidth, wordLayoutInfo.mSize.width ); - } // end of words -} - -void UpdateLayoutInfo( ParagraphLayoutInfo& paragraphLayoutInfo, float lineHeightOffset ) -{ - // Update layout info. - - // Initialize members to be updated. - paragraphLayoutInfo.mSize = Size::ZERO; - paragraphLayoutInfo.mAscender = 0.f; - paragraphLayoutInfo.mNumberOfCharacters = 0u; - - // Traverses all words. - for( WordLayoutInfoContainer::iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - it != endIt; - ++it ) - { - WordLayoutInfo& word( *it ); - - // Sets the index within the paragraph to the first character of the word. - word.mFirstCharacter = paragraphLayoutInfo.mNumberOfCharacters; - - // Updates the paragraph's size. - UpdateSize( paragraphLayoutInfo.mSize, word.mSize ); - - // Updates the paragraph's max asender. - paragraphLayoutInfo.mAscender = std::max( paragraphLayoutInfo.mAscender, word.mAscender ); - - // Updates the paragraph's number of characters. - paragraphLayoutInfo.mNumberOfCharacters += word.mCharactersLayoutInfo.size(); - } - - // Sets the line height offset. - paragraphLayoutInfo.mSize.height += lineHeightOffset; - paragraphLayoutInfo.mLineHeightOffset = lineHeightOffset; -} - -void RemoveWordsFromParagraph( std::size_t wordIndex, - std::size_t numberOfWords, - float lineHeightOffset, - ParagraphLayoutInfo& paragraphLayout ) -{ - // Removes words from a paragraph. - - // * Check if words or paragraphs can be merged after removing a number of words or a paragraph separator needs to be done outside this method. - - // Remove words from layout info. - paragraphLayout.mWordsLayoutInfo.erase( paragraphLayout.mWordsLayoutInfo.begin() + wordIndex, - paragraphLayout.mWordsLayoutInfo.begin() + ( wordIndex + numberOfWords ) ); - - UpdateLayoutInfo( paragraphLayout, lineHeightOffset ); -} - -void RemoveCharactersFromParagraphInfo( TextView::RelayoutData& relayoutData, - const std::size_t numberOfCharacters, - bool& mergeWords, - bool& mergeParagraphs, - TextInfoIndices& textInfoIndicesBegin, - TextInfoIndices& textInfoIndicesEnd, - TextInfoIndices& textInfoMergeIndicesBegin, - TextInfoIndices& textInfoMergeIndicesEnd, - ParagraphLayoutInfo& paragraphLayout, - std::vector& removedTextActorsFromFirstWord, - std::vector& removedTextActorsFromLastWord ) -{ - const TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo; - - if( textInfoIndicesBegin.mWordIndex < textInfoIndicesEnd.mWordIndex ) - { - // Deleted text is from different words. The two different words may be merged. - - // Get first word. - WordLayoutInfo& firstWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex ) ); - - // Get last word. - WordLayoutInfo& lastWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) ); - - // whether first or last word need to be split and merged. - bool mergeFromBegin = false; - bool mergeToEnd = false; - - if( textInfoIndicesBegin.mCharacterIndex > 0u ) - { - // First word is going to be split. It could be merged with the last word. - mergeFromBegin = true; - textInfoMergeIndicesBegin.mWordIndex = textInfoIndicesBegin.mWordIndex; - } - else if( ( textInfoIndicesBegin.mCharacterIndex == 0u ) && ( textInfoIndicesBegin.mWordIndex > 0u ) ) - { - // First word is going to be removed completely. - // Check if previous word could be merged. - - // Get word before. - WordLayoutInfo& previousWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex - 1u ) ); - if( WordSeparator != previousWordLayout.mType ) - { - // Previous word is not a word separator, so could be merged. - mergeFromBegin = true; - textInfoMergeIndicesBegin.mWordIndex = textInfoIndicesBegin.mWordIndex - 1u; - } - } - - if( mergeFromBegin ) - { - // First word (or previous one) could be merged. Check if last one could be merged as well. - - if( textInfoIndicesEnd.mCharacterIndex + 1u < lastWordLayout.mCharactersLayoutInfo.size() ) - { - // Last word is going to be split. It could be merged with the first word. - mergeToEnd = true; - textInfoMergeIndicesEnd.mWordIndex = textInfoIndicesEnd.mWordIndex; - } - else if( ( textInfoIndicesEnd.mCharacterIndex + 1u == lastWordLayout.mCharactersLayoutInfo.size() ) && ( textInfoIndicesEnd.mWordIndex + 1u < paragraphLayout.mWordsLayoutInfo.size() ) ) - { - // Last word is going to be removed completely. - // Check if the word after could be merged. - - // Get word after. - WordLayoutInfo& afterWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex + 1u ) ); - if( WordSeparator != afterWordLayout.mType ) - { - // The word after is not a word separator, so could be merged. - mergeToEnd = true; - textInfoMergeIndicesEnd.mWordIndex = textInfoIndicesEnd.mWordIndex + 1u; - } - } - - // Merge words only if both words could be merged. - mergeWords = mergeFromBegin && mergeToEnd; - } - - if( ( textInfoIndicesEnd.mCharacterIndex + 1u == lastWordLayout.mCharactersLayoutInfo.size() ) && ( textInfoIndicesEnd.mWordIndex + 1u == paragraphLayout.mWordsLayoutInfo.size() ) ) - { - // Last word of the paragraph is going to be removed completely. - // Check if it's a paragraph separator. - - if( ParagraphSeparator == lastWordLayout.mType ) - { - // The paragraph separator is going to be removed. - if( textInfoIndicesBegin.mParagraphIndex + 1u < textLayoutInfo.mParagraphsLayoutInfo.size() ) - { - // Paragraph need to be merged. - textInfoMergeIndicesBegin.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex; - textInfoMergeIndicesEnd.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex + 1u; - mergeParagraphs= true; - - ++textInfoIndicesBegin.mParagraphIndex; // increase both indices, - textInfoIndicesEnd.mParagraphIndex +=2u; // will delete last paragraph. - } - } - } - - if( textInfoIndicesBegin.mCharacterIndex > 0u ) - { - // First word needs to be split. - - // Store text-actors before removing them. - CollectTextActors( removedTextActorsFromFirstWord, firstWordLayout, textInfoIndicesBegin.mCharacterIndex, firstWordLayout.mCharactersLayoutInfo.size() ); - - RemoveCharactersFromWord( textInfoIndicesBegin.mCharacterIndex, - firstWordLayout.mCharactersLayoutInfo.size() - textInfoIndicesBegin.mCharacterIndex, - firstWordLayout ); - - ++textInfoIndicesBegin.mWordIndex; // will delete from the word after. - } - - if( textInfoIndicesEnd.mCharacterIndex + 1u < lastWordLayout.mCharactersLayoutInfo.size() ) - { - // Last word needs to be split. - - // Store text-actors before removing them. - CollectTextActors( removedTextActorsFromLastWord, lastWordLayout, 0u, textInfoIndicesEnd.mCharacterIndex + 1u ); - - RemoveCharactersFromWord( 0u, - textInfoIndicesEnd.mCharacterIndex + 1u, - lastWordLayout ); - - if( mergeWords ) - { - // This word is going to be merged, so is not needed. - ++textInfoIndicesEnd.mWordIndex; // will delete the last word. - } - } - else if( textInfoIndicesEnd.mCharacterIndex + 1u == lastWordLayout.mCharactersLayoutInfo.size() ) - { - // The whole last word is going to be removed. - ++textInfoIndicesEnd.mWordIndex; // will delete the last word. - - if( ( WordSeparator == lastWordLayout.mType ) && mergeWords ) - { - // The last word is a word separator and the word after is going to be merged so is not needed. - ++textInfoIndicesEnd.mWordIndex; // will delete the word after the last one. - } - } - } - else - { - // Chraracters to be removed are from the same word. - - RemoveCharactersFromWordInfo( relayoutData, - numberOfCharacters, - mergeWords, - mergeParagraphs, - textInfoIndicesBegin, - textInfoIndicesEnd, - textInfoMergeIndicesBegin, - textInfoMergeIndicesEnd, - paragraphLayout, - removedTextActorsFromFirstWord ); - } // word indices -} - -void SplitParagraph( const TextInfoIndices& indices, - float lineHeightOffset, - ParagraphLayoutInfo& firstParagraphLayoutInfo, - ParagraphLayoutInfo& lastParagraphLayoutInfo ) -{ - // Splits a paragraph in two. - // A word may be split in two as well. - - // * Split the word within the paragraph. - // * Add last part of the word to the new paragraph. - // * Add words from wordPosition + 1 to the end. - // * Update layout info of the last paragraph. - // * Remove words added to the last part of the paragraph from the first paragraph. - - // early returns!! - if( ( 0u == indices.mWordIndex ) && ( 0u == indices.mCharacterIndex ) ) - { - // the whole paragraph goes to the last part. - lastParagraphLayoutInfo = firstParagraphLayoutInfo; - - firstParagraphLayoutInfo = ParagraphLayoutInfo(); - - return; - } - - if( !firstParagraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - const std::size_t numberOfWords = firstParagraphLayoutInfo.mWordsLayoutInfo.size(); - if( indices.mWordIndex == numberOfWords - 1u ) - { - const WordLayoutInfo& word( *( firstParagraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ); - if( indices.mCharacterIndex == word.mCharactersLayoutInfo.size() ) - { - // the whole paragraph goes to the first part. - - // Just delete whatever there is in the last part of the paragraph. - lastParagraphLayoutInfo = ParagraphLayoutInfo(); - - return; - } - } - } - - lastParagraphLayoutInfo = ParagraphLayoutInfo(); - - // 1) Split the word whitin the paragraph. - WordLayoutInfo& firstWordLayoutInfo( *( firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex ) ); - WordLayoutInfo lastWordLayoutInfo; - - SplitWord( indices.mCharacterIndex, - firstWordLayoutInfo, - lastWordLayoutInfo ); - - // 2) Add last part of the word to the new paragraph. - if( !lastWordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - lastParagraphLayoutInfo.mWordsLayoutInfo.push_back( lastWordLayoutInfo ); - } - - // 3) Add words from word-position + 1 to the end. - lastParagraphLayoutInfo.mWordsLayoutInfo.insert( lastParagraphLayoutInfo.mWordsLayoutInfo.end(), - firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + indices.mWordIndex + 1u, - firstParagraphLayoutInfo.mWordsLayoutInfo.end() ); - - // 4) update layout info of the last paragraph. - for( WordLayoutInfoContainer::iterator it = lastParagraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = lastParagraphLayoutInfo.mWordsLayoutInfo.end(); - it != endIt; - ++it ) - { - WordLayoutInfo& layoutInfo( *it ); - - UpdateSize( lastParagraphLayoutInfo.mSize, layoutInfo.mSize ); - lastParagraphLayoutInfo.mNumberOfCharacters += layoutInfo.mCharactersLayoutInfo.size(); - lastParagraphLayoutInfo.mAscender = std::max( lastParagraphLayoutInfo.mAscender, layoutInfo.mAscender ); - } - lastParagraphLayoutInfo.mSize.height += lineHeightOffset; - lastParagraphLayoutInfo.mLineHeightOffset = lineHeightOffset; - - // 5) Remove words added to the last part of the paragraph from the first paragraph. - - // if the number of characters of the last word of the first paragraph is zero, it should be removed. - const std::size_t index = ( firstWordLayoutInfo.mCharactersLayoutInfo.empty() ? indices.mWordIndex : indices.mWordIndex + 1u ); - - firstParagraphLayoutInfo.mWordsLayoutInfo.erase( firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + index, firstParagraphLayoutInfo.mWordsLayoutInfo.end() ); - - // 6) update layout info of the first paragraph. - UpdateLayoutInfo( firstParagraphLayoutInfo, lineHeightOffset ); - - // 7) Split text and styles. - - // Copies the whole text to the last part of the paragraph. - lastParagraphLayoutInfo.mText = firstParagraphLayoutInfo.mText; - - // Removes from the first part of the paragraph the text that goes to the last part. - firstParagraphLayoutInfo.mText.Remove( indices.mCharacterParagraphIndex, firstParagraphLayoutInfo.mText.GetLength() - indices.mCharacterParagraphIndex ); - - // Removes from the last part of the paragraph the text that remains in the first part. - lastParagraphLayoutInfo.mText.Remove( 0u, indices.mCharacterParagraphIndex ); - - // Sets the character's styles for the last part of the paragraph. - lastParagraphLayoutInfo.mTextStyles.Insert( lastParagraphLayoutInfo.mTextStyles.End(), - firstParagraphLayoutInfo.mTextStyles.Begin() + indices.mCharacterParagraphIndex, - firstParagraphLayoutInfo.mTextStyles.End() ); - - // Removes the character's styles that go to the last part of the paragraph. - firstParagraphLayoutInfo.mTextStyles.Erase( firstParagraphLayoutInfo.mTextStyles.Begin() + indices.mCharacterParagraphIndex, - firstParagraphLayoutInfo.mTextStyles.End() ); -} - -void MergeParagraph( ParagraphLayoutInfo& firstParagraphLayoutInfo, - const ParagraphLayoutInfo& lastParagraphLayoutInfo ) -{ - // Merges two given paragraphs. - // - // Can't merge two paragraphs if the last word of the first one is a paragraph separator (new paragraph character) - - // Early returns. - - if( lastParagraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - // Nothing to merge if last paragraph is empty. - return; - } - - if( firstParagraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - // If first paragraph is empty, just copy the last paragraph to the first one. - firstParagraphLayoutInfo = lastParagraphLayoutInfo; - - return; - } - - // Check the last word of the first paragraph doesn't finish with a new paragraph character. - WordLayoutInfo& lastWordLayout( *( firstParagraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ); - if( ParagraphSeparator == lastWordLayout.mType ) - { - DALI_ASSERT_ALWAYS( !"TextViewProcessor::MergeParagraph(). ERROR: A paragraph can't be merged to another paragraph which finishes with a new paragraph character." ); - } - - // If the las word of the first paragraph or the first word of the last paragraph is a white space, both paragraphs can be concatenated. - // Otherwise both words need to be merged first. - const WordLayoutInfo& firstWordLayout( *lastParagraphLayoutInfo.mWordsLayoutInfo.begin() ); - - std::size_t index = 0u; - if( ( WordSeparator != lastWordLayout.mType ) && ( WordSeparator != firstWordLayout.mType ) && ( ParagraphSeparator != firstWordLayout.mType ) ) - { - // Last word of the first paragraph is not a word separator and first word of the last paragraph is not a word or paragraph separator. - // Words need to be merged. - - MergeWord( lastWordLayout, - firstWordLayout ); - - // After merging two words, the rest of the words need to be added. - ++index; // By increasing this index the word already merged won't be added again. - } - - // Merge layout info - - // Insert the layout of the words. - const std::size_t numberOfWords = firstParagraphLayoutInfo.mWordsLayoutInfo.size(); - firstParagraphLayoutInfo.mWordsLayoutInfo.insert( firstParagraphLayoutInfo.mWordsLayoutInfo.end(), - lastParagraphLayoutInfo.mWordsLayoutInfo.begin() + index, lastParagraphLayoutInfo.mWordsLayoutInfo.end() ); - - // Increase the index of the first character of each inserted word. - for( WordLayoutInfoContainer::iterator it = firstParagraphLayoutInfo.mWordsLayoutInfo.begin() + numberOfWords, endIt = firstParagraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it ) - { - WordLayoutInfo& word( *it ); - word.mFirstCharacter += firstParagraphLayoutInfo.mNumberOfCharacters; - } - - // Update the size and other layout parameters. - UpdateSize( firstParagraphLayoutInfo.mSize, lastParagraphLayoutInfo.mSize ); - firstParagraphLayoutInfo.mAscender = std::max( firstParagraphLayoutInfo.mAscender, lastParagraphLayoutInfo.mAscender ); - firstParagraphLayoutInfo.mLineHeightOffset = std::max( firstParagraphLayoutInfo.mLineHeightOffset, lastParagraphLayoutInfo.mLineHeightOffset ); - firstParagraphLayoutInfo.mNumberOfCharacters += lastParagraphLayoutInfo.mNumberOfCharacters; - - // Merge text and styles. - firstParagraphLayoutInfo.mText.Append( lastParagraphLayoutInfo.mText ); - for( Vector::ConstIterator it = lastParagraphLayoutInfo.mTextStyles.Begin(), endIt = lastParagraphLayoutInfo.mTextStyles.End(); it != endIt; ++it ) - { - firstParagraphLayoutInfo.mTextStyles.PushBack( new TextStyle( *(*it) ) ); - } -} - -WordLayoutInfo GetLastWordLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ) -{ - WordLayoutInfo layoutInfo; - - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - layoutInfo = *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ); - } - - return layoutInfo; -} - -CharacterLayoutInfo GetFirstCharacterLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ) -{ - CharacterLayoutInfo layoutInfo; - - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - const WordLayoutInfo& wordInfo( *paragraphLayoutInfo.mWordsLayoutInfo.begin() ); - - layoutInfo = GetFirstCharacterLayoutInfo( wordInfo ); - } - - return layoutInfo; -} - -CharacterLayoutInfo GetLastCharacterLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ) -{ - const WordLayoutInfo wordInfo = GetLastWordLayoutInfo( paragraphLayoutInfo ); - - return GetLastCharacterLayoutInfo( wordInfo ); -} - -void CollectTextActorsFromParagraphs( std::vector& textActors, const TextLayoutInfo& textLayoutInfo, const std::size_t paragraphIndexBegin, const std::size_t paragraphIndexEnd ) -{ - for( ParagraphLayoutInfoContainer::const_iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndexBegin, paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndexEnd; - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - const ParagraphLayoutInfo& paragraph( *paragraphIt ); - - CollectTextActorsFromWords( textActors, paragraph, 0u, paragraph.mWordsLayoutInfo.size() ); - } -} - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h b/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h deleted file mode 100644 index 3e9b0f0..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-paragraph-processor.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PARAGRAPH_PROCESSOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PARAGRAPH_PROCESSOR_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -/** - * Creates a data structure with info to layout the paragraph, and data structures with useful info to modify the layout data structure if characters are added or removed. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - * @param[out] paragraphLayoutInfo Layout info for the whole paragraph. - */ -void CreateParagraphInfo( TextView::RelayoutData& relayoutData, - ParagraphLayoutInfo& paragraphLayoutInfo ); - -/** - * Updates the paragraph layout info. - * - * @param[in,out] paragraphLayoutInfo The paragraph layout info. - * @param[in] lineHeightOffset The offset added to the line height. - */ -void UpdateLayoutInfo( ParagraphLayoutInfo& paragraphLayoutInfo, float lineHeightOffset ); - -/** - * Removes a given number of words from the given paragraph. - * - * @pre \e wordIndex and \e wordIndex + \e numberOfWords can't exceed the bounds of the paragraph. - * - * @param[in] wordIndex Index to the word within the paragraph with the starting position to be deleted. - * @param[in] numberOfWords The number of words to be deleted. - * @param[in] lineHeightOffset The offset added to the line height. Needed to update the layout info. - * @param[in,out] paragraphLayout The input is the layout info of the paragraph. The output is the layout info of the paragraph without the removed words. - */ -void RemoveWordsFromParagraph( std::size_t wordIndex, - std::size_t numberOfWords, - float lineHeightOffset, - ParagraphLayoutInfo& paragraphLayout ); - -/** - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in] numberOfCharacters The number of characters to be deleted. - * @param[out] mergeWords Whether words need to be merged after removing characters. - * @param[out] mergeParagraphs Whether current paragraph need to be merged with the next one. - * @param[in,out] textInfoIndicesBegin Indices to the paragraph, word and characters from where to delete characters. It returns from where words need to be removed. - * @param[out] textInfoIndicesEnd If paragraphs or words need to be merged it returns info to delete them (If a word is merged, it has to be removed. Equal for paragraphs). - * @param[out] textInfoMergeIndicesBegin The indices to the first part of the paragraph and word to be merged. - * @param[out] textInfoMergeIndicesEnd The indices to the last part of the paragraph and word to be merged. - * @param[in,out] paragraphLayout Layout info of the paragraph where the word is located. - * @param[out] removedTextActorsFromFirstWord Stores removed text-actors of the word pointed by the 'begin' index. - * @param[out] removedTextActorsFromLastWord Stores removed text-actors of the word pointed by the 'end' index. - */ -void RemoveCharactersFromParagraphInfo( TextView::RelayoutData& relayoutData, - std::size_t numberOfCharacters, - bool& mergeWords, - bool& mergeParagraphs, - TextInfoIndices& textInfoIndicesBegin, - TextInfoIndices& textInfoIndicesEnd, - TextInfoIndices& textInfoMergeIndicesBegin, - TextInfoIndices& textInfoMergeIndicesEnd, - ParagraphLayoutInfo& paragraphLayout, - std::vector& removedTextActorsFromFirstWord, - std::vector& removedTextActorsFromLastWord ); - -/** - * Splits a given paragraph in two. - * - * @note It deletes whatever there is in the last part of the paragraph. - * - * @param[in] indices Index to the word within the paragraph and index to the character within the word to split the paragraph. - * @param[in] lineHeightOffset Additional space between lines. Needed to update layout info. - * @param[in,out] firstParagraphLayoutInfo The input is the layout info of the given paragraph. The output is the first part of the input paragraph. - * @param[in,out] lastParagraphLayoutInfo Layout info of the last part of the given paragraph. - */ -void SplitParagraph( const TextInfoIndices& indices, - float lineHeightOffset, - ParagraphLayoutInfo& firstParagraphLayoutInfo, - ParagraphLayoutInfo& lastParagraphLayoutInfo ); - -/** - * Merges the two given paragraphs by adding words of the last paragraph to the firs one. - * - * @note Does nothing if last part of the paragraph is empty. - * @note If the first part of the paragraph is empty it just copy the last part to it. - * @note it asserts if the last word of the first paragraph is a paragraph separator (new paragraph character) - * - * @param[in,out] firstParagraphLayoutInfo The input is the layout info of the first paragraph. The output is the layout info of the merged paragraph. - * @param[in] lastParagraphLayoutInfo Layout info of the last paragraph. - * - */ -void MergeParagraph( ParagraphLayoutInfo& firstParagraphLayoutInfo, - const ParagraphLayoutInfo& lastParagraphLayoutInfo ); - -/** - * Retrieves the layout information of the last word of the given paragraph. - * - * @param[in] paragraphLayoutInfo The paragraph layout. - * - * @return Layout information of the last word of the paragraph. - */ -WordLayoutInfo GetLastWordLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ); - -/** - * Retrieves the layout information of the first character of the given paragraph. - * - * @param[in] paragraphLayoutInfo The paragraph layout. - * - * @return Layout information of the first character of the paragraph. - */ -CharacterLayoutInfo GetFirstCharacterLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ); - -/** - * Retrieves the layout information of the last character of the given paragraph. - * - * @param[in] paragraphLayoutInfo The paragraph layout. - * - * @return Layout information of the last character of the paragraph. - */ -CharacterLayoutInfo GetLastCharacterLayoutInfo( const ParagraphLayoutInfo& paragraphLayoutInfo ); - -/** - * Collects text-actors from the given paragraphs and stores them into the text-actor vector. - * - * @param[out] textActors Stores the text-actors of the given paragraphs. - * @param[in] textLayoutInfo Whole text with the given paragraphs. - * @param[in] paragraphIndexBegin The first paragraph. - * @param[in] paragraphIndexEnd The last paragraph. - */ -void CollectTextActorsFromParagraphs( std::vector& textActors, const TextLayoutInfo& textLayoutInfo, std::size_t paragraphIndexBegin, std::size_t paragraphIndexEnd ); - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PARAGRAPH_PROCESSOR_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.cpp b/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.cpp deleted file mode 100644 index df420cf..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2014 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 - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -#if defined(DEBUG_ENABLED) -Debug::Filter* gTextViewProcessorLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TEXT_VIEW_PROCESSOR"); -#endif - -void dbgPrint( const WordLayoutInfo& word ) -{ - std::cout << " size " << word.mSize << std::endl; - std::cout << " ascender " << word.mAscender << std::endl; - std::cout << " type "; - switch( word.mType ) - { - case NoSeparator: - { - std::cout << "NoSeparator" << std::endl; - break; - } - case ParagraphSeparator: - { - std::cout << "ParagraphSeparator" << std::endl; - break; - } - case WordSeparator: - { - std::cout << "WordSeparator" << std::endl; - break; - } - } - std::cout << " first char " << word.mFirstCharacter << std::endl; - std::cout << " num char " << word.mCharactersLayoutInfo.size() << std::endl; - for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), endCharacterIt = word.mCharactersLayoutInfo.end(); - characterIt != endCharacterIt; - ++characterIt ) - { - const CharacterLayoutInfo& character( *characterIt ); - - std::cout << "[" << character.mSize << std::endl; - std::cout << " ascender " << character.mAscender << std::endl; - } -} - -void dbgPrint( const ParagraphLayoutInfo& paragraph ) -{ - std::cout << "< "; - std::cout << " text : [" << paragraph.mText.GetText() << "]" << std::endl; - std::cout << " number of styles : " << paragraph.mTextStyles.Count() << std::endl; - std::cout << paragraph.mSize; - for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin(), endWordIt = paragraph.mWordsLayoutInfo.end(); - wordIt != endWordIt; - ++wordIt ) - { - dbgPrint( *wordIt ); - } - std::cout << " >"; - std::cout << std::endl; -} - -void dbgPrint( const TextLayoutInfo& textInfo ) -{ - std::cout << "||" << std::endl; - std::cout << textInfo.mWholeTextSize; - std::cout << textInfo.mNumberOfCharacters; - for( ParagraphLayoutInfoContainer::const_iterator it = textInfo.mParagraphsLayoutInfo.begin(), endIt = textInfo.mParagraphsLayoutInfo.end(); - it != endIt; - ++it ) - { - dbgPrint( *it ); - } - std::cout << "||" << std::endl; -} - -void dbgPrint( const TextStyle& style ) -{ - std::cout << " font name : " << style.GetFontName() << std::endl; - std::cout << " font style : " << style.GetFontStyle() << std::endl; - std::cout << " font point size : " << style.GetFontPointSize() << std::endl; - std::cout << " weight : " << style.GetWeight() << std::endl; - std::cout << " text color : " << style.GetTextColor() << std::endl; - std::cout << " italics : " << style.IsItalicsEnabled() << std::endl; - std::cout << " italics angle : " << style.GetItalicsAngle() << std::endl; - std::cout << " underline : " << style.IsUnderlineEnabled() << std::endl; - std::cout << " underline thickness : " << style.GetUnderlineThickness() << std::endl; - std::cout << " underline position : " << style.GetUnderlinePosition() << std::endl; - std::cout << " shadow : " << style.IsShadowEnabled() << std::endl; - std::cout << " shadow color : " << style.GetShadowColor() << std::endl; - std::cout << " shadow offset : " << style.GetShadowOffset() << std::endl; - std::cout << " shadow size : " << style.GetShadowSize() << std::endl; - std::cout << " glow : " << style.IsGlowEnabled() << std::endl; - std::cout << " glow color : " << style.GetGlowColor() << std::endl; - std::cout << " glow intensity : " << style.GetGlowIntensity() << std::endl; - std::cout << " smooth edge : " << style.GetSmoothEdge() << std::endl; - std::cout << " outline : " << style.IsOutlineEnabled() << std::endl; - std::cout << " outline color : " << style.GetOutlineColor() << std::endl; - std::cout << " outline thickness : " << style.GetOutlineThickness() << std::endl; - std::cout << " gradient : " << style.IsGradientEnabled() << std::endl; - std::cout << " gradient color : " << style.GetGradientColor() << std::endl; - std::cout << " gradient start point : " << style.GetGradientStartPoint() << std::endl; - std::cout << " gradient end point : " << style.GetGradientEndPoint() << std::endl; - std::cout << " is font name default : " << style.IsFontNameDefault() << std::endl; - std::cout << " is font style default : " << style.IsFontStyleDefault() << std::endl; - std::cout << " is font size default : " << style.IsFontSizeDefault() << std::endl; - std::cout << " is text color default : " << style.IsTextColorDefault() << std::endl; - std::cout << " is font weight default : " << style.IsFontWeightDefault() << std::endl; - std::cout << " is smooth edge default : " << style.IsSmoothEdgeDefault() << std::endl; - std::cout << " is italics default : " << style.IsItalicsDefault() << std::endl; - std::cout << " is underline default : " << style.IsUnderlineDefault() << std::endl; - std::cout << " is shadow default : " << style.IsShadowDefault() << std::endl; - std::cout << " is glow default : " << style.IsGlowDefault() << std::endl; - std::cout << " is outline default : " << style.IsOutlineDefault() << std::endl; - std::cout << " is gradient default : " << style.IsGradientDefault() << std::endl; -} - -void dbgPrint( const TextInfoIndices& indices ) -{ - std::cout << " paragraph : " << indices.mParagraphIndex << std::endl; - std::cout << " word : " << indices.mWordIndex << std::endl; - std::cout << " char : " << indices.mCharacterIndex << std::endl; - std::cout << " char in paragraph : " << indices.mCharacterParagraphIndex << std::endl; -} - -void dbgPrint( const MarkupProcessor::StyledTextArray& textArray ) -{ - for( MarkupProcessor::StyledTextArray::const_iterator it = textArray.begin(), endIt = textArray.end(); it != endIt; ++it ) - { - const MarkupProcessor::StyledText& text( *it ); - - std::cout << text.mText.GetText(); - } -} - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h b/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h deleted file mode 100644 index 2529bb8..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-dbg.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_DBG_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_DBG_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -//Forward declarations. -class TextStyle; - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -//Forward declarations. -struct WordLayoutInfo; -struct ParagraphLayoutInfo; -struct TextLayoutInfo; -struct TextInfoIndices; - -#if defined(DEBUG_ENABLED) -extern Debug::Filter* gTextViewProcessorLogFilter; -#endif - -void dbgPrint( const WordLayoutInfo& word ); -void dbgPrint( const ParagraphLayoutInfo& paragraph ); -void dbgPrint( const TextLayoutInfo& textInfo ); -void dbgPrint( const TextStyle& style ); -void dbgPrint( const TextInfoIndices& indices ); -void dbgPrint( const MarkupProcessor::StyledTextArray& text ); - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_DBG_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.cpp b/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.cpp deleted file mode 100644 index 43a5f4e..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2014 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 - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -void UpdateSize( Size& size1, const Size& size2, const SizeGrowType type ) -{ - switch( type ) - { - case GrowWidth: - { - size1.width += size2.width; - size1.height = std::max( size1.height, size2.height ); - break; - } - case GrowHeight: - { - size1.width = std::max( size1.width, size2.width ); - size1.height += size2.height; - break; - } - } -} - -TextSeparatorType GetTextSeparatorType( const Character& character ) -{ - // returns if the given character is a paragraph separator '\n', a word separator ' ' or if is not a separator (any other character). - return ( character.IsNewLine() ? ParagraphSeparator : ( character.IsWhiteSpace() ? WordSeparator : NoSeparator ) ); -} - -void ChooseFontFamilyName( const Character& character, TextStyle& style ) -{ - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::ChooseFontFamilyName\n" ); - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " input font name: [%s]\n", style.GetFontName().c_str() ); - - bool userDefinedFontFamilyName = false; - - // First check if there is a font defined in the style and it supports the given text. - if( !style.GetFontName().empty() ) - { - const FontParameters fontParams( style.GetFontName(), style.GetFontStyle() , style.GetFontPointSize() ); - const Font font = Font::New( fontParams ); - - if( !font.IsDefaultSystemFont() && font.AllGlyphsSupported( character ) ) - { - userDefinedFontFamilyName = true; - } - } - - if( !userDefinedFontFamilyName ) - { - const Font defaultSystemFont = Font::New(); - - // At this point no font is set or doesn't support the given text. - if( !defaultSystemFont.AllGlyphsSupported( character ) ) - { - // If the default system font doesn't support the given text, - // an appropiate font is selected. - style.SetFontName( Font::GetFamilyForText( character ) ); - // @TODO Font::GetFamilyForText() should return font family and font style. - } - else - { - // All characters are supported with default font, so use it - style.SetFontName( "" ); - } - } - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " output font name: [%s]\n", style.GetFontName().c_str() ); - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::ChooseFontFamilyName\n" ); -} - -void GetIndicesFromGlobalCharacterIndex( const std::size_t index, - const TextLayoutInfo& textLayoutInfo, - TextInfoIndices& indices ) -{ - // clear all indices - indices = TextInfoIndices(); - - // Early return. - if( textLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - // Text is empty. All indices are 0. - return; - } - - std::size_t currentIndex = 0u; // stores how many characters have been traversed (within the whole text). - - // Traverse all paragraphs and words until global index is found. - bool found = false; - for( ParagraphLayoutInfoContainer::const_iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin(), - paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.end(); - ( !found ) && ( paragraphIt != paragraphEndIt ); - ++paragraphIt, ++indices.mParagraphIndex ) - { - const ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt ); - std::size_t currentCharactersTraversed = currentIndex; // stores how many characters have been traversed until this paragraph. - - if( currentIndex + paragraphLayoutInfo.mNumberOfCharacters > index ) - { - // The character is in this paragraph - for( WordLayoutInfoContainer::const_iterator wordIt = paragraphLayoutInfo.mWordsLayoutInfo.begin(), - wordEndIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); - ( !found ) && ( wordIt != wordEndIt ); - ++wordIt, ++indices.mWordIndex ) - { - const WordLayoutInfo& wordLayoutInfo( *wordIt ); - - if( currentIndex + wordLayoutInfo.mCharactersLayoutInfo.size() > index ) - { - // The character is in this word - indices.mCharacterIndex = index - currentIndex; - indices.mCharacterParagraphIndex = index - currentCharactersTraversed; - found = true; - } - else - { - // check in the next word. - currentIndex += wordLayoutInfo.mCharactersLayoutInfo.size(); - } - } // end words. - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - --indices.mWordIndex; - } - } - else - { - // check in the next paragraph - currentIndex += paragraphLayoutInfo.mNumberOfCharacters; - } - } // end paragraphs. - - // Need to decrease indices as they have been increased in the last loop. - if( !textLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - --indices.mParagraphIndex; - } -} - -void ClearText( std::vector& textActors ) -{ - for( std::vector::iterator it = textActors.begin(), endIt = textActors.end(); it != endIt; ++it ) - { - (*it).SetText( std::string( "" ) ); - } -} - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h b/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h deleted file mode 100644 index c543e32..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-helper-functions.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_HELPER_FUNCTIONS_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_HELPER_FUNCTIONS_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -/** - * Enum type used to update a size adding other one. - * If the grow type is \e GrowWidth, size's widths are added and size's height is the max of both. - * Alternativelly if grow type is \e GrowHeight heights are added and width is the max of both. - */ -enum SizeGrowType -{ - GrowWidth, - GrowHeight, -}; - -/** - * Updates the size of a character, word, line or the whole text with a given size. - * - * For characters, words, and lines the new height will be the maximum of both sizes - * and the new width will be the sum of both. - * - * For the whole text, the new height will be the sum of both and the new width the max of both. - * - * The \e type parameter speficies which type of update is required. - * - * @param[in,out] size1 The current size to be updated. - * @param[in] size2 The size of a character, word, or a line. - * @param[in] type Type of update. - */ -void UpdateSize( Size& size1, const Size& size2, SizeGrowType type = GrowWidth ); - -/** - * Return the type of separator (white space, new line or no separator) for the given character. - * - * @param[in] character The given character. - * - * @return The type of separator. - */ -TextSeparatorType GetTextSeparatorType( const Character& character ); - -/** - * Choose a suitable font family name for the given character. - * - * It may modify the text-style of the given character by setting a suitable font-family. - * - * @param[in] character The character. - * @param[in,out] style The style of the character. - */ -void ChooseFontFamilyName( const Character& character, TextStyle& style ); - -/** - * Retrieves the line, word and character indices for the given global character's index. - * - * i.e. The retrieved indices for the character 18 (j) for the following text would be: 2, 0, 2, 0 - * - * a b c d - * e f g h - * i j k l - * m n o p - * - * @param[in] index The global character index. - * @param[in] textLayoutInfo Contains info about the number of characters per word, and line. - * @param[out] indices Index to the line, word and character within the word where the given character is located. - */ -void GetIndicesFromGlobalCharacterIndex( std::size_t index, - const TextLayoutInfo& textLayoutInfo, - TextInfoIndices& indices ); - -/** - * Clear the text of the given text-actors. - * - * @param[in] textActors The given text-actors. - */ -void ClearText( std::vector& textActors ); - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_HELPER_FUNCTIONS_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor-types.h b/dali-toolkit/internal/controls/text-view/text-view-processor-types.h deleted file mode 100644 index 15005cc..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor-types.h +++ /dev/null @@ -1,356 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_TYPES_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_TYPES_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -class TextStyle; - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextProcessor -{ -// Forward declarations. -struct BidirectionalParagraphInfo; -struct BidirectionalLineInfo; -} // namespace TextProcessor - -namespace TextViewProcessor -{ - -/** - * Whether the text is a new paragraph character '\n', a white space or normal text. - */ -enum TextSeparatorType -{ - ParagraphSeparator, - WordSeparator, - NoSeparator -}; - -/** - * Whether to clear the text of the text-actors when text is removed. - */ -enum TextOperationOnRemove -{ - CLEAR_TEXT, - KEEP_TEXT -}; - - -/** - * Stores text info indices. - */ -struct TextInfoIndices -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - TextInfoIndices(); - - /** - * Constructor. - */ - TextInfoIndices( std::size_t paragraphIndex, - std::size_t wordIndex, - std::size_t characterIndex ); - - /** - * Equality operator. - * @param [in] indices The text-info indices to be compared. - * - * @return \e true if both indices are equal. - */ - bool operator==( const TextInfoIndices& indices ) const; - - std::size_t mParagraphIndex; ///< The paragraph index within the text. - std::size_t mWordIndex; ///< The word index within the paragraph. - std::size_t mCharacterIndex; ///< The character index within the word. - std::size_t mCharacterParagraphIndex; ///< The character index within the paragraph. -}; - -/** - * Stores gradient info. - * - * Used to fade in/out text-actors. - */ -struct GradientInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - GradientInfo(); - - /** - * Default destructor. - */ - ~GradientInfo(); - - /** - * Copy constructor - */ - GradientInfo( const GradientInfo& info ); - - /** - * Assignment operator. - */ - GradientInfo& operator=( const GradientInfo& info ); - - Vector4 mGradientColor; ///< Gradient color. - Vector2 mStartPoint; ///< Gradient start point. - Vector2 mEndPoint; ///< Gradient end point. -}; - -/** - * Layout information for a character. - * It stores the position, size and ascender of its respective text-actor. - */ -struct CharacterLayoutInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - CharacterLayoutInfo(); - - /** - * Default destructor. - * - * Deletes the gradient info. - */ - ~CharacterLayoutInfo(); - - /** - * Copy constructor. - */ - CharacterLayoutInfo( const CharacterLayoutInfo& character ); - - /** - * Assignment operator. - */ - CharacterLayoutInfo& operator=( const CharacterLayoutInfo& character ); - - // Metrics of the glyph. - Size mSize; ///< Height of the font and advance (the horizontal distance from the origin of the current character and the next one). - float mBearing; ///< Vertical distance from the baseline to the top of the glyph's boundary box. - float mAscender; ///< Distance from the base line to the top of the line. - float mUnderlineThickness; ///< The underline's thickness. - float mUnderlinePosition; ///< The underline's position. - - // Position and alignment offset. It depends on the lay-out. - Vector3 mPosition; ///< Position within the text-view - Vector2 mOffset; ///< Alignment and justification offset. - - RenderableActor mGlyphActor; ///< Handle to a text-actor. - float mColorAlpha; ///< Alpha component for the initial text color when text is faded. - GradientInfo* mGradientInfo; ///< Stores gradient info. - - bool mIsVisible:1; ///< Whether the text-actor is visible. - bool mSetText:1; ///< Whether a new text needs to be set in the text-actor. - bool mSetStyle:1; ///< Whether a new style needs to be set in the text-actor. - bool mIsColorGlyph:1; ///< Whether this character is an emoticon. -}; -typedef std::vector CharacterLayoutInfoContainer; - -/** - * Layout information for a word. - */ -struct WordLayoutInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - WordLayoutInfo(); - - /** - * Default destructor. - * - * Clears all characters. - */ - ~WordLayoutInfo(); - - /** - * Copy constructor. - */ - WordLayoutInfo( const WordLayoutInfo& word ); - - /** - * Assignment operator. - */ - WordLayoutInfo& operator=( const WordLayoutInfo& word ); - - Size mSize; ///< Size of the word. - float mAscender; ///< Max of all ascenders of all characters. - TextSeparatorType mType; ///< Whether this word is a word separator, a line separator or is not a separator. - std::size_t mFirstCharacter; ///< Index to the first character of the word within the paragraph. - CharacterLayoutInfoContainer mCharactersLayoutInfo; ///< Layout info for all characters. -}; -typedef std::vector WordLayoutInfoContainer; - -/** - * Stores the reordered layout for right to left text. - */ -struct RightToLeftParagraphLayout -{ - RightToLeftParagraphLayout() - : mWordsLayoutInfo(), - mText(), - mTextStyles(), - mPreviousLayoutCleared( false ) - { - } - - WordLayoutInfoContainer mWordsLayoutInfo; ///< Layout info for all words. - Text mText; ///< Stores the text. - Vector mTextStyles; ///< Stores the style per each character. - bool mPreviousLayoutCleared:1; ///< Whether the previous right to left layout has been cleared. - - /** - * Clears the word layout vector, the text and the vector of styles. - */ - void Clear(); -}; - -/** - * Layout information for a paragraph. - */ -struct ParagraphLayoutInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - ParagraphLayoutInfo(); - - /** - * Default destructor. - * - * Clears all words, deletes all text styles, the paragraph bidirectional info and all bidirectional infor for each line. - */ - ~ParagraphLayoutInfo(); - - /** - * Copy constructor. - */ - ParagraphLayoutInfo( const ParagraphLayoutInfo& paragraph ); - - /** - * Assignment operator. - */ - ParagraphLayoutInfo& operator=( const ParagraphLayoutInfo& paragraph ); - - /** - * Deletes the bidirectional info for each line. - */ - void ClearBidirectionalInfo(); - -private: - - /** - * Deletes all text styles. - */ - void ClearStyles(); - -public: - Size mSize; ///< Size of the paragraph. - float mAscender; ///< Max of all ascenders of all words. - float mLineHeightOffset; ///< Line height offset. - std::size_t mFirstCharacter; ///< Index to the first character of the paragraph. - std::size_t mNumberOfCharacters; ///< Stores the number of characters. - WordLayoutInfoContainer mWordsLayoutInfo; ///< Layout info for all words. - Text mText; ///< Stores the text. - Vector mTextStyles; ///< Stores the style per each character. - RightToLeftParagraphLayout* mRightToLeftLayout; ///< Stores the reordered layout for the paragraph. - TextProcessor::BidirectionalParagraphInfo* mBidirectionalParagraphInfo; ///< Contains bidirectional info for the whole paragraph. Set to NULL if the paragraph has left to right characters only. - Vector mBidirectionalLinesInfo; ///< Contains bidirectional info for each laid-out line. -}; -typedef std::vector ParagraphLayoutInfoContainer; - -/** - * Layout information for the whole text. - */ -struct TextLayoutInfo -{ - /** - * Default constructor. - * - * Initializes all members to their default values. - */ - TextLayoutInfo(); - - /** - * Defualt destructor. - * - * Clears the paragraph vector, the ellipsis text and deletes all ellipsis styles. - */ - ~TextLayoutInfo(); - - /** - * Copy constructor. - */ - TextLayoutInfo( const TextLayoutInfo& text ); - - /** - * Assignment operator. - */ - TextLayoutInfo& operator=( const TextLayoutInfo& text ); - -private: - /** - * Deletes all the ellipsis text styles. - */ - void ClearStyles(); - -public: - Size mWholeTextSize; ///< width and height of the whole text. - float mMaxWordWidth; ///< maximum width between all words. - float mMaxItalicsOffset; ///< When rendering text-view in offscreen an extra width offset is needed to prevent italic characters to be cut if they are in the right edge. - std::size_t mNumberOfCharacters; ///< Stores the number of characters. - ParagraphLayoutInfoContainer mParagraphsLayoutInfo; ///< Layout information for all paragraphs. - WordLayoutInfo mEllipsizeLayoutInfo; ///< Layout information for the ellipsize text. - Dali::Text mEllipsisText; ///< The ellipsis text. - Vector mEllipsisTextStyles; ///< Stores the style per each character of the ellipsis text. -}; - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_TYPES_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor.cpp b/dali-toolkit/internal/controls/text-view/text-view-processor.cpp deleted file mode 100644 index 40f1fab..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor.cpp +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Copyright (c) 2014 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 - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -namespace -{ -/** - * Update text layout info. - * - * Updates the size of the whole text, the maximum width of all words and the number of characters. - * - * @param[in,out] textLayoutInfo - */ -void UpdateLayoutInfo( TextLayoutInfo& textLayoutInfo ) -{ - // Initialize members to be updated. - textLayoutInfo.mWholeTextSize = Size::ZERO; - textLayoutInfo.mMaxWordWidth = 0.f; - textLayoutInfo.mNumberOfCharacters = 0u; - - // Traverse all text updating values. - for( ParagraphLayoutInfoContainer::const_iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - const ParagraphLayoutInfo& paragraph( *paragraphIt ); - - // Updates text size with the size of all paragraphs. - UpdateSize( textLayoutInfo.mWholeTextSize, paragraph.mSize, GrowHeight ); - - // Updates number of characters. - textLayoutInfo.mNumberOfCharacters += paragraph.mNumberOfCharacters; - - // Updates the max word's width. - for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - const WordLayoutInfo& word( *wordIt ); - - textLayoutInfo.mMaxWordWidth = std::max( textLayoutInfo.mMaxWordWidth, word.mSize.width ); - } - } -} - -} // namespace - -// Constructors and assignment operators - -TextInfoIndices::TextInfoIndices() -: mParagraphIndex( 0u ), - mWordIndex( 0u ), - mCharacterIndex( 0u ), - mCharacterParagraphIndex( 0u ) -{ -} - -TextInfoIndices::TextInfoIndices( const std::size_t paragraphIndex, - const std::size_t wordIndex, - const std::size_t characterIndex ) -: mParagraphIndex( paragraphIndex ), - mWordIndex( wordIndex ), - mCharacterIndex( characterIndex ), - mCharacterParagraphIndex( 0u ) -{ -} - -bool TextInfoIndices::operator==( const TextInfoIndices& indices ) const -{ - return ( ( mParagraphIndex == indices.mParagraphIndex ) && - ( mWordIndex == indices.mWordIndex ) && - ( mCharacterIndex == indices.mCharacterIndex ) && - ( mCharacterParagraphIndex == indices.mCharacterParagraphIndex ) ); -} - -///////////////////// -// Layout info. -///////////////////// - -TextLayoutInfo::TextLayoutInfo() -: mWholeTextSize(), - mMaxWordWidth( 0.f ), - mMaxItalicsOffset( 0.f ), - mNumberOfCharacters( 0u ), - mParagraphsLayoutInfo(), - mEllipsizeLayoutInfo(), - mEllipsisText( "..." ), - mEllipsisTextStyles() -{ - // Sets default styles for the default ellipsis text. - mEllipsisTextStyles.PushBack( new TextStyle() ); - mEllipsisTextStyles.PushBack( new TextStyle() ); - mEllipsisTextStyles.PushBack( new TextStyle() ); -} - -TextLayoutInfo::~TextLayoutInfo() -{ - ClearStyles(); -} - -TextLayoutInfo::TextLayoutInfo( const TextLayoutInfo& text ) -: mWholeTextSize( text.mWholeTextSize ), - mMaxWordWidth( text.mMaxWordWidth ), - mMaxItalicsOffset( text.mMaxItalicsOffset ), - mNumberOfCharacters( text.mNumberOfCharacters ), - mParagraphsLayoutInfo( text.mParagraphsLayoutInfo ), - mEllipsizeLayoutInfo( text.mEllipsizeLayoutInfo ), - mEllipsisText( text.mEllipsisText ), - mEllipsisTextStyles() -{ - for( Vector::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it ) - { - mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) ); - } -} - -TextLayoutInfo& TextLayoutInfo::operator=( const TextLayoutInfo& text ) -{ - if( this != &text ) - { - mWholeTextSize = text.mWholeTextSize; - mMaxWordWidth = text.mMaxWordWidth; - mMaxItalicsOffset = text.mMaxItalicsOffset; - mNumberOfCharacters = text.mNumberOfCharacters; - mParagraphsLayoutInfo = text.mParagraphsLayoutInfo; - mEllipsizeLayoutInfo = text.mEllipsizeLayoutInfo; - mEllipsisText = text.mEllipsisText; - - ClearStyles(); - - for( Vector::ConstIterator it = text.mEllipsisTextStyles.Begin(), endIt = text.mEllipsisTextStyles.End(); it != endIt; ++it ) - { - mEllipsisTextStyles.PushBack( new TextStyle( *(*it) ) ); - } - } - return *this; -} - -void TextLayoutInfo::ClearStyles() -{ - for( Vector::Iterator it = mEllipsisTextStyles.Begin(), endIt = mEllipsisTextStyles.End(); it != endIt; ++it ) - { - delete *it; - } - mEllipsisTextStyles.Clear(); -} - -///////////////////////////////////////////////////////////////////////////////////////////// - -void CreateTextInfo( const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // * Traverse the given text spliting it in paragraphs and each paragraph in words. - // * White spaces and new paragraph characters are alone in one word. - // * Bidirectional text is processed in each paragraph. - // It creates the conversion tables - // It does the ligatures if there is arabic glyphs. - // It doesn't reorder the text as it must be done for each line not for the paragraph. - // * Generates a layout data structure to store layout information (size, position, ascender, text direction, etc) and metrics of all characters. - // * Store text for each paragraph and the style for each character. - - // Collect previously created text-actors. - std::vector textActors; - CollectTextActorsFromParagraphs( textActors, relayoutData.mTextLayoutInfo, 0u, relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.size() ); - - if( !textActors.empty() ) - { - // Add text-actors to the cache. - relayoutData.mTextActorCache.InsertTextActors( textActors ); - relayoutData.mTextActorCache.ClearTexts(); - } - - // Store the ellipsize layout info before clearing the previous created info. - // TODO: fix this. Don't clear the ellipsis layout, store it somewhere else ... - const WordLayoutInfo ellipsizeInfo = relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo; - Dali::Text ellipsisText = relayoutData.mTextLayoutInfo.mEllipsisText; - Vector ellipsisTextStyles = relayoutData.mTextLayoutInfo.mEllipsisTextStyles; - relayoutData.mTextLayoutInfo.mEllipsisTextStyles.Clear(); - - // clear previously created info. - relayoutData.mTextLayoutInfo = TextLayoutInfo(); - relayoutData.mCharacterLogicalToVisualMap.clear(); - relayoutData.mCharacterVisualToLogicalMap.clear(); - - // Sets the ellipsize layout info. - relayoutData.mTextLayoutInfo.mEllipsizeLayoutInfo = ellipsizeInfo; - relayoutData.mTextLayoutInfo.mEllipsisText = ellipsisText; - relayoutData.mTextLayoutInfo.mEllipsisTextStyles = ellipsisTextStyles; - - // Split the whole text in paragraphs. - // It returns a vector of Text with all the paragraphs. - // and for each paragraph a vector of styles per character. TODO: don't create a style per character. - std::vector paragraphs; - std::vector< Vector > styles; - TextProcessor::SplitInParagraphs( text, - paragraphs, - styles ); - - // Reserve space for the current number of paragraphs. - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.resize( paragraphs.size(), ParagraphLayoutInfo() ); - - // Traverse all paragraphs - std::size_t paragraphIndex = 0u; - std::vector::iterator paragraphIt, paragraphEndIt; - std::vector< Vector >::const_iterator styleIt, styleEndIt; - for( paragraphIt = paragraphs.begin(), paragraphEndIt = paragraphs.end(), - styleIt = styles.begin(), styleEndIt = styles.end(); - ( paragraphIt != paragraphEndIt ) && ( styleIt != styleEndIt ); - ++paragraphIndex, - ++paragraphIt, - ++styleIt ) - { - // Gets the paragraph and the styles for each character. - Text& paragraph( *paragraphIt ); - const Vector& textStyles( *styleIt ); - - // Retrieve the data structure for the current paragraph. - ParagraphLayoutInfo& paragraphLayoutInfo = *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex ); - - // Sets text and styles. - paragraphLayoutInfo.mText = paragraph; - paragraphLayoutInfo.mTextStyles = textStyles; - - // Fills the paragraph data structure with the layout info. - - if( !paragraph.IsEmpty() ) - { - CreateParagraphInfo( relayoutData, - paragraphLayoutInfo ); - - // do not add the line offset if the paragraph has no characters. - paragraphLayoutInfo.mSize.height += layoutParameters.mLineHeightOffset; - paragraphLayoutInfo.mLineHeightOffset = layoutParameters.mLineHeightOffset; - } - else - { - // This paragraph has no text. i.e. the previous paragraph ends with '\n'. - // Even though, line height needs to be set in order to align the whole text correctly. - - float lineHeight = 0.f; - // Get the last character of the last paragraph. - if( 0u < paragraphIndex ) - { - const ParagraphLayoutInfo& paragraphInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + ( paragraphIndex - 1u ) ) ); - - const CharacterLayoutInfo characterInfo = GetLastCharacterLayoutInfo( paragraphInfo ); - - lineHeight = characterInfo.mSize.height; - } - - paragraphLayoutInfo.mSize.height = lineHeight; - } - - // Fills the conversion tables used to get the logical or visual position of a character is case there is right to left text. - // If there is right to left text, it needs to be updated every time the text is relaid-out. - for( std::size_t index = 0u; index < paragraphLayoutInfo.mNumberOfCharacters; ++index ) - { - relayoutData.mCharacterLogicalToVisualMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); - relayoutData.mCharacterVisualToLogicalMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); - } - - // Update layout info for the whole text. - UpdateSize( relayoutData.mTextLayoutInfo.mWholeTextSize, paragraphLayoutInfo.mSize, GrowHeight ); - relayoutData.mTextLayoutInfo.mNumberOfCharacters += paragraphLayoutInfo.mNumberOfCharacters; - } // end of paragraphs -} - -void UpdateTextInfo( std::size_t position, - const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // Update current internal data structure with added text. - - // * Creates layout info for the given text. - // * With the given position, find where to add the text. - // * If the new text is not added at the end of current text, a paragraph need to be split. - // * Merge the last paragraph of the new text to the last part or the split paragraph. - // * Add paragraphs between first and last of the new text. - // * Merge the first part of the split paragraph with the first paragraph of the new text. - // * Update the layout info for the whole text. - - // Early returns: - - if( text.empty() ) - { - // nothing to do if the input text is empty. - return; - } - - if( 0u == relayoutData.mTextLayoutInfo.mNumberOfCharacters ) - { - // Current text is empty. There is no need to update current data structure, - // just create a new one with the new input text. - CreateTextInfo( text, - layoutParameters, - relayoutData ); - return; - } - - // initial checks. - if( position > relayoutData.mTextLayoutInfo.mNumberOfCharacters ) - { - // Asserts if text is to be added out of bounds. - DALI_ASSERT_ALWAYS( !"TextViewProcessor::UpdateTextInfo (insert). Trying to insert text out of bounds." ); - } - - - // TODO - // If in the insertion is involved right to left text, - // check the neighbour characters is needed. - // i.e. Arabic characters may have four different glyphs (isolated, end, middle, begin). - // So check the neighbours on each side is needed in order to render - // the correct ligatures. - - - TextView::RelayoutData relayoutDataForNewText; - - // Creates layout info for the given text. - // It doesn't create text-actors as text could be added to an existing one. - CreateTextInfo( text, - layoutParameters, - relayoutDataForNewText ); - - // Fills the conversion tables used to get the logical or visual position of a character is case there is right to left text. - // If there is right to left text, it needs to be updated every time the text is relaid-out. - std::size_t index = 0u; - for( std::size_t i = 0u; i < relayoutDataForNewText.mTextLayoutInfo.mNumberOfCharacters; ++i ) - { - relayoutData.mCharacterLogicalToVisualMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); - relayoutData.mCharacterVisualToLogicalMap.push_back( relayoutData.mTextLayoutInfo.mNumberOfCharacters + index ); - ++index; - } - - // If a paragraph is split, it stores the last part of the paragraph. - ParagraphLayoutInfo lastParagraphLayoutInfo; - - // Stores indices to the paragraph, word and character of the given position. - TextInfoIndices textInfoIndices; - - if( position < relayoutData.mTextLayoutInfo.mNumberOfCharacters ) - { - // Get paragraph, word and character indices for given position. - GetIndicesFromGlobalCharacterIndex( position, - relayoutData.mTextLayoutInfo, - textInfoIndices ); - - // 1) Split the paragraph - - // Split a paragraph in two is needed, then merge the first part of the split paragraph - // with the first paragraph of the new text, add subsequent paragraphs and merge the last paragraph - // of the new text with the last part of the split paragraph. - - // Implementation notes! - // - // These references to the first paragraph are declared in this scope because if new paragraphs are inserted in step 2, - // they become invalid, making the algorithm to crash if used again. - // In the step 3, references to the first paragraph are needed and declared again. - - // Stores the first part of the split paragraph. - ParagraphLayoutInfo& firstParagraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndices.mParagraphIndex ) ); - - SplitParagraph( textInfoIndices, - PointSize( layoutParameters.mLineHeightOffset ), - firstParagraphLayoutInfo, - lastParagraphLayoutInfo ); - } - else - { - // Position is just after the last character. - // Calculates indices for that position. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - textInfoIndices.mParagraphIndex = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.size() - 1u; - const ParagraphLayoutInfo& paragraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( !paragraphLayoutInfo.mWordsLayoutInfo.empty() ) - { - textInfoIndices.mWordIndex = paragraphLayoutInfo.mWordsLayoutInfo.size() - 1u; - - const WordLayoutInfo& wordLayoutInfo( *( paragraphLayoutInfo.mWordsLayoutInfo.end() - 1u ) ); - textInfoIndices.mCharacterIndex = wordLayoutInfo.mCharactersLayoutInfo.size(); - - // Sets the character index within the paragraph. - textInfoIndices.mCharacterParagraphIndex = 0u; - for( WordLayoutInfoContainer::const_iterator it = paragraphLayoutInfo.mWordsLayoutInfo.begin(), endIt = paragraphLayoutInfo.mWordsLayoutInfo.end(); it != endIt; ++it ) - { - textInfoIndices.mCharacterParagraphIndex += wordLayoutInfo.mCharactersLayoutInfo.size(); - } - } - } - } - - // 2) If the new text has more than 1 paragraph, merge the last paragraph of the input text with the last part of the split paragraph. - //TODO check this cases ( num paragraphs ==1, >1, >2 ) if it could be simplified. - if( relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.size() > 1u ) - { - ParagraphLayoutInfo& lastInputParagraphLayoutInfo( *( relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - MergeParagraph( lastInputParagraphLayoutInfo, - lastParagraphLayoutInfo ); - - if( relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.size() > 2u ) - { - // Insert all paragraphs except first and last in the text. - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.insert( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndices.mParagraphIndex + 1u, - relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + 1u, - relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ); - } - - // Insert the last paragraph to the text - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.insert( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndices.mParagraphIndex + relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.size() - 1u, - lastInputParagraphLayoutInfo ); - } - else - { - // Merge the new paragraph to the last part of the split paragraph. - ParagraphLayoutInfo& inputParagraphLayoutInfo( *relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.begin() ); - - MergeParagraph( inputParagraphLayoutInfo, - lastParagraphLayoutInfo ); - } - - // 3) Merge the first paragraph of the split text with the first paragraph of the input text. - ParagraphLayoutInfo& firstParagraphLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndices.mParagraphIndex ) ); - ParagraphLayoutInfo& firstInputParagraphLayoutInfo( *relayoutDataForNewText.mTextLayoutInfo.mParagraphsLayoutInfo.begin() ); - - MergeParagraph( firstParagraphLayoutInfo, - firstInputParagraphLayoutInfo ); - - // 4) Update text info. - - // Updates the whole text size, maximum word size, etc. - UpdateLayoutInfo( relayoutData.mTextLayoutInfo ); -} - -void UpdateTextInfo( std::size_t position, - std::size_t numberOfCharacters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData, - const TextOperationOnRemove clearText ) -{ - // Removes 'numberOfCharacters' starting from 'position'. - - // * It checks if text to be deleted is in the same paragraph or not: - // * If it is not, check which paragraphs need to be split/merged or deleted. - // * If it is but all characters of the paragraph are going to be deleted, just delete the paragraph (nothing needs to be split/merged) - // * If only some characters of the same paragraph are going to be deleted, proceed similarly: check if text to be deleted is in the same word. - // * If it is not, split/merge words. - // * Check if the whole word needs to be deleted. - // * Check if only some characters of the word need to be deleted. - // * Updates layout info. - - // * The algorithm checks if a word separator is deleted (in that case, different words need to be merged) and if a new paragraph separator is deleted (two paragraphs need to be merged). - - // Early return - - if( 0u == numberOfCharacters ) - { - DALI_ASSERT_DEBUG( !"TextViewProcessor::UpdateTextInfo. WARNING: trying to delete 0 characters!" ); - - // nothing to do if no characters are deleted. - return; - } - - // Asserts if trying to delete text out of bounds. - DALI_ASSERT_ALWAYS( position + numberOfCharacters <= relayoutData.mTextLayoutInfo.mNumberOfCharacters && "TextViewProcessor::UpdateTextInfo. ERROR: trying to delete characters out of boundary" ); - - // Remove characters from character to visual map and vs. - // If there is right to left text, it needs to be updated every time the text is relaid-out. - relayoutData.mCharacterLogicalToVisualMap.erase( relayoutData.mCharacterLogicalToVisualMap.end() - numberOfCharacters, relayoutData.mCharacterLogicalToVisualMap.end() ); - relayoutData.mCharacterVisualToLogicalMap.erase( relayoutData.mCharacterVisualToLogicalMap.end() - numberOfCharacters, relayoutData.mCharacterVisualToLogicalMap.end() ); - - // Get paragraph, word and character indices for the given start position. - TextInfoIndices textInfoIndicesBegin; - GetIndicesFromGlobalCharacterIndex( position, - relayoutData.mTextLayoutInfo, - textInfoIndicesBegin ); - - // Get paragraph, word and character indices for the given end position (start position + number of characters to be deleted). - TextInfoIndices textInfoIndicesEnd; - GetIndicesFromGlobalCharacterIndex( position + numberOfCharacters - 1u, - relayoutData.mTextLayoutInfo, - textInfoIndicesEnd ); - - // Vectors used to temporary store text-actors removed from text. - // Three vectors are needed because text-actors are not removed in order - // but insert them in order is required to reuse them later. - std::vector removedTextActorsFromBegin; - std::vector removedTextActorsFromMid; - std::vector removedTextActorsFromEnd; - - // Whether paragraphs and words need to be merged. - bool mergeParagraphs = false; - bool mergeWords = false; - - // Indices of the paragraphs and words to be merged. - TextInfoIndices textInfoMergeIndicesBegin; - TextInfoIndices textInfoMergeIndicesEnd; - - const ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex ) ); // used to check the number of characters of the paragraph - // if all characters to be deleted are in the same paragraph. - if( textInfoIndicesBegin.mParagraphIndex < textInfoIndicesEnd.mParagraphIndex ) - { - // Deleted text is from different paragraphs. It may need to split two paragraphs, and merge first part of the first one with last part of the last one. - - // whether first or last paragraph need to be split and merged with the last part. - bool mergeFirstParagraph = false; - bool mergeLastParagraph = true; - - textInfoMergeIndicesBegin.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex; - textInfoMergeIndicesEnd.mParagraphIndex = textInfoIndicesEnd.mParagraphIndex; - - if( ( textInfoIndicesBegin.mWordIndex > 0u ) || ( textInfoIndicesBegin.mCharacterIndex > 0u ) ) - { - // first character to be deleted is not the first one of the current paragraph. - ++textInfoIndicesBegin.mParagraphIndex; // won't delete current paragraph - - // As some characters remain, this paragraph could be merged with the last one. - mergeFirstParagraph = true; - } - - // Check if all characters of the last paragraph are going to be deleted. - bool wholeParagraphDeleted = false; - const ParagraphLayoutInfo& lastParagraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesEnd.mParagraphIndex ) ); - if( textInfoIndicesEnd.mWordIndex + 1u == lastParagraphLayout.mWordsLayoutInfo.size() ) - { - const WordLayoutInfo& lastWordLayout( *( lastParagraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) ); - if( textInfoIndicesEnd.mCharacterIndex + 1u == lastWordLayout.mCharactersLayoutInfo.size() ) - { - // All characters of the last paragraph are going to be deleted. - ++textInfoIndicesEnd.mParagraphIndex; // will delete the last paragraph. - - // the whole last paragraph is deleted. Need to check if the next paragraph could be merged. - mergeLastParagraph = false; - wholeParagraphDeleted = true; - } - } - - if( wholeParagraphDeleted ) - { - // It means the whole last paragraph is deleted completely. - // It's needed to check if there is another paragraph after that could be merged. - if( textInfoIndicesEnd.mParagraphIndex < relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.size() ) - { - mergeLastParagraph = true; - - // Point the first characters of the next paragraph. - textInfoIndicesEnd.mWordIndex = 0u; - textInfoIndicesEnd.mCharacterIndex = 0u; - textInfoMergeIndicesEnd.mParagraphIndex = textInfoIndicesEnd.mParagraphIndex; - } - } - - // If some characters remain in the first and last paragraph, they need to be merged. - mergeParagraphs = mergeFirstParagraph && mergeLastParagraph; - - if( mergeParagraphs ) - { - // last paragraph is going to be merged with the first one, so is not needed. - ++textInfoIndicesEnd.mParagraphIndex; // will delete the last paragraph. - } - - if( mergeFirstParagraph ) - { - // Remove characters from the first paragraph. - - // Vectors used to temporary store text-actors removed from the paragraph. - // Three vectors are needed because text-actors are not removed in order - // but insert them in order is required to reuse them later. - std::vector removedTextActorsFromFirstWord; - std::vector removedTextActorsFromFirstParagraph; - - // As paragraphIndexBegin has been increased just to not to remove the paragraph, decrease now is needed to access it. - ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex - 1u ) ); - - // Remove the characters from the text and the styles. - paragraphLayout.mText.Remove( textInfoIndicesBegin.mCharacterParagraphIndex, paragraphLayout.mNumberOfCharacters - textInfoIndicesBegin.mCharacterParagraphIndex ); - - for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin() + textInfoIndicesBegin.mCharacterParagraphIndex, - endIt = paragraphLayout.mTextStyles.End(); - it != endIt; - ++it ) - { - delete *it; - } - paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin() + textInfoIndicesBegin.mCharacterParagraphIndex, - paragraphLayout.mTextStyles.End() ); - - if( ( textInfoIndicesBegin.mWordIndex + 1u < paragraphLayout.mWordsLayoutInfo.size() ) || ( 0u == textInfoIndicesBegin.mCharacterIndex ) ) - { - // Remove extra words within current paragraph. (and current word if whole characters are removed) - // 0 == characterIndexBegin means the whole word is deleted. - const std::size_t wordIndex = ( ( 0u == textInfoIndicesBegin.mCharacterIndex ) ? textInfoIndicesBegin.mWordIndex : textInfoIndicesBegin.mWordIndex + 1u ); - - // Store text-actors before removing them. - CollectTextActorsFromWords( removedTextActorsFromFirstParagraph, paragraphLayout, wordIndex, paragraphLayout.mWordsLayoutInfo.size() ); - - RemoveWordsFromParagraph( wordIndex, - paragraphLayout.mWordsLayoutInfo.size() - wordIndex, - layoutParameters.mLineHeightOffset, - paragraphLayout ); - } - - if( ( textInfoIndicesBegin.mWordIndex < paragraphLayout.mWordsLayoutInfo.size() ) && ( textInfoIndicesBegin.mCharacterIndex > 0u ) ) - { - // Only some characters of the word need to be removed. - WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex ) ); - - // Store text-actors before removing them. - CollectTextActors( removedTextActorsFromFirstWord, wordLayout, textInfoIndicesBegin.mCharacterIndex, wordLayout.mCharactersLayoutInfo.size() ); - - const std::size_t wordNumberCharacters = wordLayout.mCharactersLayoutInfo.size(); - RemoveCharactersFromWord( textInfoIndicesBegin.mCharacterIndex, - wordLayout.mCharactersLayoutInfo.size() - textInfoIndicesBegin.mCharacterIndex, - wordLayout ); - - // discount the removed number of characters. - const std::size_t removedNumberOfCharacters = ( wordNumberCharacters - wordLayout.mCharactersLayoutInfo.size() ); - paragraphLayout.mNumberOfCharacters -= removedNumberOfCharacters; - } - UpdateLayoutInfo( paragraphLayout, layoutParameters.mLineHeightOffset ); - - // Insert the text-actors in order. - removedTextActorsFromBegin.insert( removedTextActorsFromBegin.end(), removedTextActorsFromFirstWord.begin(), removedTextActorsFromFirstWord.end() ); - removedTextActorsFromBegin.insert( removedTextActorsFromBegin.end(), removedTextActorsFromFirstParagraph.begin(), removedTextActorsFromFirstParagraph.end() ); - } - - if( mergeLastParagraph && !wholeParagraphDeleted ) - { - // Some characters from the last paragraph need to be removed. - - // Vectors used to temporary store text-actors removed from the paragraph. - // Three vectors are needed because text-actors are not removed in order - // but insert them in order is required to reuse them later. - std::vector removedTextActorsFromFirstWord; - std::vector removedTextActorsFromFirstParagraph; - - // paragraphIndexEnd was increased to delete the last paragraph if paragraphs need to be merged. - // To access now the last paragraph we need to decrease the index. - const std::size_t paragraphIndex = ( mergeParagraphs ? textInfoIndicesEnd.mParagraphIndex - 1u : textInfoIndicesEnd.mParagraphIndex ); - - // Get the last paragraph. - ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + paragraphIndex ) ); - - // Remove the characters from the text and the styles. - const std::size_t lastCharacterIndex = textInfoIndicesEnd.mCharacterParagraphIndex + 1u; - - paragraphLayout.mText.Remove( 0u, lastCharacterIndex ); - - for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin(), - endIt = paragraphLayout.mTextStyles.Begin() + lastCharacterIndex; - it != endIt; - ++it ) - { - delete *it; - } - paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin(), - paragraphLayout.mTextStyles.Begin() + lastCharacterIndex ); - - // Check if is needed remove the whole word. (If the character index is pointing just after the end of the word) - const WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ) ); - bool removeWholeWord = wordLayout.mCharactersLayoutInfo.size() == textInfoIndicesEnd.mCharacterIndex + 1u; - - if( ( textInfoIndicesEnd.mWordIndex > 0u ) || ( removeWholeWord ) ) - { - // Store text-actors before removing them. - CollectTextActorsFromWords( removedTextActorsFromFirstParagraph, - paragraphLayout, - 0u, - ( removeWholeWord ) ? textInfoIndicesEnd.mWordIndex + 1u : textInfoIndicesEnd.mWordIndex ); - - // Remove extra words. (and current word if whole characters are removed) - RemoveWordsFromParagraph( 0u, - ( removeWholeWord ) ? textInfoIndicesEnd.mWordIndex + 1u : textInfoIndicesEnd.mWordIndex, - layoutParameters.mLineHeightOffset, - paragraphLayout ); - } - - if( !removeWholeWord ) - { - // Only some characters of the word need to be deleted. - - // After removing all extra words. The word with the characters to be removed is the first one. - WordLayoutInfo& wordLayout( *paragraphLayout.mWordsLayoutInfo.begin() ); - - // Store text-actors before removing them. - CollectTextActors( removedTextActorsFromFirstWord, wordLayout, 0u, textInfoIndicesEnd.mCharacterIndex + 1u ); - - const std::size_t wordNumberCharacters = wordLayout.mCharactersLayoutInfo.size(); - RemoveCharactersFromWord( 0u, - textInfoIndicesEnd.mCharacterIndex + 1u, - wordLayout ); - - // discount the removed number of characters. - const std::size_t removedNumberOfCharacters = ( wordNumberCharacters - wordLayout.mCharactersLayoutInfo.size() ); - paragraphLayout.mNumberOfCharacters -= removedNumberOfCharacters; - } - UpdateLayoutInfo( paragraphLayout, layoutParameters.mLineHeightOffset ); - - // Insert the text-actors in order. - removedTextActorsFromEnd.insert( removedTextActorsFromEnd.end(), removedTextActorsFromFirstWord.begin(), removedTextActorsFromFirstWord.end() ); - removedTextActorsFromEnd.insert( removedTextActorsFromEnd.end(), removedTextActorsFromFirstParagraph.begin(), removedTextActorsFromFirstParagraph.end() ); - } - } // end delete text from different paragraphs - else if( ( textInfoIndicesBegin.mParagraphIndex == textInfoIndicesEnd.mParagraphIndex ) && ( paragraphLayout.mNumberOfCharacters == numberOfCharacters ) ) - { - // the whole paragraph needs to be deleted. - ++textInfoIndicesEnd.mParagraphIndex; // will delete current paragraph. - } - else - { - // deleted text is within the same paragraph. (merge paragraphs could be needed if the paragraph separator character is deleted) - - // Paragraph which contains the characters to be deleted. - ParagraphLayoutInfo& paragraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex ) ); - - // Remove the characters from the text and the styles. - const std::size_t firstCharacterIndex = textInfoIndicesBegin.mCharacterParagraphIndex; - const std::size_t lastCharacterIndex = textInfoIndicesEnd.mCharacterParagraphIndex + 1u; - - paragraphLayout.mText.Remove( firstCharacterIndex, lastCharacterIndex - firstCharacterIndex ); - - for( Vector::Iterator it = paragraphLayout.mTextStyles.Begin() + firstCharacterIndex, - endIt = paragraphLayout.mTextStyles.Begin() + lastCharacterIndex; - it != endIt; - ++it ) - { - delete *it; - } - paragraphLayout.mTextStyles.Erase( paragraphLayout.mTextStyles.Begin() + firstCharacterIndex, - paragraphLayout.mTextStyles.Begin() + lastCharacterIndex ); - - // Remove the characters from the paragraph layout info. It returns whether the current paragraph can be merged with the next one. - RemoveCharactersFromParagraphInfo( relayoutData, - numberOfCharacters, - mergeWords, - mergeParagraphs, - textInfoIndicesBegin, - textInfoIndicesEnd, - textInfoMergeIndicesBegin, - textInfoMergeIndicesEnd, - paragraphLayout, - removedTextActorsFromBegin, - removedTextActorsFromEnd ); - - if( mergeWords ) - { - // Merges words pointed by textInfoMergeIndicesBegin.mWordIndex and textInfoMergeIndicesEnd.mWordIndex calculated previously. - DALI_ASSERT_DEBUG( ( textInfoMergeIndicesBegin.mWordIndex < paragraphLayout.mWordsLayoutInfo.size() ) && "TextViewProcessor::UpdateTextInfo (delete). Word index (begin) out of bounds." ); - DALI_ASSERT_DEBUG( ( textInfoMergeIndicesEnd.mWordIndex < paragraphLayout.mWordsLayoutInfo.size() ) && "TextViewProcessor::UpdateTextInfo (delete). Word index (end) out of bounds." ); - - WordLayoutInfo& firstWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoMergeIndicesBegin.mWordIndex ) ); - WordLayoutInfo& lastWordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoMergeIndicesEnd.mWordIndex ) ); - - MergeWord( firstWordLayout, - lastWordLayout ); - } - - // Store text-actors before removing them. - const std::size_t endIndex = ( mergeWords && ( textInfoIndicesEnd.mWordIndex > 0u ) ) ? textInfoIndicesEnd.mWordIndex - 1u : textInfoIndicesEnd.mWordIndex; // text-actors from the last word may have been added in the merge above. - CollectTextActorsFromWords( removedTextActorsFromMid, paragraphLayout, textInfoIndicesBegin.mWordIndex, endIndex ); - - // Remove unwanted words using previously calculated indices. (including the last part of the merged word) - paragraphLayout.mWordsLayoutInfo.erase( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex, paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesEnd.mWordIndex ); - - // Update paragraph info. - UpdateLayoutInfo( paragraphLayout, layoutParameters.mLineHeightOffset ); - }// end delete text from same paragraph. - - if( mergeParagraphs ) - { - // Merges paragraphs pointed by textInfoMergeIndicesBegin.mParagraphIndex and textInfoMergeIndicesEnd.mParagraphIndex calculated previously. - - ParagraphLayoutInfo& firstParagraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoMergeIndicesBegin.mParagraphIndex ) ); - - const ParagraphLayoutInfo& lastParagraphLayout( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoMergeIndicesEnd.mParagraphIndex ) ); - - MergeParagraph( firstParagraphLayout, - lastParagraphLayout ); - } - - // Store text-actors before removing them. - const std::size_t endIndex = ( mergeParagraphs && ( textInfoIndicesEnd.mParagraphIndex > 0u ) ) ? textInfoIndicesEnd.mParagraphIndex - 1u : textInfoIndicesEnd.mParagraphIndex; // text-actors from the last paragraph may have been added in the merge above. - CollectTextActorsFromParagraphs( removedTextActorsFromMid, - relayoutData.mTextLayoutInfo, - textInfoIndicesBegin.mParagraphIndex, - endIndex ); - - // Remove unwanted paragraphs using previously calculated indices. (including the last part of the merged paragraph) - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.erase( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesBegin.mParagraphIndex, - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin() + textInfoIndicesEnd.mParagraphIndex ); - - // Update text info. - UpdateLayoutInfo( relayoutData.mTextLayoutInfo ); - - // If the last character of the last paragraph is a new paragraph character, an empty paragraph need to be added. - if( !relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.empty() ) - { - const WordLayoutInfo lastWordLayout = GetLastWordLayoutInfo( *( relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end() - 1u ) ); - - if( ParagraphSeparator == lastWordLayout.mType ) - { - ParagraphLayoutInfo lastParagraphLayout; - - const CharacterLayoutInfo layoutInfo = GetLastCharacterLayoutInfo( lastWordLayout ); - lastParagraphLayout.mSize.height = layoutInfo.mSize.height; - - relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.push_back( lastParagraphLayout ); - - relayoutData.mTextLayoutInfo.mWholeTextSize.height += layoutInfo.mSize.height; - } - } - - // Clear the text from the text-actors if required. - if( CLEAR_TEXT == clearText ) - { - ClearText( removedTextActorsFromEnd ); - ClearText( removedTextActorsFromMid ); - ClearText( removedTextActorsFromBegin ); - } - - // Insert text-actors into the cache. - // Text-actors are inserted in reverse order to use first the first removed. - relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromEnd ); - relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromMid ); - relayoutData.mTextActorCache.InsertTextActors( removedTextActorsFromBegin ); -} - -void UpdateTextInfo( std::size_t position, - std::size_t numberOfCharacters, - const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ) -{ - // Replaces 'numberOfCharacters' of text starting from 'position' with the given text. - - // TODO: Temporary implementation with remove and insert. - - // Remove. - UpdateTextInfo( position, - numberOfCharacters, - layoutParameters, - relayoutData, - KEEP_TEXT ); // Do not clear the text from the text-actors. - - // Insert. - UpdateTextInfo( position, - text, - layoutParameters, - relayoutData ); -} - -void UpdateTextInfo( float lineHeightOffset, - TextLayoutInfo& textLayoutInfo ) -{ - // Updates the space between lines with the new offset value. - - float newTextHeight = 0.f; - - for( ParagraphLayoutInfoContainer::iterator paragraphIt = textLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = textLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - ParagraphLayoutInfo& paragraphLayoutInfo( *paragraphIt ); - - paragraphLayoutInfo.mSize.height += ( lineHeightOffset - paragraphLayoutInfo.mLineHeightOffset ); - newTextHeight += paragraphLayoutInfo.mSize.height; - - paragraphLayoutInfo.mLineHeightOffset = lineHeightOffset; - } - - textLayoutInfo.mWholeTextSize.height = newTextHeight; -} - -void UpdateTextInfo( const TextStyle& style, - const TextStyle::Mask mask, - TextView::RelayoutData& relayoutData ) -{ - // Change text style for all text-actors. - - for( ParagraphLayoutInfoContainer::iterator paragraphIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.begin(), paragraphEndIt = relayoutData.mTextLayoutInfo.mParagraphsLayoutInfo.end(); - paragraphIt != paragraphEndIt; - ++paragraphIt ) - { - ParagraphLayoutInfo& paragraph( *paragraphIt ); - - std::size_t index = 0u; - for( Vector::Iterator it = paragraph.mTextStyles.Begin(), endIt = paragraph.mTextStyles.End(); it != endIt; ++it ) - { - (*it)->Copy( style, mask ); - - // Checks if the font family supports all glyphs. If not, chooses a most suitable one. - ChooseFontFamilyName( paragraph.mText[index], *(*it) ); - - ++index; - } - - for( WordLayoutInfoContainer::iterator wordIt = paragraph.mWordsLayoutInfo.begin(), wordEndIt = paragraph.mWordsLayoutInfo.end(); - wordIt != wordEndIt; - ++wordIt ) - { - WordLayoutInfo& word( *wordIt ); - - for( CharacterLayoutInfoContainer::iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt ) - { - CharacterLayoutInfo& characterLayout( *characterIt ); - - // Mark the character to be set the new style into the text-actor. - characterLayout.mSetStyle = true; - } // end characters - } // end words - } // end paragraphs -} - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-processor.h b/dali-toolkit/internal/controls/text-view/text-view-processor.h deleted file mode 100644 index a38eaa7..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-processor.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -/** - * Creates a data structure with info to layout the text, and data structures with useful info to modify the layout data structure if characters are added or removed. - * - * @param[in] text The given styled text. - * @param[in] layoutParameters Layout configuration. - * @param[out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void CreateTextInfo( const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Updates the layout data structures with the new inserted text. - * - * @note Does nothing if text has no characters. - * @note It asserts if position is bigger than the number of characters of the whole text. - * - * @param[in] position Where the text is going to be inserted. - * @param[in] text New styled text to be inserted. - * @param[in] layoutParameters Layout configuration. - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void UpdateTextInfo( std::size_t position, - const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Updates the layout data structures by removing text. - * - * @note Does nothing if number of characters to be deleted is zero. - * @note It asserts if trying to delete text out of bounds. - * - * @param[in] position Position of the first character to be removed. - * @param[in] numberOfCharacters The number of characters to be removed. - * @param[in] layoutParameters Layout configuration. - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - * @param[in] clearText Whether to clear text-actor's text before insert the text-actors into the cache. - */ -void UpdateTextInfo( std::size_t position, - std::size_t numberOfCharacters, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData, - TextOperationOnRemove clearText ); - -/** - * Updates the layout data structures by replacing text. - * - * @param[in] position Position of the first character to be replaced. - * @param[in] numberOfCharacters The number of characters to be replaced. - * @param[in] text The new styled text. - * @param[in] layoutParameters Layout configuration. - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info and conversion from visual to logical order and vice versa (for RTL text). - */ -void UpdateTextInfo( std::size_t position, - std::size_t numberOfCharacters, - const MarkupProcessor::StyledTextArray& text, - const TextView::LayoutParameters& layoutParameters, - TextView::RelayoutData& relayoutData ); - -/** - * Updates the layout data structure by modifying the space between lines. - * - * @param[in] lineHeightOffset The new space between lines. - * @param[in,out] textLayoutInfo Layout info for all characters, words, lines and the whole text. - */ -void UpdateTextInfo( float lineHeightOffset, - TextLayoutInfo& textLayoutInfo ); - -/** - * Updates the text-actor data structures by replacing the style. - * - * @note This operation is called only if the new style doesn't modify the metrics. Consequently it doesn't modify any size info. - * - * @param[in] style The new style. - * @param[in] mask The style mask. - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - */ -void UpdateTextInfo( const TextStyle& style, - TextStyle::Mask mask, - TextView::RelayoutData& relayoutData ); - -} // namespace TextViewProcessor - -} // namespace Internal - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_PROCESSOR_H__ diff --git a/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp b/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp deleted file mode 100644 index eab8cf6..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-word-processor.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright (c) 2014 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 - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -namespace -{ - -const char* const EMOJI_FONT_NAME = "SamsungEmoji"; ///< Emoticons font family name. - -} // namespace - -///////////////////// -// Layout info. -///////////////////// - -WordLayoutInfo::WordLayoutInfo() -: mSize(), - mAscender( 0.f ), - mType( NoSeparator ), - mFirstCharacter( 0u ), - mCharactersLayoutInfo() -{ -} - -WordLayoutInfo::~WordLayoutInfo() -{ -} - -WordLayoutInfo::WordLayoutInfo( const WordLayoutInfo& word ) -: mSize( word.mSize ), - mAscender( word.mAscender ), - mType( word.mType ), - mFirstCharacter( word.mFirstCharacter ), - mCharactersLayoutInfo( word.mCharactersLayoutInfo ) -{ -} - -WordLayoutInfo& WordLayoutInfo::operator=( const WordLayoutInfo& word ) -{ - mSize = word.mSize; - mAscender = word.mAscender; - mType = word.mType; - mFirstCharacter = word.mFirstCharacter; - mCharactersLayoutInfo = word.mCharactersLayoutInfo; - - return *this; -} - -void CreateWordTextInfo( const Text& paragraph, - Vector& textStyles, - WordLayoutInfo& wordLayoutInfo ) -{ - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "-->TextViewProcessor::CreateWordTextInfo\n" ); - // Split in characters. - std::size_t characterIndex = wordLayoutInfo.mFirstCharacter; - for( CharacterLayoutInfoContainer::iterator it = wordLayoutInfo.mCharactersLayoutInfo.begin(), - endIt = wordLayoutInfo.mCharactersLayoutInfo.end(); - it != endIt; - ++it, ++characterIndex ) - { - // Gets a reference of the character's layout info. - CharacterLayoutInfo& characterLayoutInfo( *it ); - - // Gets the character and the style for that character from the paragraph. - Character character = paragraph[characterIndex]; - TextStyle* textStyle = *( textStyles.Begin() + characterIndex ); - - // Checks whether the character is an emoticon. - characterLayoutInfo.mIsColorGlyph = GlyphImage::IsColorGlyph( character ); - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, " Is color glyph: %s\n", ( characterLayoutInfo.mIsColorGlyph ? "True" : "False" ) ); - - if( characterLayoutInfo.mIsColorGlyph ) - { - // If the character is an emoticon a predefined font is set. - textStyle->SetFontName( EMOJI_FONT_NAME ); - } - else - { - // Checks if the font family and the font style set in the text style supports the character. - // If not, it chooses the right font for the given character and style. - ChooseFontFamilyName( character, *textStyle ); - } - - // Gets the metrics of the font. - const Font font = Font::New( FontParameters( textStyle->GetFontName(), textStyle->GetFontStyle(), textStyle->GetFontPointSize() ) ); - const Font::Metrics metrics = font.GetMetrics( character ); - const float ascender = font.GetAscender(); - - // Fill Natural size info for current character. - - // The font line's height is used as character's height. - characterLayoutInfo.mSize.height = font.GetLineHeight(); - - // The character's advance is used as charcter's width. - characterLayoutInfo.mSize.width = metrics.GetAdvance(); - - // The ascender and bearing are used to position correctly glyphs of different font sizes. - characterLayoutInfo.mAscender = ascender; - characterLayoutInfo.mBearing = metrics.GetBearing(); - - if( character.IsNewLine() && !characterLayoutInfo.mIsColorGlyph ) - { - // A new paragraph character '\n' doesn't have any width. - characterLayoutInfo.mSize.width = 0.f; - } - - // Set's the underline thickness and position. - // Both thickness and position includes the vertical pad adjust used in effects like glow or shadow. - if( textStyle->IsUnderlineEnabled() ) - { - characterLayoutInfo.mUnderlineThickness = font.GetUnderlineThickness(); - characterLayoutInfo.mUnderlinePosition = font.GetUnderlinePosition(); - } - - // Updates the word size and ascender. - UpdateSize( wordLayoutInfo.mSize, characterLayoutInfo.mSize ); - wordLayoutInfo.mAscender = std::max( wordLayoutInfo.mAscender, characterLayoutInfo.mAscender ); - } // end of characters in the word. - DALI_LOG_INFO( gTextViewProcessorLogFilter, Debug::General, "<--TextViewProcessor::CreateWordTextInfo\n" ); -} - -void UpdateLayoutInfo( WordLayoutInfo& wordLayout ) -{ - // Initialize layout info for the whole word. - wordLayout.mSize = Size::ZERO; - wordLayout.mAscender = 0.f; - - // Traverse the character layout info to update the word layout. - for( CharacterLayoutInfoContainer::iterator layoutIt = wordLayout.mCharactersLayoutInfo.begin(), layoutEndIt = wordLayout.mCharactersLayoutInfo.end(); - layoutIt != layoutEndIt; - ++layoutIt ) - { - // Layout info for the current character. - CharacterLayoutInfo& layoutInfo( *layoutIt ); - - // Update layout info for the current word. - UpdateSize( wordLayout.mSize, layoutInfo.mSize ); - wordLayout.mAscender = std::max( wordLayout.mAscender, layoutInfo.mAscender ); - } -} - -void RemoveCharactersFromWordInfo( TextView::RelayoutData& relayoutData, - const std::size_t numberOfCharacters, - bool& mergeWords, - bool& mergeParagraphs, - TextInfoIndices& textInfoIndicesBegin, - TextInfoIndices& textInfoIndicesEnd, - TextInfoIndices& textInfoMergeIndicesBegin, - TextInfoIndices& textInfoMergeIndicesEnd, - ParagraphLayoutInfo& paragraphLayout, - std::vector& removedTextActors ) -{ - const TextLayoutInfo& textLayoutInfo = relayoutData.mTextLayoutInfo; - - // Get the word. - WordLayoutInfo& wordLayout( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex ) ); - - if( ParagraphSeparator == wordLayout.mType ) - { - // If the word is a paragraph separator and there is more paragraphs, then current paragraph and the paragraph after need to be merged. - if( textInfoIndicesBegin.mParagraphIndex + 1u < textLayoutInfo.mParagraphsLayoutInfo.size() ) - { - // current paragraph is not the last one. - - // Update indices to merge paragraphs. - textInfoMergeIndicesBegin.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex; - textInfoMergeIndicesEnd.mParagraphIndex = textInfoIndicesBegin.mParagraphIndex + 1u; - - mergeParagraphs = true; - - ++textInfoIndicesBegin.mParagraphIndex; // increase both indices, - textInfoIndicesEnd.mParagraphIndex += 2u; // will delete last paragraph. - } - - ++textInfoIndicesEnd.mWordIndex; //will delete the paragraph separator; - } - else if( WordSeparator == wordLayout.mType ) - { - // If the word is a word separator. Check if the word before and the word after can be merged. - - if( ( 0u < textInfoIndicesBegin.mWordIndex ) && ( paragraphLayout.mWordsLayoutInfo.size() > textInfoIndicesBegin.mWordIndex + 1u ) ) - { - const WordLayoutInfo& wordLayoutBefore( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex - 1u ) ); - const WordLayoutInfo& wordLayoutAfter( *( paragraphLayout.mWordsLayoutInfo.begin() + textInfoIndicesBegin.mWordIndex + 1u ) ); - - if( ( NoSeparator == wordLayoutBefore.mType ) && ( NoSeparator == wordLayoutAfter.mType ) ) - { - // This word is a word separator (white space) and is not the first word of the paragraph nor the last one. - mergeWords = true; - - // Set indices to merge the words. - textInfoMergeIndicesBegin.mWordIndex = textInfoIndicesBegin.mWordIndex - 1u; // word before word separator. - textInfoMergeIndicesEnd.mWordIndex = textInfoIndicesBegin.mWordIndex + 1u; // word after word separator. - - textInfoIndicesEnd.mWordIndex += 2u; // will delete the word separator and the merged word. - } - else - { - ++textInfoIndicesEnd.mWordIndex; // will delete the word separator; - } - } - else - { - ++textInfoIndicesEnd.mWordIndex; // will delete the word separator; - } - } - else if( numberOfCharacters == wordLayout.mCharactersLayoutInfo.size() ) - { - // The whole word needs to be removed. - ++textInfoIndicesEnd.mWordIndex; // will delete the current word. - } - else - { - // Store text-actors before removing them. - CollectTextActors( removedTextActors, wordLayout, textInfoIndicesBegin.mCharacterIndex, textInfoIndicesBegin.mCharacterIndex + numberOfCharacters ); - - // just remove some characters from current word. - RemoveCharactersFromWord( textInfoIndicesBegin.mCharacterIndex, - numberOfCharacters, - wordLayout ); - } -} - -void RemoveCharactersFromWord( const std::size_t position, - const std::size_t numberOfCharacters, - WordLayoutInfo& wordLayout ) -{ - // Removes a given number of characters from the given word starting from the 'position' index. - - // Early return. - if( 0u == numberOfCharacters ) - { - // nothing to do if the number of characters is zero. - - return; - } - - // Remove characters from layout and text-actor info. - wordLayout.mCharactersLayoutInfo.erase( wordLayout.mCharactersLayoutInfo.begin() + position, wordLayout.mCharactersLayoutInfo.begin() + position + numberOfCharacters ); - - // Some characters have been removed from the word. Update the layout info is needed. - UpdateLayoutInfo( wordLayout ); -} - -void SplitWord( const std::size_t position, - WordLayoutInfo& firstWordLayoutInfo, - WordLayoutInfo& lastWordLayoutInfo ) -{ - // Splits a word in two. - // It moves characters from the first part of the word to the last one. - - // early returns - if( 0u == position ) - { - // the whole word goes to the last part of the word. - lastWordLayoutInfo = firstWordLayoutInfo; - - firstWordLayoutInfo = WordLayoutInfo(); - - return; - } - - if( position == firstWordLayoutInfo.mCharactersLayoutInfo.size() ) - { - // the whole word goes to the first part of the word. - - // Just delete whatever there is in the last part of the word. - lastWordLayoutInfo = WordLayoutInfo(); - - return; - } - - // Initialize output data structures. - - // Layout info - lastWordLayoutInfo = WordLayoutInfo(); - - // Split layout info. - - // Insert characters from the given index 'position' to the end. - lastWordLayoutInfo.mCharactersLayoutInfo.insert( lastWordLayoutInfo.mCharactersLayoutInfo.end(), - firstWordLayoutInfo.mCharactersLayoutInfo.begin() + position, firstWordLayoutInfo.mCharactersLayoutInfo.end() ); - - // Delete characters from the first part of the word. - firstWordLayoutInfo.mCharactersLayoutInfo.erase( firstWordLayoutInfo.mCharactersLayoutInfo.begin() + position, firstWordLayoutInfo.mCharactersLayoutInfo.end() ); - - // Update the layout info of both new words. - UpdateLayoutInfo( firstWordLayoutInfo ); - UpdateLayoutInfo( lastWordLayoutInfo ); -} - -void MergeWord( WordLayoutInfo& firstWordLayoutInfo, - const WordLayoutInfo& lastWordLayoutInfo ) -{ - // Merges two given words. - - // Early returns. - if( lastWordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - // nothing to do - return; - } - - if( firstWordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - // copy last to first - - firstWordLayoutInfo = lastWordLayoutInfo; - - return; - } - - if( ( NoSeparator != firstWordLayoutInfo.mType ) || ( NoSeparator != lastWordLayoutInfo.mType ) ) - { - // Do not merge white spaces or new paragraph characters. - DALI_ASSERT_ALWAYS( !"TextViewProcessor::MergeWord(). ERROR: White spaces or new paragraph characters can't be merged with other words." ); - } - - // Merge layout info - firstWordLayoutInfo.mCharactersLayoutInfo.insert( firstWordLayoutInfo.mCharactersLayoutInfo.end(), - lastWordLayoutInfo.mCharactersLayoutInfo.begin(), - lastWordLayoutInfo.mCharactersLayoutInfo.end() ); - - // Update the word layout info. - UpdateSize( firstWordLayoutInfo.mSize, lastWordLayoutInfo.mSize ); - firstWordLayoutInfo.mAscender = std::max( firstWordLayoutInfo.mAscender, lastWordLayoutInfo.mAscender ); -} - -CharacterLayoutInfo GetFirstCharacterLayoutInfo( const WordLayoutInfo& wordLayoutInfo ) -{ - CharacterLayoutInfo layoutInfo; - - if( !wordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - layoutInfo = *wordLayoutInfo.mCharactersLayoutInfo.begin(); - } - - return layoutInfo; -} - -CharacterLayoutInfo GetLastCharacterLayoutInfo( const WordLayoutInfo& wordLayoutInfo ) -{ - CharacterLayoutInfo layoutInfo; - - if( !wordLayoutInfo.mCharactersLayoutInfo.empty() ) - { - layoutInfo = *( wordLayoutInfo.mCharactersLayoutInfo.end() - 1u ); - } - - return layoutInfo; -} - -void CollectTextActors( std::vector& textActors, const WordLayoutInfo& word, const std::size_t characterIndexBegin, const std::size_t characterIndexEnd ) -{ - for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin() + characterIndexBegin, - characterEndIt = word.mCharactersLayoutInfo.begin() + characterIndexEnd; - characterIt != characterEndIt; - ++characterIt ) - { - const CharacterLayoutInfo& characterLayout( *characterIt ); - - if( !characterLayout.mIsColorGlyph ) - { - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - if( textActor ) - { - textActors.push_back( textActor ); - } - } - } -} - -void CollectTextActorsFromWords( std::vector& textActors, const ParagraphLayoutInfo& paragraph, const std::size_t wordIndexBegin, const std::size_t wordIndexEnd ) -{ - for( WordLayoutInfoContainer::const_iterator wordIt = paragraph.mWordsLayoutInfo.begin() + wordIndexBegin, wordEndIt = paragraph.mWordsLayoutInfo.begin() + wordIndexEnd; - wordIt != wordEndIt; - ++wordIt ) - { - const WordLayoutInfo& word( *wordIt ); - - for( CharacterLayoutInfoContainer::const_iterator characterIt = word.mCharactersLayoutInfo.begin(), characterEndIt = word.mCharactersLayoutInfo.end(); - characterIt != characterEndIt; - ++characterIt ) - { - const CharacterLayoutInfo& characterLayout( *characterIt ); - - if( !characterLayout.mIsColorGlyph ) - { - TextActor textActor = TextActor::DownCast( characterLayout.mGlyphActor ); - if( textActor ) - { - textActors.push_back( textActor ); - } - } - } - } -} - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali diff --git a/dali-toolkit/internal/controls/text-view/text-view-word-processor.h b/dali-toolkit/internal/controls/text-view/text-view-word-processor.h deleted file mode 100644 index 82f36f0..0000000 --- a/dali-toolkit/internal/controls/text-view/text-view-word-processor.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_WORD_PROCESSOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_WORD_PROCESSOR_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ - -namespace TextViewProcessor -{ - -/** - * Creates a data structure with info to layout the word, and data structures with useful info to modify the layout data structure if characters are added or removed. - * - * @param[in] paragraphText The paragraph's text. - * @param[in] textStyles The styles for each character of the paragraph. - * @param[out] wordLayoutInfo Layout info for all characters of the word. - */ -void CreateWordTextInfo( const Text& paragraphText, - Vector& textStyles, - WordLayoutInfo& wordLayoutInfo ); - -/** - * Updates the word size and ascender. - * - * It's called after deleting some characters, split a word in two, - * or when a new word is created when right to left text is reordered. - * - * @param[in] wordLayout The word layout info. - */ -void UpdateLayoutInfo( WordLayoutInfo& wordLayout ); - -/** - * Removes a given number of characters from the given word. - * - * It calls the RemoveCharactersFromWord() function to remove characters from the word. - * - * If the word is a white space \e mergeWords will return \e true and \e textInfoMergeIndicesBegin and \e textInfoMergeIndicesEnd will be set to merge the two adjacent words. - * If the word is a new paragraph character \e mergeParagraphs will return \e true and \e textInfoMergeIndicesBegin and \e textInfoMergeIndicesEnd will be set to merge the two paragraphs. - * - * @param[in,out] relayoutData Natural size (metrics), layout, text-actor info. - * @param[in] numberOfCharacters The number of characters to be deleted. - * @param[out] mergeWords Whether adjacent words need to be merged. - * @param[out] mergeParagraphs Whether current paragraph need to be merged with the next one. - * @param[in,out] textInfoIndicesBegin Indices to the paragraph, word and characters from where to delete characters. It returns from where words need to be removed. - * @param[out] textInfoIndicesEnd If paragraphs or words need to be merged it returns info to delete them (If a word is merged, it has to be removed. Equal for paragraphs). - * @param[out] textInfoMergeIndicesBegin The indices to the first part of the paragraph and word to be merged. - * @param[out] textInfoMergeIndicesEnd The indices to the last part of the paragraph and word to be merged. - * @param[in,out] paragraphLayout Layout info of the paragraph where the word is located. - * @param[out] removedTextActors Stores handles of temoved text-actors. - */ -void RemoveCharactersFromWordInfo( TextView::RelayoutData& relayoutData, - std::size_t numberOfCharacters, - bool& mergeWords, - bool& mergeParagraphs, - TextInfoIndices& textInfoIndicesBegin, - TextInfoIndices& textInfoIndicesEnd, - TextInfoIndices& textInfoMergeIndicesBegin, - TextInfoIndices& textInfoMergeIndicesEnd, - ParagraphLayoutInfo& paragraphLayout, - std::vector& removedTextActors ); -/** - * Removes a given number of characters from the given word. - * - * @pre \e positon and \e position + \e numberOfCharacters can't exceed the bounds of the word. - * - * @param[in] position Character index within the word with the starting position to be deleted. - * @param[in] numberOfCharacters The number of characters to be deleted. - * @param[in,out] wordLayout The input is the layout info of the word. The output is the layout info of the word without the removed characters. - */ -void RemoveCharactersFromWord( std::size_t position, - std::size_t numberOfCharacters, - WordLayoutInfo& wordLayout ); - -/** - * Splits a word in two. - * - * Removes part of the text from the input word and creates a new word with the removed text. - * - * i.e. The result of split 'word' by the position 3 would be 'wor' and 'd'. - * - * @note It deletes whatever there is in the last part of the word. - * - * @param[in] position Character index where to split the word. - * @param[in,out] firstWordLayoutInfo The input is the layout info of the given word. The output is the first part of the input word (from the character \e 0 to the character \e position - \e 1). - * @param[out] lastWordLayoutInfo Layout info of the last part of the given word ( from the character \e position to the end of the word). - */ -void SplitWord( std::size_t position, - WordLayoutInfo& firstWordLayoutInfo, - WordLayoutInfo& lastWordLayoutInfo ); - -/** - * Merges the two given words by adding characters of the last word to the firs one. - * - * @note Does nothing if last part of the word is empty. - * @note If the first part of the word is empty it just copy the last part to it. - * @note It asserts if the first or the last word is a word separator (white space) or a paragraph separator (new paragraph character) - * - * @param[in,out] firstWordLayoutInfo The input is the layout info of the first word. The output is the layout info of the merged word. - * @param[in] lastWordLayoutInfo Layout info of the last word. - */ -void MergeWord( WordLayoutInfo& firstWordLayoutInfo, - const WordLayoutInfo& lastWordLayoutInfo ); - -/** - * Retrieves the layout information of the first character of the given word. - * - * @param[in] wordLayoutInfo The word layout. - * - * @return Layout information of the first character of the word. - */ -CharacterLayoutInfo GetFirstCharacterLayoutInfo( const WordLayoutInfo& wordLayoutInfo ); - -/** - * Retrieves the layout information of the last character of the given word. - * - * @param[in] wordLayoutInfo The word layout. - * - * @return Layout information of the last character of the word. - */ -CharacterLayoutInfo GetLastCharacterLayoutInfo( const WordLayoutInfo& wordLayoutInfo ); - -/** - * Collects text-actors from the given word, within the given indices, and stores them into the text-actor vector. - * - * @param[out] textActors Stores the text-actors of the given word. - * @param[in] characterIndexBegin The first text-actor to be stored. - * @param[in] characterIndexEnd The last text-actor to be stored. - */ -void CollectTextActors( std::vector& textActors, const WordLayoutInfo& word, std::size_t characterIndexBegin, std::size_t characterIndexEnd ); - -/** - * Collects text-actors from the given paragraph, within the given indices, and stores them into the text-actor vector. - * - * @param[out] textActors Stores the text-actors of the given paragraph. - * @param[in] paragraph The paragraph with the words. - * @param[in] wordIndexBegin Index to the first word. - * @param[in] wordIndexEnd Index to the last word. - */ -void CollectTextActorsFromWords( std::vector& textActors, const ParagraphLayoutInfo& paragraph, std::size_t wordIndexBegin, std::size_t wordIndexEnd ); - -} //namespace TextViewProcessor - -} //namespace Internal - -} //namespace Toolkit - -} //namespace Dali - -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_VIEW_WORD_PROCESSOR_H__ diff --git a/dali-toolkit/internal/controls/tool-bar/tool-bar-impl.cpp b/dali-toolkit/internal/controls/tool-bar/tool-bar-impl.cpp index 3bdc399..0bcfe26 100644 --- a/dali-toolkit/internal/controls/tool-bar/tool-bar-impl.cpp +++ b/dali-toolkit/internal/controls/tool-bar/tool-bar-impl.cpp @@ -19,7 +19,7 @@ #include "tool-bar-impl.h" // EXTERNAL INCLUDES -#include +#include #include #include #include @@ -74,12 +74,12 @@ void ToolBar::SetBackground( Actor background ) // ToolBar image background.SetParentOrigin( Dali::ParentOrigin::TOP_CENTER ); background.SetAnchorPoint( Dali::AnchorPoint::TOP_CENTER ); - background.SetPreferredSize( Vector2( mToolBarSize.width, mToolBarSize.height ) ); + background.SetSize( Vector2( mToolBarSize.width, mToolBarSize.height ) ); - ImageActor imageActor = ImageActor::DownCast( background ); - if ( imageActor ) + RenderableActor renderableActor = RenderableActor::DownCast( background ); + if ( renderableActor ) { - imageActor.SetSortModifier( 1.f ); + renderableActor.SetSortModifier( 1.f ); } Self().Add( background ); @@ -125,9 +125,9 @@ void ToolBar::AddControl( Actor control, float relativeSize, Toolkit::Alignment: // Create an alignment container where to place the control. Toolkit::Alignment alignmentContainer = Toolkit::Alignment::New( alignment ); - alignmentContainer.SetSizeScalePolicy( FIT_WITH_ASPECT_RATIO ); + alignmentContainer.SetSizeScalePolicy( SizeScalePolicy::FIT_WITH_ASPECT_RATIO ); alignmentContainer.SetPadding( padding ); - alignmentContainer.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + alignmentContainer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); alignmentContainer.Add( control ); // Insert the control in the table view. @@ -322,7 +322,7 @@ void ToolBar::OnInitialize() // Layout mLayout = Toolkit::TableView::New( 1, 1 ); mLayout.SetName( "TOOLBAR_LAYOUT" ); - mLayout.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); mLayout.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); Self().Add( mLayout ); @@ -359,7 +359,7 @@ void ToolBar::OnControlChildAdd(Actor& child) void ToolBar::OnControlSizeSet( const Vector3& targetSize ) { mToolBarSize = targetSize; - mBackground.SetPreferredSize( Vector2( mToolBarSize.width, mToolBarSize.height ) ); + mBackground.SetSize( Vector2( mToolBarSize.width, mToolBarSize.height ) ); } } // namespace Internal diff --git a/dali-toolkit/internal/controls/view/view-impl.cpp b/dali-toolkit/internal/controls/view/view-impl.cpp index a1d0c09..0262bb7 100644 --- a/dali-toolkit/internal/controls/view/view-impl.cpp +++ b/dali-toolkit/internal/controls/view/view-impl.cpp @@ -19,6 +19,7 @@ #include "view-impl.h" // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -132,7 +133,7 @@ void View::SetBackground( ImageActor backgroundImage ) mBackgroundLayer = Layer::New(); mBackgroundLayer.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - mBackgroundLayer.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + mBackgroundLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); // Add background layer to custom actor. Self().Add( mBackgroundLayer ); @@ -152,7 +153,8 @@ void View::SetBackground( ImageActor backgroundImage ) } backgroundImage.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); - backgroundImage.SetRelayoutEnabled( false ); // We will scale its size manually + backgroundImage.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); + backgroundImage.SetSizeScalePolicy( SizeScalePolicy::FILL_WITH_ASPECT_RATIO ); mBackgroundLayer.Add( backgroundImage ); RelayoutRequest(); @@ -160,14 +162,16 @@ void View::SetBackground( ImageActor backgroundImage ) void View::SetOrientationFunction( Degree portrait, Degree landscale, Degree portraitInverse, Degree landscapeInverse ) { - mOrientationFunction[View::PORTRAIT] = portrait; - mOrientationFunction[View::LANDSCAPE] = landscale; - mOrientationFunction[View::PORTRAIT_INVERSE] = portraitInverse; - mOrientationFunction[View::LANDSCAPE_INVERSE] = landscapeInverse; + mOrientationFunction[View::PORTRAIT] = portrait.degree; + mOrientationFunction[View::LANDSCAPE] = landscale.degree; + mOrientationFunction[View::PORTRAIT_INVERSE] = portraitInverse.degree; + mOrientationFunction[View::LANDSCAPE_INVERSE] = landscapeInverse.degree; } void View::OrientationChanged( Dali::Orientation orientation ) { + Actor self = Self(); + // Nothing to do if orientation doesn't really change. if ( orientation.GetDegrees() == mOrientation || !mAutoRotateEnabled ) { @@ -178,13 +182,13 @@ void View::OrientationChanged( Dali::Orientation orientation ) // has parent so we expect it to be on stage mRotateAnimation = Animation::New( ROTATION_ANIMATION_DURATION ); - mRotateAnimation.RotateTo( Self(), Degree( -orientation.GetDegrees() ), Vector3::ZAXIS, AlphaFunctions::EaseOut ); + mRotateAnimation.AnimateTo( Property( self, Actor::Property::ORIENTATION ), Quaternion( Radian( -orientation.GetRadians() ), Vector3::ZAXIS ), AlphaFunctions::EaseOut ); // Resize the view if( mFullScreen ) { const Vector2& stageSize( Stage::GetCurrent().GetSize() ); - const Vector3& currentSize( Self().GetCurrentSize() ); + const Vector3& currentSize( self.GetCurrentSize() ); float minSize = std::min( stageSize.width, stageSize.height ); float maxSize = std::max( stageSize.width, stageSize.height ); @@ -214,15 +218,15 @@ void View::OrientationChanged( Dali::Orientation orientation ) { // width grows, shrink height faster Vector3 shrink( currentSize );shrink.height = targetSize.height; - mRotateAnimation.Resize( Self(), shrink, AlphaFunctions::EaseOut, 0.0f, ROTATION_ANIMATION_DURATION * 0.5f ); - mRotateAnimation.Resize( Self(), targetSize, AlphaFunctions::EaseIn, 0.0f, ROTATION_ANIMATION_DURATION ); + mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), shrink, AlphaFunctions::EaseOut, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION * 0.5f ) ); + mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), targetSize, AlphaFunctions::EaseIn, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION ) ); } else { // height grows, shrink width faster Vector3 shrink( currentSize );shrink.width = targetSize.width; - mRotateAnimation.Resize( Self(), shrink, AlphaFunctions::EaseOut, 0.0f, ROTATION_ANIMATION_DURATION * 0.5f ); - mRotateAnimation.Resize( Self(), targetSize, AlphaFunctions::EaseIn, 0.0f, ROTATION_ANIMATION_DURATION ); + mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), shrink, AlphaFunctions::EaseOut, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION * 0.5f ) ); + mRotateAnimation.AnimateTo( Property( self, Actor::Property::SIZE ), targetSize, AlphaFunctions::EaseIn, TimePeriod( 0.0f, ROTATION_ANIMATION_DURATION ) ); } } @@ -292,35 +296,23 @@ void View::OnInitialize() } } -void View::OnRelayout( const Vector2& size, RelayoutContainer& container ) -{ - if( mBackgroundLayer ) - { - if( mBackgroundLayer && mBackgroundLayer.GetChildCount() > 0 ) - { - Actor background = mBackgroundLayer.GetChildAt(0); - background.SetScale( FillXYKeepAspectRatio( Vector3( size.width, size.height, 1.0f ), background.GetTargetSize() ) ); - } - } -} - View::Orientation View::DegreeToViewOrientation( Degree degree ) { View::Orientation orientation = PORTRAIT; - if( fabsf( mOrientationFunction[PORTRAIT] - degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT], degree ) ) + if( fabsf( mOrientationFunction[PORTRAIT] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT], degree.degree ) ) { orientation = PORTRAIT; } - else if( fabsf( mOrientationFunction[LANDSCAPE] - degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE], degree ) ) + else if( fabsf( mOrientationFunction[LANDSCAPE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE], degree.degree ) ) { orientation = LANDSCAPE; } - else if( fabsf( mOrientationFunction[PORTRAIT_INVERSE] - degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT_INVERSE], degree ) ) + else if( fabsf( mOrientationFunction[PORTRAIT_INVERSE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[PORTRAIT_INVERSE], degree.degree ) ) { orientation = PORTRAIT_INVERSE; } - else if( fabsf( mOrientationFunction[LANDSCAPE_INVERSE] - degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE_INVERSE], degree ) ) + else if( fabsf( mOrientationFunction[LANDSCAPE_INVERSE] - degree.degree ) <= GetRangedEpsilon( mOrientationFunction[LANDSCAPE_INVERSE], degree.degree ) ) { orientation = LANDSCAPE_INVERSE; } diff --git a/dali-toolkit/internal/controls/view/view-impl.h b/dali-toolkit/internal/controls/view/view-impl.h index 9aacc9e..b956eae 100644 --- a/dali-toolkit/internal/controls/view/view-impl.h +++ b/dali-toolkit/internal/controls/view/view-impl.h @@ -137,11 +137,6 @@ private: // From Control */ virtual void OnInitialize(); - /** - * @copydoc Toolkit::Control::OnRelayout() - */ - virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ); - private: diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index b2e9a08..838592c 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -1,6 +1,8 @@ # Add local source files here toolkit_src_files = \ + $(toolkit_src_dir)/atlas-manager/atlas-manager.cpp \ + $(toolkit_src_dir)/atlas-manager/atlas-manager-impl.cpp \ $(toolkit_src_dir)/builder/builder-actor.cpp \ $(toolkit_src_dir)/builder/builder-animations.cpp \ $(toolkit_src_dir)/builder/builder-impl.cpp \ @@ -12,6 +14,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/builder/replacement.cpp \ $(toolkit_src_dir)/controls/alignment/alignment-impl.cpp \ $(toolkit_src_dir)/controls/bloom-view/bloom-view-impl.cpp \ + $(toolkit_src_dir)/controls/bubble-effect/bubble-emitter-impl.cpp \ $(toolkit_src_dir)/controls/buttons/button-impl.cpp \ $(toolkit_src_dir)/controls/buttons/check-box-button-impl.cpp \ $(toolkit_src_dir)/controls/buttons/push-button-impl.cpp \ @@ -35,6 +38,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/controls/scroll-bar/scroll-bar-impl.cpp \ $(toolkit_src_dir)/controls/scroll-component/scroll-bar-internal-impl.cpp \ $(toolkit_src_dir)/controls/scroll-component/scroll-bar-internal.cpp \ + $(toolkit_src_dir)/controls/scrollable/bouncing-effect-actor.cpp \ $(toolkit_src_dir)/controls/scrollable/item-view/item-view-impl.cpp \ $(toolkit_src_dir)/controls/scrollable/scrollable-impl.cpp \ $(toolkit_src_dir)/controls/scrollable/scroll-connector-impl.cpp \ @@ -54,25 +58,9 @@ toolkit_src_files = \ $(toolkit_src_dir)/controls/slider/slider-impl.cpp \ $(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-input/text-input-decorator-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-handles-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-popup-impl.cpp \ - $(toolkit_src_dir)/controls/text-input/text-input-text-highlight-impl.cpp \ - $(toolkit_src_dir)/controls/text-view/relayout-utilities.cpp \ - $(toolkit_src_dir)/controls/text-view/split-by-char-policies.cpp \ - $(toolkit_src_dir)/controls/text-view/split-by-new-line-char-policies.cpp \ - $(toolkit_src_dir)/controls/text-view/split-by-word-policies.cpp \ - $(toolkit_src_dir)/controls/text-view/text-actor-cache.cpp \ - $(toolkit_src_dir)/controls/text-view/text-processor-bidirectional-info.cpp \ - $(toolkit_src_dir)/controls/text-view/text-processor.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-character-processor.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-impl.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-paragraph-processor.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-processor-dbg.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-processor-helper-functions.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-processor.cpp \ - $(toolkit_src_dir)/controls/text-view/text-view-word-processor.cpp \ + $(toolkit_src_dir)/controls/text-controls/text-field-impl.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/tool-bar/tool-bar-impl.cpp \ $(toolkit_src_dir)/controls/view/view-impl.cpp \ $(toolkit_src_dir)/focus-manager/focus-manager-impl.cpp \ @@ -85,6 +73,32 @@ toolkit_src_files = \ $(toolkit_src_dir)/shader-effects/page-turn-effect-impl.cpp \ $(toolkit_src_dir)/shader-effects/water-effect-impl.cpp \ $(toolkit_src_dir)/styling/style-manager-impl.cpp \ + $(toolkit_src_dir)/text/bidirectional-support.cpp \ + $(toolkit_src_dir)/text/character-set-conversion.cpp \ + $(toolkit_src_dir)/text/clipping/text-clipper.cpp \ + $(toolkit_src_dir)/text/logical-model-impl.cpp \ + $(toolkit_src_dir)/text/multi-language-support.cpp \ + $(toolkit_src_dir)/text/segmentation.cpp \ + $(toolkit_src_dir)/text/shaper.cpp \ + $(toolkit_src_dir)/text/text-control-interface.cpp \ + $(toolkit_src_dir)/text/text-controller.cpp \ + $(toolkit_src_dir)/text/text-io.cpp \ + $(toolkit_src_dir)/text/text-view.cpp \ + $(toolkit_src_dir)/text/text-view-interface.cpp \ + $(toolkit_src_dir)/text/visual-model-impl.cpp \ + $(toolkit_src_dir)/text/decorator/text-decorator.cpp \ + $(toolkit_src_dir)/text/layouts/layout-engine.cpp \ + $(toolkit_src_dir)/text/multi-language-support-impl.cpp \ + $(toolkit_src_dir)/text/rendering/text-backend.cpp \ + $(toolkit_src_dir)/text/rendering/text-renderer.cpp \ + $(toolkit_src_dir)/text/rendering/atlas/text-atlas-renderer.cpp \ + $(toolkit_src_dir)/text/rendering/atlas/atlas-glyph-manager.cpp \ + $(toolkit_src_dir)/text/rendering/atlas/atlas-glyph-manager-impl.cpp \ + $(toolkit_src_dir)/text/rendering/basic/text-basic-renderer.cpp \ + $(toolkit_src_dir)/text/rendering/shaders/text-basic-shader.cpp \ + $(toolkit_src_dir)/text/rendering/shaders/text-basic-shadow-shader.cpp \ + $(toolkit_src_dir)/text/rendering/shaders/text-bgra-shader.cpp \ + $(toolkit_src_dir)/text/rendering/text-backend-impl.cpp \ $(toolkit_src_dir)/transition-effects/cube-transition-effect-impl.cpp \ $(toolkit_src_dir)/transition-effects/cube-transition-cross-effect-impl.cpp \ $(toolkit_src_dir)/transition-effects/cube-transition-fold-effect-impl.cpp \ diff --git a/dali-toolkit/internal/filters/blur-two-pass-filter.cpp b/dali-toolkit/internal/filters/blur-two-pass-filter.cpp index ee152de..af62fb3 100644 --- a/dali-toolkit/internal/filters/blur-two-pass-filter.cpp +++ b/dali-toolkit/internal/filters/blur-two-pass-filter.cpp @@ -142,7 +142,7 @@ void BlurTwoPassFilter::Enable() // create actor to render input with applied emboss effect mActorForInput = ImageActor::New( mInputImage ); mActorForInput.SetParentOrigin( ParentOrigin::CENTER ); - mActorForInput.SetSize(mTargetSize); + mActorForInput.SetSize( mTargetSize ); mActorForInput.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // create internal offscreen for result of horizontal pass @@ -151,7 +151,7 @@ void BlurTwoPassFilter::Enable() // create an actor to render mImageForHorz for vertical blur pass mActorForHorz = ImageActor::New( mImageForHorz ); mActorForHorz.SetParentOrigin( ParentOrigin::CENTER ); - mActorForHorz.SetSize(mTargetSize); + mActorForHorz.SetSize( mTargetSize ); mActorForHorz.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // create internal offscreen for result of the two pass blurred image @@ -160,7 +160,7 @@ void BlurTwoPassFilter::Enable() // create an actor to blend the blurred image and the input image with the given blur strength mActorForBlending = ImageActor::New( mBlurredImage ); mActorForBlending.SetParentOrigin( ParentOrigin::CENTER ); - mActorForBlending.SetSize(mTargetSize); + mActorForBlending.SetSize( mTargetSize ); mActorForBlending.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); mRootActor.Add( mActorForInput ); diff --git a/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp index 5a3a611..b1f3c14 100644 --- a/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/focus-manager-impl.cpp @@ -19,6 +19,7 @@ #include "focus-manager-impl.h" // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -674,7 +675,7 @@ void FocusManager::CreateDefaultFocusIndicatorActor() focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f)); // Apply size constraint to the focus indicator - focusIndicator.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + focusIndicator.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); SetFocusIndicatorActor(focusIndicator); } diff --git a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp index 038f99c..5b0bcb5 100644 --- a/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp @@ -19,6 +19,7 @@ #include "keyboard-focus-manager-impl.h" // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -477,7 +478,7 @@ void KeyboardFocusManager::CreateDefaultFocusIndicatorActor() focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f)); // Apply size constraint to the focus indicator - focusIndicator.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + focusIndicator.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); SetFocusIndicatorActor(focusIndicator); } diff --git a/dali-toolkit/internal/focus-manager/keyinput-focus-manager-impl.cpp b/dali-toolkit/internal/focus-manager/keyinput-focus-manager-impl.cpp index 5d7d4be..9fee428 100644 --- a/dali-toolkit/internal/focus-manager/keyinput-focus-manager-impl.cpp +++ b/dali-toolkit/internal/focus-manager/keyinput-focus-manager-impl.cpp @@ -19,6 +19,7 @@ #include "keyinput-focus-manager-impl.h" // EXTERNAL INCLUDES +#include // for strcmp #include #include diff --git a/dali-toolkit/internal/scripting/script-impl.h b/dali-toolkit/internal/scripting/script-impl.h index ba4094e..bda3721 100644 --- a/dali-toolkit/internal/scripting/script-impl.h +++ b/dali-toolkit/internal/scripting/script-impl.h @@ -17,6 +17,8 @@ * limitations under the License. * */ +// EXTERNAL INCLUDES +#include // INTERNAL INCLUDES #include diff --git a/dali-toolkit/internal/shader-effects/page-turn-effect-impl.cpp b/dali-toolkit/internal/shader-effects/page-turn-effect-impl.cpp index ead7e40..732bbf9 100644 --- a/dali-toolkit/internal/shader-effects/page-turn-effect-impl.cpp +++ b/dali-toolkit/internal/shader-effects/page-turn-effect-impl.cpp @@ -20,7 +20,6 @@ // EXTERNAL HEADERS #include -#include #include #include @@ -54,79 +53,70 @@ const Vector2 DEFAULT_SPINE_SHADOW_PARAMETER(50.0f, 20.0f); // when the vanishing point is very far away(pageHeight*THRESHOLD), make it infinitely, in this case, the page bent horizontally const float THRESHOLD(20.0); -struct CommonParametersConstraint +void CommonParametersConstraint( Matrix& current, const PropertyInputContainer& inputs ) { - Matrix operator()( const Matrix& current, - const PropertyInput& originalCenterProperty, - const PropertyInput& currentCenterProperty, - const PropertyInput& pageSizeProperty) + const Vector2& originalCenter = inputs[0]->GetVector2(); + Vector2 currentCenter = inputs[1]->GetVector2(); + const Vector2& pageSize = inputs[2]->GetVector2(); + + // calculate the curve direction and the vanishing point + // here, the vanishing point is the intersection of spine with the line passing through original center and vertical to curve direction + Vector2 curveDirection( currentCenter - originalCenter ); + curveDirection.Normalize(); + if( fabs(curveDirection.y) < 0.01f) // eliminate the possibility of division by zero in the next step { - const Vector2& originalCenter = originalCenterProperty.GetVector2(); - Vector2 currentCenter = currentCenterProperty.GetVector2(); - const Vector2& pageSize = pageSizeProperty.GetVector2(); - - // calculate the curve direction and the vanishing point - // here, the vanishing point is the intersection of spine with the line passing through original center and vertical to curve direction - Vector2 curveDirection( currentCenter - originalCenter ); - curveDirection.Normalize(); - if( fabs(curveDirection.y) < 0.01f) // eliminate the possibility of division by zero in the next step - { - curveDirection.y = 0.01f; - } - float vanishingPointY = originalCenter.y + curveDirection.x * originalCenter.x / curveDirection.y; - - float curveEndY, cosTheta ,sinTheta ,translateX, translateY; - // when the vanishing point is very far away, make it infinitely, in this case, the page bent horizontally - if( fabs(vanishingPointY-pageSize.y*0.5f) >= pageSize.y*THRESHOLD ) - { - curveDirection = Vector2(-1.f,0.f); - currentCenter.y = originalCenter.y; - - curveEndY = originalCenter.y; - cosTheta = 1.f; - sinTheta = 0.f; - translateX = currentCenter.x - originalCenter.x; - translateY = vanishingPointY; - } - else - { - curveEndY = currentCenter.y - curveDirection.y * (currentCenter.x/curveDirection.x) ; - Vector2 v1( currentCenter.x, currentCenter.y - vanishingPointY ); - v1.Normalize(); - Vector2 v2( originalCenter.x, originalCenter.y - vanishingPointY ); - v2.Normalize(); - cosTheta = v1.x*v2.x + v1.y*v2.y; - sinTheta = ( vanishingPointY > pageSize.y*0.5f ) ? sqrt(1.0-cosTheta*cosTheta) : -sqrt(1.0-cosTheta*cosTheta); - translateX = currentCenter.x - cosTheta*originalCenter.x - sinTheta*( originalCenter.y-vanishingPointY ); - translateY = currentCenter.y + sinTheta*originalCenter.x - cosTheta*( originalCenter.y-vanishingPointY ); - } + curveDirection.y = 0.01f; + } + float vanishingPointY = originalCenter.y + curveDirection.x * originalCenter.x / curveDirection.y; - float originalLength = fabs(originalCenter.x/curveDirection.x); - float currentLength = fabs(currentCenter.x/curveDirection.x); - float curveHeight = 0.45f*sqrt(originalLength*originalLength - currentLength*currentLength); - - Matrix commonParameters( false ); - float* parameterArray = commonParameters.AsFloat(); - parameterArray[0] = cosTheta; - parameterArray[1] = -sinTheta; - parameterArray[2] = originalCenter.x; - parameterArray[3] = originalCenter.y; - parameterArray[4] = sinTheta; - parameterArray[5] = cosTheta; - parameterArray[6] = currentCenter.x; - parameterArray[7] = currentCenter.y; - parameterArray[8] = translateX; - parameterArray[9] = translateY; - parameterArray[10] = vanishingPointY; - parameterArray[11] = curveEndY; - parameterArray[12] = curveDirection.x; - parameterArray[13] = curveDirection.y; - parameterArray[14] = curveHeight; - parameterArray[15] = currentLength; - - return commonParameters; + float curveEndY, cosTheta ,sinTheta ,translateX, translateY; + // when the vanishing point is very far away, make it infinitely, in this case, the page bent horizontally + if( fabs(vanishingPointY-pageSize.y*0.5f) >= pageSize.y*THRESHOLD ) + { + curveDirection = Vector2(-1.f,0.f); + currentCenter.y = originalCenter.y; + + curveEndY = originalCenter.y; + cosTheta = 1.f; + sinTheta = 0.f; + translateX = currentCenter.x - originalCenter.x; + translateY = vanishingPointY; + } + else + { + curveEndY = currentCenter.y - curveDirection.y * (currentCenter.x/curveDirection.x) ; + Vector2 v1( currentCenter.x, currentCenter.y - vanishingPointY ); + v1.Normalize(); + Vector2 v2( originalCenter.x, originalCenter.y - vanishingPointY ); + v2.Normalize(); + cosTheta = v1.x*v2.x + v1.y*v2.y; + sinTheta = ( vanishingPointY > pageSize.y*0.5f ) ? sqrt(1.0-cosTheta*cosTheta) : -sqrt(1.0-cosTheta*cosTheta); + translateX = currentCenter.x - cosTheta*originalCenter.x - sinTheta*( originalCenter.y-vanishingPointY ); + translateY = currentCenter.y + sinTheta*originalCenter.x - cosTheta*( originalCenter.y-vanishingPointY ); } -}; + + float originalLength = fabs(originalCenter.x/curveDirection.x); + float currentLength = fabs(currentCenter.x/curveDirection.x); + float curveHeight = 0.45f*sqrt(originalLength*originalLength - currentLength*currentLength); + + float* parameterArray = current.AsFloat(); + parameterArray[0] = cosTheta; + parameterArray[1] = -sinTheta; + parameterArray[2] = originalCenter.x; + parameterArray[3] = originalCenter.y; + parameterArray[4] = sinTheta; + parameterArray[5] = cosTheta; + parameterArray[6] = currentCenter.x; + parameterArray[7] = currentCenter.y; + parameterArray[8] = translateX; + parameterArray[9] = translateY; + parameterArray[10] = vanishingPointY; + parameterArray[11] = curveEndY; + parameterArray[12] = curveDirection.x; + parameterArray[13] = curveDirection.y; + parameterArray[14] = curveHeight; + parameterArray[15] = currentLength; +} }//namespace @@ -401,12 +391,8 @@ Toolkit::PageTurnEffect PageTurnEffect::CreateShaderEffect( bool enableBlending shaderImpl->mOriginalCenterPropertyIndex = handle.RegisterProperty( ORIGINAL_CENTER_PROPERTY_NAME, Vector2( defaultPageSize[0], defaultPageSize[1]*0.5f ) ); shaderImpl->mCurrentCenterPropertyIndex = handle.RegisterProperty( CURRENT_CENTER_PROPERTY_NAME, Vector2( defaultPageSize[0], defaultPageSize[1]*0.5f ) ); - shaderImpl->mInternalConstraint = Constraint::New( handle.GetPropertyIndex( "uCommonParameters" ), - LocalSource( shaderImpl->mOriginalCenterPropertyIndex ), - LocalSource( shaderImpl->mCurrentCenterPropertyIndex ), - LocalSource( handle.GetPropertyIndex( PAGE_SIZE_PROPERTY_NAME ) ), - CommonParametersConstraint() ); - handle.ApplyConstraint( shaderImpl->mInternalConstraint ); + + shaderImpl->ApplyInternalConstraint(); // setting isTurningBack to -1.0f here means turning page forward handle.SetUniform( IS_TURNING_BACK_PROPERTY_NAME, -1.0f ); @@ -447,7 +433,11 @@ void PageTurnEffect::SetSpineShadowParameter(const Vector2& spineShadowParameter void PageTurnEffect::ApplyInternalConstraint() { - mShaderEffect.ApplyConstraint( mInternalConstraint ); + Constraint constraint = Constraint::New( mShaderEffect, mShaderEffect.GetPropertyIndex( "uCommonParameters" ), CommonParametersConstraint ); + constraint.AddSource( LocalSource( mOriginalCenterPropertyIndex ) ); + constraint.AddSource( LocalSource( mCurrentCenterPropertyIndex ) ); + constraint.AddSource( LocalSource( mShaderEffect.GetPropertyIndex( PAGE_SIZE_PROPERTY_NAME ) ) ); + constraint.Apply(); } const std::string& PageTurnEffect::GetPageSizePropertyName() const diff --git a/dali-toolkit/internal/shader-effects/page-turn-effect-impl.h b/dali-toolkit/internal/shader-effects/page-turn-effect-impl.h index 1e49e33..b75af2e 100644 --- a/dali-toolkit/internal/shader-effects/page-turn-effect-impl.h +++ b/dali-toolkit/internal/shader-effects/page-turn-effect-impl.h @@ -114,7 +114,6 @@ private: Property::Index mOriginalCenterPropertyIndex; Property::Index mCurrentCenterPropertyIndex; - Constraint mInternalConstraint; private: //undefined copy constructor. diff --git a/dali-toolkit/internal/styling/style-manager-impl.cpp b/dali-toolkit/internal/styling/style-manager-impl.cpp index fa453dd..4378e84 100644 --- a/dali-toolkit/internal/styling/style-manager-impl.cpp +++ b/dali-toolkit/internal/styling/style-manager-impl.cpp @@ -36,6 +36,7 @@ namespace const char* LANDSCAPE_QUALIFIER = "landscape"; const char* PORTRAIT_QUALIFIER = "portrait"; +const char* FONT_SIZE_QUALIFIER = "font-size-"; const char* DEFAULT_THEME = DALI_STYLE_DIR "tizen-default-theme.json"; @@ -99,7 +100,8 @@ Toolkit::StyleManager StyleManager::Get() } StyleManager::StyleManager() - : mOrientationDegrees( 0 ) // Portrait +: mOrientationDegrees( 0 ), // Portrait + mDefaultFontSize( -1 ) { // Add theme builder constants mThemeBuilderConstants[ PACKAGE_PATH_KEY ] = DEFAULT_PACKAGE_PATH; @@ -110,6 +112,8 @@ StyleManager::StyleManager() if( styleMonitor ) { styleMonitor.StyleChangeSignal().Connect( this, &StyleManager::StyleMonitorChange ); + + mDefaultFontSize = styleMonitor.GetDefaultFontSize(); } } @@ -244,9 +248,13 @@ void StyleManager::BuildQualifiedStyleName( const std::string& styleName, const void StyleManager::ApplyStyle( Toolkit::Builder builder, Toolkit::Control control ) { - // Convert control name to lower case - std::string styleName = control.GetTypeName(); - std::transform( styleName.begin(), styleName.end(), styleName.begin(), ::tolower ); + std::string styleName = control.GetStyleName(); + if( styleName.empty() ) + { + // Convert control name to lower case + styleName = control.GetTypeName(); + std::transform( styleName.begin(), styleName.end(), styleName.begin(), ::tolower ); + } // Apply the style after choosing the correct actual style (e.g. landscape or portrait) StringList qualifiers; @@ -266,6 +274,14 @@ void StyleManager::ApplyStyle( Toolkit::Builder builder, Toolkit::Control contro // Remove the last qualifier in an attempt to find a style that is valid qualifiers.pop_back(); } + + if( mDefaultFontSize >= 0 ) + { + // Apply the style for logical font size + std::stringstream fontSizeQualifier; + fontSizeQualifier << styleName << "-" << FONT_SIZE_QUALIFIER << mDefaultFontSize; + builder.ApplyStyle( fontSizeQualifier.str(), control ); + } } void StyleManager::ApplyThemeStyle( Toolkit::Control control ) @@ -380,6 +396,11 @@ void StyleManager::CacheBuilder( Toolkit::Builder builder, const std::string& ke void StyleManager::StyleMonitorChange( StyleMonitor styleMonitor, StyleChange styleChange ) { + if( styleChange.defaultFontSizeChange ) + { + mDefaultFontSize = styleMonitor.GetDefaultFontSize(); + } + mStyleChangeSignal.Emit( Toolkit::StyleManager::Get(), styleChange ); } diff --git a/dali-toolkit/internal/styling/style-manager-impl.h b/dali-toolkit/internal/styling/style-manager-impl.h index 648c11d..09d0c13 100644 --- a/dali-toolkit/internal/styling/style-manager-impl.h +++ b/dali-toolkit/internal/styling/style-manager-impl.h @@ -241,6 +241,8 @@ private: Orientation mOrientation; ///< Handle to application orientation object int mOrientationDegrees; ///< Directly set value of orientation + int mDefaultFontSize; ///< Logical size, not a point-size + std::string mThemeFile; ///< The full path of the current theme file Property::Map mThemeBuilderConstants; ///< Contants to give the theme builder diff --git a/dali-toolkit/internal/text/bidirectional-line-info-run.h b/dali-toolkit/internal/text/bidirectional-line-info-run.h new file mode 100644 index 0000000..355668d --- /dev/null +++ b/dali-toolkit/internal/text/bidirectional-line-info-run.h @@ -0,0 +1,49 @@ +#ifndef __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_LINE_INFO_RUN_H__ +#define __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_LINE_INFO_RUN_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief BidirectionalLineInfoRun + */ +struct BidirectionalLineInfoRun +{ + CharacterRun characterRun; ///< The initial character index within the whole text and the number of characters of the run. + CharacterIndex* visualToLogicalMap; ///< Pointer to the visual to logical map table. + CharacterDirection direction; ///< Direction of the first character of the paragraph. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_LINE_INFO_RUN_H__ diff --git a/dali-toolkit/internal/text/bidirectional-paragraph-info-run.h b/dali-toolkit/internal/text/bidirectional-paragraph-info-run.h new file mode 100644 index 0000000..feefa84 --- /dev/null +++ b/dali-toolkit/internal/text/bidirectional-paragraph-info-run.h @@ -0,0 +1,51 @@ +#ifndef __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_PARAGRAPH_INFO_RUN_H__ +#define __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_PARAGRAPH_INFO_RUN_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief BidirectionalParagraphInfoRun + * + * In terms of the bidirectional algorithm, a 'paragraph' is understood as a run of characters between Paragraph Separators or appropriate Newline Functions. + * A 'paragraph' may also be determined by higher-level protocols like a mark-up tag. + */ +struct BidirectionalParagraphInfoRun +{ + CharacterRun characterRun; ///< The initial character index within the whole text and the number of characters of the run. + BidiInfoIndex bidirectionalInfoIndex; ///< Index to the table with the bidirectional info per paragraph. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_PARAGRAPH_INFO_RUN_H__ diff --git a/dali-toolkit/internal/text/bidirectional-support.cpp b/dali-toolkit/internal/text/bidirectional-support.cpp new file mode 100644 index 0000000..c58c126 --- /dev/null +++ b/dali-toolkit/internal/text/bidirectional-support.cpp @@ -0,0 +1,289 @@ +/* + * 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 + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace +{ + +/** + * @brief Get the lines of a paragraph. + * + * @param[in] paragraphInfo The paragraph. + * @param[in] lines The lines. + * @param[in] lineIndex Index pointing the first line to be checked. + * @param[out] firstLine Index to the first line of the paragraph. + * @param[out] numberOfLines The number of lines. + */ +void GetLines( const BidirectionalParagraphInfoRun& paragraphInfo, + const Vector& lines, + unsigned int lineIndex, + unsigned int& firstLine, + unsigned int& numberOfLines ) +{ + firstLine = lineIndex; + numberOfLines = 0u; + + const CharacterIndex lastCharacterIndex = paragraphInfo.characterRun.characterIndex + paragraphInfo.characterRun.numberOfCharacters; + bool firstLineFound = false; + + for( Vector::ConstIterator it = lines.Begin() + lineIndex, + endIt = lines.End(); + it != endIt; + ++it ) + { + const LineRun& line = *it; + + if( ( line.characterRun.characterIndex + line.characterRun.numberOfCharacters > paragraphInfo.characterRun.characterIndex ) && + ( lastCharacterIndex > line.characterRun.characterIndex ) ) + { + firstLineFound = true; + ++numberOfLines; + } + else if( lastCharacterIndex <= line.characterRun.characterIndex ) + { + // nothing else to do. + break; + } + + if( !firstLineFound ) + { + ++firstLine; + } + } +} + +} // namespace + +void SetBidirectionalInfo( const Vector& text, + const Vector& scripts, + const Vector& lineBreakInfo, + Vector& bidirectionalInfo ) +{ + // Traverse the script runs. If there is one with a right to left script, create the bidirectional info for the paragraph containing that script is needed. + // From the bidirectional point of view, a paragraph is the piece of text between two LINE_MUST_BREAK. + + // Index pointing the first character of the current paragraph. + CharacterIndex paragraphCharacterIndex = 0u; + + // Pointer to the text buffer. + const Character* textBuffer = text.Begin(); + + // Pointer to the line break info buffer. + const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + + // The number of characters. + const Length numberOfCharacters = text.Count(); + + // Handle to the bidirectional info module in text-abstraction. + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + + for( Vector::ConstIterator it = scripts.Begin(), + endIt = scripts.End(); + it != endIt; + ++it ) + { + const ScriptRun& scriptRun = *it; + const CharacterIndex lastScriptRunIndex = scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters; + + if( TextAbstraction::IsRightToLeftScript( scriptRun.script ) && // The script is right to left. + ( lastScriptRunIndex > paragraphCharacterIndex ) ) // It isn't part of a previous paragraph. + { + // Find the paragraphs which contains this script run. + // Consider: + // 1) Different paragraphs may contain this script run. + // ------||------------------- rtl sr ------------------------||------------------- + // --||----- p -----||------------------ p -------------||-------- p ------||------ + // + // 2) The paragraph which contains this script run may contain other right to left script runs. + // -----||--- rtl sr ---||---- ltr sr ----||---------- rtl sr -----------||-------- + // -----||---------------------------------- p -----------------------------------| + + while( lastScriptRunIndex > paragraphCharacterIndex ) + { + // There is a paragraph which contains the current script. + + Length index = paragraphCharacterIndex; + while( ( index < numberOfCharacters ) && ( paragraphCharacterIndex < lastScriptRunIndex ) ) + { + if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ) ) + { + if( index >= scriptRun.characterRun.characterIndex ) + { + // The Bidirectional run must have the same number of characters than the paragraph. + BidirectionalParagraphInfoRun bidirectionalRun; + bidirectionalRun.characterRun.characterIndex = paragraphCharacterIndex; + bidirectionalRun.characterRun.numberOfCharacters = ( index - paragraphCharacterIndex ) + 1u; // The must break character is part of the paragrah. + + // Create the bidirectional info for the whole paragraph and store the index to the table with this info in the run. + bidirectionalRun.bidirectionalInfoIndex = bidirectionalSupport.CreateInfo( textBuffer + bidirectionalRun.characterRun.characterIndex, + bidirectionalRun.characterRun.numberOfCharacters ); + + bidirectionalInfo.PushBack( bidirectionalRun ); + } + + // Update the character index of the next paragraph. + paragraphCharacterIndex = index + 1u; + } + ++index; + } + + // The last character is always a must-break, so there is no need to check if there is characters left. + } + } + } +} + +void ReplaceBidirectionalInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +void ReorderLines( const Vector& bidirectionalInfo, + Vector& lineRuns, + Vector& lineInfoRuns ) +{ + // Handle to the bidirectional info module in text-abstraction. + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + + // Keep an index to the first line to be checked if it's contained inside the paragraph. + // Avoids check the lines from the beginning for each paragraph. + unsigned int lineIndex = 0u; + + for( Vector::ConstIterator it = bidirectionalInfo.Begin(), + endIt = bidirectionalInfo.End(); + it != endIt; + ++it ) + { + const BidirectionalParagraphInfoRun& paragraphInfo = *it; + const CharacterDirection direction = bidirectionalSupport.GetParagraphDirection( paragraphInfo.bidirectionalInfoIndex ); + + // Get the lines for this paragraph. + unsigned int firstLine = 0u; + unsigned int numberOfLines = 0u; + + // Get an index to the first line and the number of lines of the current paragraph. + GetLines( paragraphInfo, + lineRuns, + lineIndex, + firstLine, + numberOfLines ); + + lineIndex = firstLine + numberOfLines; + + // Traverse the lines and reorder them + for( Vector::Iterator lineIt = lineRuns.Begin() + firstLine, + endLineIt = lineRuns.Begin() + firstLine + numberOfLines; + lineIt != endLineIt; + ++lineIt ) + { + LineRun& line = *lineIt; + + // Sets the paragraph's direction. + line.direction = direction; + + // Creates a bidirectional info for the line run. + BidirectionalLineInfoRun lineInfoRun; + lineInfoRun.characterRun.characterIndex = line.characterRun.characterIndex; + lineInfoRun.characterRun.numberOfCharacters = line.characterRun.numberOfCharacters; + lineInfoRun.direction = direction; + + // Allocate space for the conversion maps. + // The memory is freed after the visual to logical to visual conversion tables are built in the logical model. + lineInfoRun.visualToLogicalMap = reinterpret_cast( malloc( line.characterRun.numberOfCharacters * sizeof( CharacterIndex ) ) ); + + // Reorders the line. + bidirectionalSupport.Reorder( paragraphInfo.bidirectionalInfoIndex, + line.characterRun.characterIndex - paragraphInfo.characterRun.characterIndex, + line.characterRun.numberOfCharacters, + lineInfoRun.visualToLogicalMap ); + + // Push the run into the vector. + lineInfoRuns.PushBack( lineInfoRun ); + } + } +} + +void ReorderLines( LogicalModel& logicalModel, + const VisualModel& visualModel, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +bool GetMirroredText( const Vector& text, + Vector& mirroredText ) +{ + // Handle to the bidirectional info module in text-abstraction. + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + + mirroredText = text; + + return bidirectionalSupport.GetMirroredText( mirroredText.Begin(), + mirroredText.Count() ); +} + +void GetCharactersDirection( const Vector& bidirectionalInfo, + Vector& directions ) +{ + // Handle to the bidirectional info module in text-abstraction. + TextAbstraction::BidirectionalSupport bidirectionalSupport = TextAbstraction::BidirectionalSupport::Get(); + + CharacterIndex index = 0u; + CharacterDirection* directionsBuffer = directions.Begin(); + for( Vector::ConstIterator it = bidirectionalInfo.Begin(), + endIt = bidirectionalInfo.End(); + it != endIt; + ++it ) + { + const BidirectionalParagraphInfoRun& paragraph = *it; + + // Fills with left to right those paragraphs without right to left characters. + memset( directionsBuffer + index, false, ( paragraph.characterRun.characterIndex - index ) * sizeof( bool ) ); + index += paragraph.characterRun.numberOfCharacters; + + bidirectionalSupport.GetCharactersDirection( paragraph.bidirectionalInfoIndex, + directionsBuffer + paragraph.characterRun.characterIndex, + paragraph.characterRun.numberOfCharacters ); + } + + // Fills with left to right those paragraphs without right to left characters. + memset( directionsBuffer + index, false, ( directions.Count() - index ) * sizeof( bool ) ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/bidirectional-support.h b/dali-toolkit/internal/text/bidirectional-support.h new file mode 100644 index 0000000..f51e5e7 --- /dev/null +++ b/dali-toolkit/internal/text/bidirectional-support.h @@ -0,0 +1,143 @@ +#ifndef __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_SUPPORT_H__ +#define __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_SUPPORT_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 + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class LogicalModel; +class VisualModel; + +/** + * Sets the bidirectional info into the logical model. + * + * @param[in] text Vector of UTF-32 characters. + * @param[in] scripts Vector containing the script runs for the whole text. + * @param[in] lineBreakInfo The line break info. + * @param[out] bidirectionalInfo Vector with the bidirectional infor for each paragraph. + */ +void SetBidirectionalInfo( const Vector& text, + const Vector& scripts, + const Vector& lineBreakInfo, + Vector& bidirectionalInfo ); + +/** + * Replaces the bidirectional info from the logical model. + * + * @pre The @p model needs to have a text set. + * @pre The @p model needs to have the line break info set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ReplaceBidirectionalInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +/** + * Sets the visual to logical map tables. + * + * Any map tables previously set are removed. + * It sets the paragraph's direction to each line. + * + * @pre The @p logicalModel needs to have a text set. + * @pre The @p logicalModel needs to have the bidirectional info indices for each paragraph set. + * @pre The @p visualModel needs to have the laid-out lines info set. + * + * @param[in] bidirectionalInfo Vector with the bidirectional infor for each paragraph. + * @param[in,out] lineRuns The line runs converted to characters. + * @param[out] lineInfoRuns line runs with the visual to logical conversion maps. + */ +void ReorderLines( const Vector& bidirectionalInfo, + Vector& lineRuns, + Vector& lineInfoRuns ); + +/** + * Replaces the visual to logical and logical to visual map tables. + * + * @pre The @p logicalModel needs to have a text set. + * @pre The @p logicalModel needs to have the line break info set. + * @pre The @p visualModel needs to have the laid-out lines info set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] logicalModel The text's logical model. + * @param[in] visualModel The text's visual model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ReorderLines( LogicalModel& logicalModel, + const VisualModel& visualModel, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +/** + * @brief Replaces any character which could be mirrored. + * + * @param[in] text The text. + * @param[in] mirroredText The mirroredText. + * + * @return @e true if a character has been replaced. + */ +bool GetMirroredText( const Vector& text, + Vector& mirroredText ); + +/** + * @brief Retrieves the character's directions. + * + * @pre The @p logicalModel needs to have a text set. + * @pre The @p logicalModel needs to have the bidirectional info indices for each paragraph set. + * + * @param[in] bidirectionalInfo Vector with the bidirectional infor for each paragraph. + * @param[out] directions The direction, @e false is left to right and @e true is right to left, of each character of the paragraph. + */ +void GetCharactersDirection( const Vector& bidirectionalInfo, + Vector& directions ); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BIDIRECTIONAL_SUPPORT_H__ diff --git a/dali-toolkit/internal/text/character-run.h b/dali-toolkit/internal/text/character-run.h new file mode 100644 index 0000000..221ecbd --- /dev/null +++ b/dali-toolkit/internal/text/character-run.h @@ -0,0 +1,48 @@ +#ifndef __DALI_TOOLKIT_TEXT_CHARACTER_RUN_H__ +#define __DALI_TOOLKIT_TEXT_CHARACTER_RUN_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A run of consecutive characters. + */ +struct CharacterRun +{ + CharacterIndex characterIndex; ///< Index to the first character. + Length numberOfCharacters; ///< Number of characters in the run. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_CHARACTER_RUN_H__ diff --git a/dali-toolkit/internal/text/character-set-conversion.cpp b/dali-toolkit/internal/text/character-set-conversion.cpp new file mode 100644 index 0000000..3afecbb --- /dev/null +++ b/dali-toolkit/internal/text/character-set-conversion.cpp @@ -0,0 +1,216 @@ +/* + * 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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace +{ + const static uint8_t U1 = 1u; + const static uint8_t U2 = 2u; + const static uint8_t U3 = 3u; + const static uint8_t U4 = 4u; + const static uint8_t U0 = 0u; + const static uint8_t UTF8_LENGTH[256] = { + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // lead byte = 0xxx xxxx (U+0000 - U+007F + some extended ascii characters) + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // + U1, U1, // + + U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, // + U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, // lead byte = 110x xxxx (U+0080 - U+07FF) + U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, // + U2, U2, // + + U3, U3, U3, U3, U3, U3, U3, U3, U3, U3, // lead byte = 1110 xxxx (U+0800 - U+FFFF) + U3, U3, U3, U3, U3, U3, // + + U4, U4, U4, U4, U4, U4, U4, U4, // lead byte = 1111 0xxx (U+10000 - U+1FFFFF) + + U0, U0, U0, U0, // Non valid. + U0, U0, U0, U0, // Non valid. + }; +} // namespace + +uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length ) +{ + uint32_t numberOfCharacters = 0u; + + const uint8_t* begin = utf8; + const uint8_t* end = utf8 + length; + + for( ; begin < end ; begin += UTF8_LENGTH[*begin], ++numberOfCharacters ); + + return numberOfCharacters; +} + +uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters ) +{ + uint32_t numberOfBytes = 0u; + + const uint32_t* begin = utf32; + const uint32_t* end = utf32 + numberOfCharacters; + + for( ; begin < end; ++begin ) + { + const uint32_t code = *begin; + + if( code < 0x80u ) + { + ++numberOfBytes; + } + else if( code < 0x800u ) + { + numberOfBytes += U2; + } + else if( code < 0x10000u ) + { + numberOfBytes += U3; + } + else if( code < 0x200000u ) + { + numberOfBytes += U4; + } + } + + return numberOfBytes; +} + +uint32_t Utf8ToUtf32( const uint8_t* const utf8, uint32_t length, uint32_t* utf32 ) +{ + uint32_t numberOfCharacters = 0u; + + const uint8_t* begin = utf8; + const uint8_t* end = utf8 + length; + + for( ; begin < end ; ++numberOfCharacters ) + { + const uint8_t leadByte = *begin; + + switch( UTF8_LENGTH[leadByte] ) + { + case U1: + { + *utf32++ = leadByte; + begin++; + break; + } + + case U2: + { + uint32_t& code = *utf32++; + code = leadByte & 0x1fu; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U3: + { + uint32_t& code = *utf32++; + code = leadByte & 0x0fu; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + + case U4: + { + uint32_t& code = *utf32++; + code = leadByte & 0x07u; + begin++; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + code <<= 6u; + code |= *begin++ & 0x3fu; + break; + } + } + } + + return numberOfCharacters; +} + +uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, uint8_t* utf8 ) +{ + const uint32_t* begin = utf32; + const uint32_t* end = utf32 + numberOfCharacters; + + uint8_t* utf8Begin = utf8; + + for( ; begin < end; ++begin ) + { + const uint32_t code = *begin; + + if( code < 0x80u ) + { + *utf8++ = code; + } + else if( code < 0x800u ) + { + *utf8++ = static_cast( code >> 6u ) | 0xc0u; // lead byte for 2 byte sequence + *utf8++ = static_cast( code & 0x3f ) | 0x80u; // continuation byte + } + else if( code < 0x10000u ) + { + *utf8++ = static_cast( code >> 12u ) | 0xe0u; // lead byte for 2 byte sequence + *utf8++ = static_cast( ( code >> 6u ) & 0x3f ) | 0x80u; // continuation byte + *utf8++ = static_cast( code & 0x3f ) | 0x80u; // continuation byte + } + else if( code < 0x200000u ) + { + *utf8++ = static_cast( code >> 18u ) | 0xf0u; // lead byte for 2 byte sequence + *utf8++ = static_cast( ( code >> 12u ) & 0x3f ) | 0x80u; // continuation byte + *utf8++ = static_cast( ( code >> 6u ) & 0x3f ) | 0x80u; // continuation byte + *utf8++ = static_cast( code & 0x3f ) | 0x80u; // continuation byte + } + } + + return utf8 - utf8Begin; +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/character-set-conversion.h b/dali-toolkit/internal/text/character-set-conversion.h new file mode 100644 index 0000000..7a62498 --- /dev/null +++ b/dali-toolkit/internal/text/character-set-conversion.h @@ -0,0 +1,83 @@ +#ifndef __DALI_TOOLKIT_CHARACTER_SET_CONVERSION_H__ +#define __DALI_TOOLKIT_CHARACTER_SET_CONVERSION_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +/** + * @brief Retrieves the number of characters of the text array encoded in UTF8 + * + * @param[in] utf8 The pointer to the UTF8 array. + * @param[in] length The length of the UTF8 array. + * + * @return The number of characters. + */ +uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length ); + +/** + * @brief Retrieves the number of bytes needed to encode in UTF8 the given text array encoded in UTF32. + * + * @param[in] utf32 The pointer to the UTF32 array. + * @param[in] numberOfCharacters The number of characters of the UTF32 array. + * + * @return The number of bytes. + */ +uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters ); + +/** + * @brief Converts a text array encoded in UTF8 into a text array encoded in UTF32. + * + * The @p utf32 buffer needs to be big enough to store all the characters. + * + * @param[in] utf8 The pointer to the UTF8 array. + * @param[in] length The length of the UTF8 array. + * @param[out] utf32 The pointer to the UTF32 array. + * + * @return The number of characters. + */ +uint32_t Utf8ToUtf32( const uint8_t* const utf8, uint32_t length, uint32_t* utf32 ); + +/** + * @brief Converts a text array encoded in UTF32 into a text array encoded in UTF8. + * + * The @p utf8 buffer needs to be big enough to store all the characters. + * + * @param[in] utf32 The pointer to the UTF32 array. + * @param[in] numberOfCharacters The number of characters of the UTF32 array. + * @param[out] utf8 The pointer to the UTF8 array. + * + * @return The number of bytes. + */ +uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, uint8_t* utf8 ); + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_CHARACTER_SET_CONVERSION_H__ diff --git a/dali-toolkit/internal/text/clipping/text-clipper.cpp b/dali-toolkit/internal/text/clipping/text-clipper.cpp new file mode 100644 index 0000000..7a79e4c --- /dev/null +++ b/dali-toolkit/internal/text/clipping/text-clipper.cpp @@ -0,0 +1,159 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +namespace +{ + +// Currently on desktop machines 2k x 2k is the maximum frame buffer size, on target is 4k x 4k. +const float MAX_OFFSCREEN_RENDERING_SIZE = 2048.f; + +} // namespace + + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +ClipperPtr Clipper::New( const Vector2& size ) +{ + ClipperPtr clipper( new Clipper() ); + + // Second-phase init + clipper->Initialize( size ); + + return clipper; +} + +Actor Clipper::GetRootActor() const +{ + return mOffscreenRootActor; +} + +ImageActor Clipper::GetImageActor() const +{ + return mImageActor; +} + +void Clipper::Refresh( const Vector2& size ) +{ + const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.width ), + std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.height ) ); + + const bool sizeChanged = offscreenSize != mCurrentOffscreenSize; + + if( sizeChanged ) + { + // Reconfigure camera for current size. + mOffscreenCameraActor.SetOrthographicProjection( offscreenSize ); + + // Recreate frame buffer for offscreen rendering when the size changes. + FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width, + offscreenSize.height, + Pixel::RGBA8888 ); + + mImageActor.SetSize( offscreenSize ); + mImageActor.SetImage( frameBufferImage ); + mRenderTask.SetTargetFrameBuffer( frameBufferImage ); + + // Stores current sizPe to avoid create new Dali resources if text changes. + mCurrentOffscreenSize = offscreenSize; + } + + mRenderTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); +} + +void Clipper::Initialize( const Vector2& size ) +{ + const Size offscreenSize( std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.width ), + std::min( MAX_OFFSCREEN_RENDERING_SIZE, size.height ) ); + + // Create a root actor and an image actor for offscreen rendering. + mOffscreenRootActor = Layer::New(); + mOffscreenRootActor.SetRelayoutEnabled( false ); + mOffscreenRootActor.SetColorMode( USE_OWN_COLOR ); + mOffscreenRootActor.SetPositionInheritanceMode( DONT_INHERIT_POSITION ); + mOffscreenRootActor.SetInheritScale( false ); + mOffscreenRootActor.SetDepthTestDisabled( true ); + mOffscreenRootActor.SetSize( offscreenSize ); + + mImageActor = ImageActor::New(); + mImageActor.SetRelayoutEnabled( false ); + mImageActor.SetParentOrigin( ParentOrigin::CENTER ); + mImageActor.SetBlendFunc( BlendingFactor::ONE, BlendingFactor::ONE_MINUS_SRC_ALPHA, + BlendingFactor::ONE, BlendingFactor::ONE ); + mImageActor.SetScale( Vector3( 1.0f, -1.0f, 1.0f ) ); + mImageActor.SetSize( offscreenSize ); + + // Creates a new camera actor. + mOffscreenCameraActor = CameraActor::New(); + mOffscreenCameraActor.SetParentOrigin( ParentOrigin::CENTER ); + mOffscreenCameraActor.SetOrthographicProjection( offscreenSize ); + mOffscreenRootActor.Add( mOffscreenCameraActor ); // camera to shoot the offscreen text + + // Creates a new render task. + mRenderTask = Stage::GetCurrent().GetRenderTaskList().CreateTask(); + mRenderTask.SetSourceActor( mOffscreenRootActor ); + mRenderTask.SetClearColor( Color::TRANSPARENT ); + mRenderTask.SetClearEnabled( true ); + mRenderTask.SetExclusive( true ); + mRenderTask.SetCameraActor( mOffscreenCameraActor ); + + // Creates a frame buffer for offscreen rendering + FrameBufferImage frameBufferImage = FrameBufferImage::New( offscreenSize.width, + offscreenSize.height, + Pixel::RGBA8888 ); + mImageActor.SetImage( frameBufferImage ); + mRenderTask.SetTargetFrameBuffer( frameBufferImage ); + + // Stores current size to avoid create new Dali resources if text changes. + mCurrentOffscreenSize = offscreenSize; +} + +Clipper::Clipper() +{ +} + +Clipper::~Clipper() +{ + if( Stage::IsInstalled() ) + { + UnparentAndReset( mOffscreenRootActor ); + UnparentAndReset( mImageActor ); + + Stage::GetCurrent().GetRenderTaskList().RemoveTask( mRenderTask ); + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/clipping/text-clipper.h b/dali-toolkit/internal/text/clipping/text-clipper.h new file mode 100644 index 0000000..d435c86 --- /dev/null +++ b/dali-toolkit/internal/text/clipping/text-clipper.h @@ -0,0 +1,118 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_CLIPPER_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_CLIPPER_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 +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class Clipper; +typedef IntrusivePtr ClipperPtr; + +/** + * @brief A helper class for clipping actors using a FrameBufferImage. + */ +class Clipper : public RefObject +{ +public: + + /** + * @brief Create a clipper. + * + * @param[in] size The size of the clipping region. + */ + static ClipperPtr New( const Vector2& size ); + + /** + * @brief Children added to this actor will be clipped with the specified region. + * + * @note This is done by rendering to a FrameBufferImage which must then be displayed; see also GetImageActor(). + * @return The root actor. + */ + Actor GetRootActor() const; + + /** + * @brief This actor will display the resulting FrameBufferImage. + * + * @return The image actor. + */ + ImageActor GetImageActor() const; + + /** + * @brief Refresh the contents of the FrameBufferImage. + * + * @param[in] size The size of the clipping region. + */ + void Refresh( const Vector2& size ); + +private: // Implementation + + /** + * @brief Second-phase init + * + * @param[in] size The size of the clipping region. + */ + void Initialize( const Vector2& size ); + + /** + * Construct a new Clipper. + */ + Clipper(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~Clipper(); + +private: + + // Undefined copy constructor and assignment operators + Clipper(const Clipper&); + Clipper& operator=(const Clipper& rhs); + +private: // Data + + Layer mOffscreenRootActor; + CameraActor mOffscreenCameraActor; + ImageActor mImageActor; + RenderTask mRenderTask; + Vector2 mCurrentOffscreenSize; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_CLIPPER_H__ diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp new file mode 100644 index 0000000..3a6d7da --- /dev/null +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -0,0 +1,1049 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG_ENABLED +#define DECORATOR_DEBUG + +#endif + + +namespace Dali +{ +namespace Internal +{ +namespace +{ +#ifdef DECORATOR_DEBUG +Integration::Log::Filter* gLogFilter( Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_TEXT_DECORATOR") ); +#endif +} +} +} + + +// Local Data +namespace +{ + +const char* DEFAULT_GRAB_HANDLE_IMAGE( DALI_IMAGE_DIR "insertpoint-icon.png" ); +const char* DEFAULT_SELECTION_HANDLE_ONE( DALI_IMAGE_DIR "text-input-selection-handle-left.png" ); +const char* DEFAULT_SELECTION_HANDLE_TWO( DALI_IMAGE_DIR "text-input-selection-handle-right.png" ); +//const char* DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" ); +//const char* DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" ); + +const Dali::Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.5f, 2.0f, 1.0f ); +const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f ); + +const std::size_t CURSOR_BLINK_INTERVAL = 500; // Cursor blink interval +const std::size_t MILLISECONDS = 1000; + +const float DISPLAYED_HIGHLIGHT_Z_OFFSET( -0.05f ); + +/** + * structure to hold coordinates of each quad, which will make up the mesh. + */ +struct QuadCoordinates +{ + /** + * Default constructor + */ + QuadCoordinates() + { + } + + /** + * Constructor + * @param[in] x1 left co-ordinate + * @param[in] y1 top co-ordinate + * @param[in] x2 right co-ordinate + * @param[in] y2 bottom co-ordinate + */ + QuadCoordinates(float x1, float y1, float x2, float y2) + : min(x1, y1), + max(x2, y2) + { + } + + Dali::Vector2 min; ///< top-left (minimum) position of quad + Dali::Vector2 max; ///< bottom-right (maximum) position of quad +}; + +typedef std::vector QuadContainer; + +/** + * @brief Takes a bounding rectangle in the local coordinates of an actor and returns the world coordinates Bounding Box. + * @param[in] boundingRectangle local bounding + * @param[out] Vector4 World coordinate bounding Box. + */ +void LocalToWorldCoordinatesBoundingBox( const Dali::Rect& boundingRectangle, Dali::Vector4& boundingBox ) +{ + // Convert to world coordinates and store as a Vector4 to be compatible with Property Notifications. + Dali::Vector2 stageSize = Dali::Stage::GetCurrent().GetSize(); + + const float originX = boundingRectangle.x - 0.5f * stageSize.width; + const float originY = boundingRectangle.y - 0.5f * stageSize.height; + + boundingBox = Dali::Vector4( originX, + originY, + originX + boundingRectangle.width, + originY + boundingRectangle.height ); +} + + +} // end of namespace + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct Decorator::Impl : public ConnectionTracker +{ + struct CursorImpl + { + CursorImpl() + : x(0.0f), + y(0.0f), + cursorHeight(0.0f), + lineHeight(0.0f), + color(Dali::Color::WHITE) + { + } + + float x; + float y; + float cursorHeight; + float lineHeight; + + Vector4 color; + }; + + struct SelectionHandleImpl + { + SelectionHandleImpl() + : x(0.0f), + y(0.0f), + lineHeight(0.0f), + flipped(false) + { + } + + float x; + float y; + float lineHeight; ///< Not the handle height + bool flipped; + + ImageActor actor; + Actor grabArea; + + Image pressedImage; + Image releasedImage; + }; + + Impl( Dali::Toolkit::Internal::Control& parent, Observer& observer ) + : mTextControlParent(parent), + mObserver(observer), + mActiveCursor(ACTIVE_CURSOR_NONE), + mActiveGrabHandle(false), + mActiveSelection( false ), + mActiveCopyPastePopup( false ), + mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ), + mCursorBlinkDuration( 0.0f ), + mCursorBlinkStatus( true ), + mGrabDisplacementX( 0.0f ), + mGrabDisplacementY( 0.0f ), + mHighlightColor( 0.07f, 0.41f, 0.59f, 1.0f ), // light blue + mBoundingBox( Rect() ) + { + } + + /** + * Relayout of the decorations owned by the decorator. + * @param[in] size The Size of the UI control the decorater is adding it's decorations to. + */ + void Relayout( const Vector2& size, const Vector2& scrollPosition ) + { + // TODO - Remove this if nothing is active + CreateActiveLayer(); + + // Show or hide the cursors + CreateCursors(); + if( mPrimaryCursor ) + { + mPrimaryCursor.SetPosition( mCursor[PRIMARY_CURSOR].x + scrollPosition.x, + mCursor[PRIMARY_CURSOR].y + scrollPosition.y ); + mPrimaryCursor.SetSize( Size( 1.0f, mCursor[PRIMARY_CURSOR].cursorHeight ) ); + } + if( mSecondaryCursor ) + { + mSecondaryCursor.SetPosition( mCursor[SECONDARY_CURSOR].x + scrollPosition.x, + mCursor[SECONDARY_CURSOR].y + scrollPosition.y ); + mSecondaryCursor.SetSize( Size( 1.0f, mCursor[SECONDARY_CURSOR].cursorHeight ) ); + } + + // Show or hide the grab handle + if( mActiveGrabHandle ) + { + SetupTouchEvents(); + + CreateGrabHandle(); + + mGrabHandle.SetPosition( mCursor[PRIMARY_CURSOR].x + scrollPosition.x, + mCursor[PRIMARY_CURSOR].lineHeight + scrollPosition.y ); + } + else if( mGrabHandle ) + { + UnparentAndReset( mGrabHandle ); + } + + // Show or hide the selection handles/highlight + if( mActiveSelection ) + { + SetupTouchEvents(); + + CreateSelectionHandles(); + + SelectionHandleImpl& primary = mSelectionHandle[ PRIMARY_SELECTION_HANDLE ]; + primary.actor.SetPosition( primary.x + scrollPosition.x, + primary.lineHeight + scrollPosition.y ); + + SelectionHandleImpl& secondary = mSelectionHandle[ SECONDARY_SELECTION_HANDLE ]; + secondary.actor.SetPosition( secondary.x + scrollPosition.x, + secondary.lineHeight + scrollPosition.y ); + + CreateHighlight(); + UpdateHighlight(); + } + else + { + UnparentAndReset( mSelectionHandle[ PRIMARY_SELECTION_HANDLE ].actor ); + UnparentAndReset( mSelectionHandle[ SECONDARY_SELECTION_HANDLE ].actor ); + UnparentAndReset( mHighlightMeshActor ); + } + + if ( mActiveCopyPastePopup ) + { + if ( !mCopyPastePopup ) + { + mCopyPastePopup = TextSelectionPopup::New(); +#ifdef DECORATOR_DEBUG + mCopyPastePopup.SetName("mCopyPastePopup"); +#endif + mCopyPastePopup.SetAnchorPoint( AnchorPoint::CENTER ); + mCopyPastePopup.OnRelayoutSignal().Connect( this, &Decorator::Impl::PopUpRelayoutComplete ); // Position popup after size negotiation + mActiveLayer.Add ( mCopyPastePopup ); + } + } + else + { + if ( mCopyPastePopup ) + { + UnparentAndReset( mCopyPastePopup ); + } + } + } + + void PopUpRelayoutComplete( Actor actor ) + { + // Size negotiation for CopyPastePopup complete so can get the size and constrain position within bounding box. + + mCopyPastePopup.OnRelayoutSignal().Disconnect( this, &Decorator::Impl::PopUpRelayoutComplete ); + + Vector3 popupPosition( mCursor[PRIMARY_CURSOR].x, mCursor[PRIMARY_CURSOR].y -100.0f , 0.0f); //todo 100 to be an offset Property + + Vector3 popupSize = Vector3( mCopyPastePopup.GetRelayoutSize( Dimension::WIDTH ), mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT ), 0.0f ); + + GetConstrainedPopupPosition( popupPosition, popupSize, AnchorPoint::CENTER, mActiveLayer, mBoundingBox ); + + SetUpPopUpPositionNotifications(); + + mCopyPastePopup.SetPosition( popupPosition ); //todo grabhandle(cursor) or selection handle positions to be used + } + + void CreateCursor( ImageActor& cursor ) + { + cursor = CreateSolidColorActor( Color::WHITE ); + cursor.SetParentOrigin( ParentOrigin::TOP_LEFT ); // Need to set the default parent origin as CreateSolidColorActor() sets a different one. + cursor.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + cursor.SetRelayoutEnabled( false ); + } + + // Add or Remove cursor(s) from parent + void CreateCursors() + { + if( mActiveCursor == ACTIVE_CURSOR_NONE ) + { + UnparentAndReset( mPrimaryCursor ); + UnparentAndReset( mSecondaryCursor ); + } + else + { + /* Create Primary and or Secondary Cursor(s) if active and add to parent */ + if ( mActiveCursor == ACTIVE_CURSOR_PRIMARY || + mActiveCursor == ACTIVE_CURSOR_BOTH ) + { + if ( !mPrimaryCursor ) + { + CreateCursor( mPrimaryCursor ); +#ifdef DECORATOR_DEBUG + mPrimaryCursor.SetName( "PrimaryCursorActor" ); +#endif + mActiveLayer.Add( mPrimaryCursor); + } + } + + if ( mActiveCursor == ACTIVE_CURSOR_BOTH ) + { + if ( !mSecondaryCursor ) + { + CreateCursor( mSecondaryCursor ); +#ifdef DECORATOR_DEBUG + mSecondaryCursor.SetName( "SecondaryCursorActor" ); +#endif + mActiveLayer.Add( mSecondaryCursor); + } + } + else + { + UnparentAndReset( mSecondaryCursor ); + } + } + } + + bool OnCursorBlinkTimerTick() + { + // Cursor blinking + if ( mPrimaryCursor ) + { + mPrimaryCursor.SetVisible( mCursorBlinkStatus ); + } + if ( mSecondaryCursor ) + { + mSecondaryCursor.SetVisible( mCursorBlinkStatus ); + } + + mCursorBlinkStatus = !mCursorBlinkStatus; + + return true; + } + + void SetupTouchEvents() + { + if ( !mTapDetector ) + { + mTapDetector = TapGestureDetector::New(); + mTapDetector.DetectedSignal().Connect( this, &Decorator::Impl::OnTap ); + } + + if ( !mPanGestureDetector ) + { + mPanGestureDetector = PanGestureDetector::New(); + mPanGestureDetector.DetectedSignal().Connect( this, &Decorator::Impl::OnPan ); + } + } + + void CreateActiveLayer() + { + if( !mActiveLayer ) + { + Actor parent = mTextControlParent.Self(); + + mActiveLayer = Layer::New(); +#ifdef DECORATOR_DEBUG + mActiveLayer.SetName ( "ActiveLayerActor" ); +#endif + + mActiveLayer.SetParentOrigin( ParentOrigin::CENTER ); + mActiveLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); + mActiveLayer.SetPositionInheritanceMode( USE_PARENT_POSITION ); + + parent.Add( mActiveLayer ); + } + + mActiveLayer.RaiseToTop(); + } + + void CreateGrabHandle() + { + if( !mGrabHandle ) + { + if ( !mGrabHandleImage ) + { + mGrabHandleImage = ResourceImage::New( DEFAULT_GRAB_HANDLE_IMAGE ); + } + + mGrabHandle = ImageActor::New( mGrabHandleImage ); + mGrabHandle.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + mGrabHandle.SetDrawMode( DrawMode::OVERLAY ); + // Area that Grab handle responds to, larger than actual handle so easier to move +#ifdef DECORATOR_DEBUG + mGrabHandle.SetName( "GrabHandleActor" ); + if ( Dali::Internal::gLogFilter->IsEnabledFor( Debug::Verbose ) ) + { + mGrabArea = Toolkit::CreateSolidColorActor( Vector4(0.0f, 0.0f, 0.0f, 0.0f), true, Color::RED, 1 ); + mGrabArea.SetName( "GrabArea" ); + } + else + { + mGrabArea = Actor::New(); + mGrabArea.SetRelayoutEnabled( true ); + mGrabArea.SetName( "GrabArea" ); + } +#else + mGrabArea = Actor::New(); + mGrabArea.SetRelayoutEnabled( true ); +#endif + + mGrabArea.SetParentOrigin( ParentOrigin::TOP_CENTER ); + mGrabArea.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + mGrabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); + mGrabArea.SetSizeModeFactor( DEFAULT_GRAB_HANDLE_RELATIVE_SIZE ); + mGrabHandle.Add( mGrabArea ); + + mTapDetector.Attach( mGrabArea ); + mPanGestureDetector.Attach( mGrabArea ); + + mActiveLayer.Add( mGrabHandle ); + } + } + + void CreateSelectionHandles() + { + SelectionHandleImpl& primary = mSelectionHandle[ PRIMARY_SELECTION_HANDLE ]; + if ( !primary.actor ) + { + if ( !primary.releasedImage ) + { + primary.releasedImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE ); + } + + primary.actor = ImageActor::New( primary.releasedImage ); +#ifdef DECORATOR_DEBUG + primary.actor.SetName("SelectionHandleOne"); +#endif + primary.actor.SetAnchorPoint( AnchorPoint::TOP_RIGHT ); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text. + primary.actor.SetDrawMode( DrawMode::OVERLAY ); // ensure grab handle above text + primary.flipped = false; + + primary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move + primary.grabArea.SetRelayoutEnabled( true ); +#ifdef DECORATOR_DEBUG + primary.grabArea.SetName("SelectionHandleOneGrabArea"); +#endif + primary.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); + primary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); + primary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); + + mTapDetector.Attach( primary.grabArea ); + mPanGestureDetector.Attach( primary.grabArea ); + primary.grabArea.TouchedSignal().Connect( this, &Decorator::Impl::OnHandleOneTouched ); + + primary.actor.Add( primary.grabArea ); + mActiveLayer.Add( primary.actor ); + } + + SelectionHandleImpl& secondary = mSelectionHandle[ SECONDARY_SELECTION_HANDLE ]; + if ( !secondary.actor ) + { + if ( !secondary.releasedImage ) + { + secondary.releasedImage = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO ); + } + + secondary.actor = ImageActor::New( secondary.releasedImage ); +#ifdef DECORATOR_DEBUG + secondary.actor.SetName("SelectionHandleTwo"); +#endif + secondary.actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); // Change to BOTTOM_LEFT if Look'n'Feel requires handle above text. + secondary.actor.SetDrawMode( DrawMode::OVERLAY ); // ensure grab handle above text + secondary.flipped = false; + + secondary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move + secondary.grabArea.SetRelayoutEnabled( true ); +#ifdef DECORATOR_DEBUG + secondary.grabArea.SetName("SelectionHandleTwoGrabArea"); +#endif + secondary.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); + secondary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE ); + secondary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); + + mTapDetector.Attach( secondary.grabArea ); + mPanGestureDetector.Attach( secondary.grabArea ); + secondary.grabArea.TouchedSignal().Connect( this, &Decorator::Impl::OnHandleTwoTouched ); + + secondary.actor.Add( secondary.grabArea ); + mActiveLayer.Add( secondary.actor ); + } + + //SetUpHandlePropertyNotifications(); TODO + } + + void CreateHighlight() + { + if ( !mHighlightMeshActor ) + { + mHighlightMaterial = Material::New( "HighlightMaterial" ); + mHighlightMaterial.SetDiffuseColor( mHighlightColor ); + + mHighlightMeshData.SetMaterial( mHighlightMaterial ); + mHighlightMeshData.SetHasNormals( true ); + + mHighlightMesh = Mesh::New( mHighlightMeshData ); + + mHighlightMeshActor = MeshActor::New( mHighlightMesh ); +#ifdef DECORATOR_DEBUG + mHighlightMeshActor.SetName( "HighlightMeshActor" ); +#endif + mHighlightMeshActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mHighlightMeshActor.SetPosition( 0.0f, 0.0f, DISPLAYED_HIGHLIGHT_Z_OFFSET ); + + Actor parent = mTextControlParent.Self(); + parent.Add( mHighlightMeshActor ); + } + } + + void UpdateHighlight() + { + // Construct a Mesh with a texture to be used as the highlight 'box' for selected text + // + // Example scenarios where mesh is made from 3, 1, 2, 2 ,3 or 3 quads. + // + // [ TOP ] [ TOP ] [TOP ] [ TOP ] [ TOP ] [ TOP ] + // [ MIDDLE ] [BOTTOM] [BOTTOM] [ MIDDLE ] [ MIDDLE ] + // [ BOTTOM] [ MIDDLE ] [ MIDDLE ] + // [BOTTOM] [ MIDDLE ] + // [BOTTOM] + // + // Each quad is created as 2 triangles. + // Middle is just 1 quad regardless of its size. + // + // (0,0) (0,0) + // 0* *2 0* *2 + // TOP TOP + // 3* *1 3* *1 + // 4* *1 4* *6 + // MIDDLE BOTTOM + // 6* *5 7* *5 + // 6* *8 + // BOTTOM + // 9* *7 + // + + if ( mHighlightMesh && mHighlightMaterial && !mHighlightQuadList.empty() ) + { + MeshData::VertexContainer vertices; + Dali::MeshData::FaceIndices faceIndices; + + std::vector::iterator iter = mHighlightQuadList.begin(); + std::vector::iterator endIter = mHighlightQuadList.end(); + + // vertex position defaults to (0 0 0) + MeshData::Vertex vertex; + // set normal for all vertices as (0 0 1) pointing outward from TextInput Actor. + vertex.nZ = 1.0f; + + for(std::size_t v = 0; iter != endIter; ++iter,v+=4 ) + { + // Add each quad geometry (a sub-selection) to the mesh data. + + // 0-----1 + // |\ | + // | \ A | + // | \ | + // | B \ | + // | \| + // 2-----3 + + QuadCoordinates& quad = *iter; + // top-left (v+0) + vertex.x = quad.min.x; + vertex.y = quad.min.y; + vertices.push_back( vertex ); + + // top-right (v+1) + vertex.x = quad.max.x; + vertex.y = quad.min.y; + vertices.push_back( vertex ); + + // bottom-left (v+2) + vertex.x = quad.min.x; + vertex.y = quad.max.y; + vertices.push_back( vertex ); + + // bottom-right (v+3) + vertex.x = quad.max.x; + vertex.y = quad.max.y; + vertices.push_back( vertex ); + + // triangle A (3, 1, 0) + faceIndices.push_back( v + 3 ); + faceIndices.push_back( v + 1 ); + faceIndices.push_back( v ); + + // triangle B (0, 2, 3) + faceIndices.push_back( v ); + faceIndices.push_back( v + 2 ); + faceIndices.push_back( v + 3 ); + + mHighlightMeshData.SetFaceIndices( faceIndices ); + } + + BoneContainer bones(0); // passed empty as bones not required + mHighlightMeshData.SetData( vertices, faceIndices, bones, mHighlightMaterial ); + mHighlightMesh.UpdateMeshData( mHighlightMeshData ); + } + } + + void OnTap( Actor actor, const TapGesture& tap ) + { + if( actor == mGrabHandle ) + { + // TODO + } + } + + void OnPan( Actor actor, const PanGesture& gesture ) + { + if( actor == mGrabArea ) + { + if( Gesture::Started == gesture.state ) + { + mGrabDisplacementX = mGrabDisplacementY = 0; + } + + mGrabDisplacementX += gesture.displacement.x; + mGrabDisplacementY += gesture.displacement.y; + + float x = mCursor[PRIMARY_CURSOR].x + mGrabDisplacementX; + float y = mCursor[PRIMARY_CURSOR].y + mCursor[PRIMARY_CURSOR].lineHeight*0.5f + mGrabDisplacementY; + + if( Gesture::Started == gesture.state || + Gesture::Continuing == gesture.state ) + { + mObserver.GrabHandleEvent( GRAB_HANDLE_PRESSED, x, y ); + } + else if( Gesture::Finished == gesture.state || + Gesture::Cancelled == gesture.state ) + { + mObserver.GrabHandleEvent( GRAB_HANDLE_RELEASED, x, y ); + } + } + } + + bool OnHandleOneTouched( Actor actor, const TouchEvent& touch ) + { + // TODO + return false; + } + + bool OnHandleTwoTouched( Actor actor, const TouchEvent& touch ) + { + // TODO + return false; + } + + // Popup + + float AlternatePopUpPositionRelativeToCursor() + { + float alternativePosition=0.0f;; + + if ( mPrimaryCursor ) // Secondary cursor not used for paste + { + Cursor cursor = PRIMARY_CURSOR; + alternativePosition = mCursor[cursor].y; + } + + const float popupHeight = 120.0f; // todo Set as a MaxSize Property in Control or retrieve from CopyPastePopup class. + + if ( mActiveGrabHandle ) + { + // If grab handle enabled then position pop-up below the grab handle. + const Vector2 grabHandleSize( 59.0f, 56.0f ); // todo + const float BOTTOM_HANDLE_BOTTOM_OFFSET = 1.5; //todo Should be a property + alternativePosition += grabHandleSize.height + popupHeight + BOTTOM_HANDLE_BOTTOM_OFFSET ; + } + else + { + alternativePosition += popupHeight; + } + + return alternativePosition; + } + + void PopUpLeavesVerticalBoundary( PropertyNotification& source ) + { + float alternativeYPosition=0.0f; + // todo + // if( mHighlightMeshActor ) // Text Selection mode + // { + // alternativePosition = AlternatePopUpPositionRelativeToSelectionHandles(); + // } + // else // Not in Text Selection mode + // { + // if can't be positioned above, then position below row. + alternativeYPosition = AlternatePopUpPositionRelativeToCursor(); + // } + mCopyPastePopup.SetY( alternativeYPosition ); + } + + + void SetUpPopUpPositionNotifications( ) + { + // Note Property notifications ignore any set anchor point so conditions must allow for this. Default is Top Left. + + // Exceeding vertical boundary + + Vector4 worldCoordinatesBoundingBox; + LocalToWorldCoordinatesBoundingBox( mBoundingBox, worldCoordinatesBoundingBox ); + + float popupHeight = mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT); + + PropertyNotification verticalExceedNotification = mCopyPastePopup.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y, + OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight/2, + worldCoordinatesBoundingBox.w - popupHeight/2 ) ); + + verticalExceedNotification.NotifySignal().Connect( this, &Decorator::Impl::PopUpLeavesVerticalBoundary ); + } + + void GetConstrainedPopupPosition( Vector3& requiredPopupPosition, Vector3& popupSize, Vector3 anchorPoint, Actor& parent, Rect& boundingBox ) + { + DALI_ASSERT_DEBUG ( "Popup parent not on stage" && parent.OnStage() ) + + // Parent must already by added to Stage for these Get calls to work + Vector3 parentAnchorPoint = parent.GetCurrentAnchorPoint(); + Vector3 parentWorldPositionLeftAnchor = parent.GetCurrentWorldPosition() - parent.GetCurrentSize()*parentAnchorPoint; + 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 ) + { + xOffSetToKeepWithinBounds = boundingRectangleWorld.x - ( popupWorldPosition.x - popupDistanceFromAnchorPoint.x ); + } + else if ( popupWorldPosition.x + popupDistanceFromAnchorPoint.x > boundingRectangleWorld.z ) + { + xOffSetToKeepWithinBounds = boundingRectangleWorld.z - ( popupWorldPosition.x + popupDistanceFromAnchorPoint.x ); + } + + // Ensure initial display of Popup is in alternative position if can not fit above. As Property notification will be a frame behind. + if ( popupWorldPosition.y - popupDistanceFromAnchorPoint.y < boundingRectangleWorld.y ) + { + requiredPopupPosition.y = AlternatePopUpPositionRelativeToCursor(); + } + + requiredPopupPosition.x = requiredPopupPosition.x + xOffSetToKeepWithinBounds; + } + + Internal::Control& mTextControlParent; + Observer& mObserver; + + Layer mActiveLayer; // Layer for active handles and alike that ensures they are above all else. + + unsigned int mActiveCursor; + bool mActiveGrabHandle; + bool mActiveSelection; + bool mActiveCopyPastePopup; + + CursorImpl mCursor[CURSOR_COUNT]; + + Timer mCursorBlinkTimer; // Timer to signal cursor to blink + unsigned int mCursorBlinkInterval; + float mCursorBlinkDuration; + bool mCursorBlinkStatus; // Flag to switch between blink on and blink off + + ImageActor mPrimaryCursor; + ImageActor mSecondaryCursor; + + ImageActor mGrabHandle; + Actor mGrabArea; + float mGrabDisplacementX; + float mGrabDisplacementY; + + SelectionHandleImpl mSelectionHandle[SELECTION_HANDLE_COUNT]; + + MeshActor mHighlightMeshActor; ///< Mesh Actor to display highlight + Mesh mHighlightMesh; ///< Mesh for highlight + MeshData mHighlightMeshData; ///< Mesh Data for highlight + Material mHighlightMaterial; ///< Material used for highlight + Vector4 mHighlightColor; ///< Color of the highlight + QuadContainer mHighlightQuadList; ///< Sub-selections that combine to create the complete selection highlight + + TextSelectionPopup mCopyPastePopup; + + Image mCursorImage; + Image mGrabHandleImage; + + TapGestureDetector mTapDetector; + PanGestureDetector mPanGestureDetector; + + Rect mBoundingBox; +}; + +DecoratorPtr Decorator::New( Internal::Control& parent, Observer& observer ) +{ + return DecoratorPtr( new Decorator(parent, observer) ); +} + +void Decorator::SetBoundingBox( const Rect& boundingBox ) +{ + mImpl->mBoundingBox = boundingBox; +} + +const Rect& Decorator::GetBoundingBox() const +{ + return mImpl->mBoundingBox; +} + +void Decorator::Relayout( const Vector2& size, const Vector2& scrollPosition ) +{ + mImpl->Relayout( size, scrollPosition ); +} + +/** Cursor **/ + +void Decorator::SetActiveCursor( ActiveCursor activeCursor ) +{ + mImpl->mActiveCursor = activeCursor; +} + +unsigned int Decorator::GetActiveCursor() const +{ + return mImpl->mActiveCursor; +} + +void Decorator::SetPosition( Cursor cursor, float x, float y, float cursorHeight, float lineHeight ) +{ + // Adjust grab handle displacement + mImpl->mGrabDisplacementX -= x - mImpl->mCursor[cursor].x; + mImpl->mGrabDisplacementY -= y - mImpl->mCursor[cursor].y; + + mImpl->mCursor[cursor].x = x; + mImpl->mCursor[cursor].y = y; + mImpl->mCursor[cursor].cursorHeight = cursorHeight; + mImpl->mCursor[cursor].lineHeight = lineHeight; +} + +void Decorator::GetPosition( Cursor cursor, float& x, float& y, float& cursorHeight, float& lineHeight ) const +{ + x = mImpl->mCursor[cursor].x; + y = mImpl->mCursor[cursor].y; + cursorHeight = mImpl->mCursor[cursor].cursorHeight; + lineHeight = mImpl->mCursor[cursor].lineHeight; +} + +void Decorator::SetColor( Cursor cursor, const Dali::Vector4& color ) +{ + mImpl->mCursor[cursor].color = color; +} + +const Dali::Vector4& Decorator::GetColor( Cursor cursor ) const +{ + return mImpl->mCursor[cursor].color; +} + +void Decorator::StartCursorBlink() +{ + if ( !mImpl->mCursorBlinkTimer ) + { + mImpl->mCursorBlinkTimer = Timer::New( mImpl->mCursorBlinkInterval ); + mImpl->mCursorBlinkTimer.TickSignal().Connect( mImpl, &Decorator::Impl::OnCursorBlinkTimerTick ); + } + + if ( !mImpl->mCursorBlinkTimer.IsRunning() ) + { + mImpl->mCursorBlinkTimer.Start(); + } +} + +void Decorator::StopCursorBlink() +{ + if ( mImpl->mCursorBlinkTimer ) + { + mImpl->mCursorBlinkTimer.Stop(); + } +} + +void Decorator::SetCursorBlinkInterval( float seconds ) +{ + mImpl->mCursorBlinkInterval = seconds*MILLISECONDS; // Convert to milliseconds +} + +float Decorator::GetCursorBlinkInterval() const +{ + return mImpl->mCursorBlinkInterval; +} + +void Decorator::SetCursorBlinkDuration( float seconds ) +{ + mImpl->mCursorBlinkDuration = seconds; +} + +float Decorator::GetCursorBlinkDuration() const +{ + return mImpl->mCursorBlinkDuration; +} + +/** GrabHandle **/ + +void Decorator::SetGrabHandleActive( bool active ) +{ + mImpl->mActiveGrabHandle = active; +} + +bool Decorator::IsGrabHandleActive() const +{ + return mImpl->mActiveGrabHandle; +} + +void Decorator::SetGrabHandleImage( Dali::Image image ) +{ + mImpl->mGrabHandleImage = image; +} + +Dali::Image Decorator::GetGrabHandleImage() const +{ + return mImpl->mGrabHandleImage; +} + +/** Selection **/ + +void Decorator::SetSelectionActive( bool active ) +{ + mImpl->mActiveSelection = active; +} + +bool Decorator::IsSelectionActive() const +{ + return mImpl->mActiveSelection; +} + +void Decorator::SetPosition( SelectionHandle handle, float x, float y, float height ) +{ + mImpl->mSelectionHandle[handle].x = x; + mImpl->mSelectionHandle[handle].y = y; + mImpl->mSelectionHandle[handle].lineHeight = height; +} + +void Decorator::GetPosition( SelectionHandle handle, float& x, float& y, float& height ) const +{ + x = mImpl->mSelectionHandle[handle].x; + y = mImpl->mSelectionHandle[handle].y; + height = mImpl->mSelectionHandle[handle].lineHeight; +} + +void Decorator::SetImage( SelectionHandle handle, SelectionHandleState state, Dali::Image image ) +{ + if( SELECTION_HANDLE_PRESSED == state ) + { + mImpl->mSelectionHandle[handle].pressedImage = image; + } + else + { + mImpl->mSelectionHandle[handle].releasedImage = image; + } +} + +Dali::Image Decorator::GetImage( SelectionHandle handle, SelectionHandleState state ) const +{ + if( SELECTION_HANDLE_PRESSED == state ) + { + return mImpl->mSelectionHandle[handle].pressedImage; + } + + return mImpl->mSelectionHandle[handle].releasedImage; +} + +void Decorator::AddHighlight( float x1, float y1, float x2, float y2 ) +{ + mImpl->mHighlightQuadList.push_back( QuadCoordinates(x1, y1, x2, y2) ); +} + +void Decorator::ClearHighlights() +{ + mImpl->mHighlightQuadList.clear(); +} + +void Decorator::SetPopupActive( bool active ) +{ + mImpl->mActiveCopyPastePopup = active; +} + +bool Decorator::IsPopupActive() const +{ + return mImpl->mActiveCopyPastePopup ; +} + +Decorator::~Decorator() +{ + delete mImpl; +} + +Decorator::Decorator( Dali::Toolkit::Internal::Control& parent, Observer& observer ) +: mImpl( NULL ) +{ + mImpl = new Decorator::Impl( parent, observer ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/decorator/text-decorator.h b/dali-toolkit/internal/text/decorator/text-decorator.h new file mode 100644 index 0000000..939c815 --- /dev/null +++ b/dali-toolkit/internal/text/decorator/text-decorator.h @@ -0,0 +1,408 @@ +#ifndef __DALI_TOOLKIT_TEXT_DECORATOR_H__ +#define __DALI_TOOLKIT_TEXT_DECORATOR_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 +#include +#include +#include + +namespace Dali +{ + +class Image; +class Vector2; +class Vector4; + +namespace Toolkit +{ + +namespace Internal +{ +class Control; +} + +namespace Text +{ + +class Decorator; +typedef IntrusivePtr DecoratorPtr; + +// Used to set the cursor positions etc. +enum Cursor +{ + PRIMARY_CURSOR, ///< The primary cursor for bidirectional text (or the regular cursor for single-direction text) + SECONDARY_CURSOR, ///< The secondary cursor for bidirectional text + CURSOR_COUNT +}; + +// Determines which of the cursors are active (if any). +enum ActiveCursor +{ + ACTIVE_CURSOR_NONE, ///< Neither primary nor secondary cursor are active + ACTIVE_CURSOR_PRIMARY, ///< Primary cursor is active (only) + ACTIVE_CURSOR_BOTH ///< Both primary and secondary cursor are active +}; + +// The state information for grab handle events +enum GrabHandleState +{ + GRAB_HANDLE_TAPPED, + GRAB_HANDLE_PRESSED, + GRAB_HANDLE_RELEASED +}; + +// The set the selection-handle positions etc. +enum SelectionHandle +{ + PRIMARY_SELECTION_HANDLE, + SECONDARY_SELECTION_HANDLE, + SELECTION_HANDLE_COUNT +}; + +enum SelectionHandleState +{ + SELECTION_HANDLE_PRESSED, + SELECTION_HANDLE_RELEASED +}; + +/** + * @brief A Text Decorator is used to display cursors, handles, selection highlights and pop-ups. + * + * The decorator is responsible for clipping decorations which are positioned outside of the parent area. + * + * The Popup decoration will be positioned either above the Grab handle or above the selection handles but if doing so + * would cause the Popup to exceed the Decoration Bounding Box ( see SetBoundingBox API ) the the Popup will be repositioned below the handle(s). + * + * Selection handles will be flipped around to ensure they do not exceed the Decoration Bounding Box. ( Stay visible ). + * + * Decorator components forward input events to a controller class through an observer interface. + * The controller is responsible for selecting which components are active. + */ +class Decorator : public RefObject +{ +public: + + class Observer + { + public: + + /** + * @brief Constructor. + */ + Observer() {}; + + /** + * @brief Virtual destructor. + */ + virtual ~Observer() {}; + + /** + * @brief An input event from the grab handle. + * + * @param[in] state The grab handle state. + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + */ + virtual void GrabHandleEvent( GrabHandleState state, float x, float y ) = 0; + }; + + /** + * @brief Create a new instance of a Decorator. + * + * @param[in] parent Decorations will be added to this parent control. + * @param[in] observer A class which receives input events from Decorator components. + * @return A pointer to a new Decorator. + */ + static DecoratorPtr New( Dali::Toolkit::Internal::Control& parent, Observer& observer ); + + /** + * @brief Set the bounding box which handles, popup and similar decorations will not exceed. + * + * The default value is the width and height of the stage from the top left origin. + * If a title bar for example is on the top of the screen then the y should be the title's height and + * the boundary height the stage height minus the title's height. + * Restrictions - The boundary box should be set up with a fixed z position for the text-input and the default camera. + * + * ------------------------------------------ + * |(x,y) | + * |o---------------------------------------| + * || || + * || Bounding Box || boundary height + * || || + * |----------------------------------------| + * ------------------------------------------ + * boundary width + * + * @param[in] boundingBox Vector( x coordinate, y coordinate, width, height ) + */ + void SetBoundingBox( const Rect& boundingBox ); + + /** + * @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 the bounding box origin, width and height + */ + const Rect& GetBoundingBox() const; + + /** + * @brief The decorator waits until a relayout before creating actors etc. + * + * @param[in] size The size of the parent control after size-negotiation. + * @param[in] scrollPosition The cursor, grab-handle positions etc. should be offset by this. + */ + void Relayout( const Dali::Vector2& size, const Vector2& scrollPosition ); + + /** + * @brief Sets which of the cursors are active. + * + * @note Cursor will only be visible if within the parent area. + * @param[in] activeCursor Which of the cursors should be active (if any). + */ + void SetActiveCursor( ActiveCursor activeCursor ); + + /** + * @brief Query which of the cursors are active. + * + * @return Which of the cursors are active (if any). + */ + unsigned int GetActiveCursor() const; + + /** + * @brief Sets the position of a cursor. + * + * @param[in] cursor The cursor to set. + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + * @param[in] cursorHeight The logical height of the cursor. + * @param[in] lineHeight The logical height of the line. + */ + void SetPosition( Cursor cursor, float x, float y, float cursorHeight, float lineHeight ); + + /** + * @brief Retrieves the position of a cursor. + * + * @param[in] cursor The cursor to get. + * @param[out] x The x position relative to the top-left of the parent control. + * @param[out] y The y position relative to the top-left of the parent control. + * @param[out] cursorHeight The logical height of the cursor. + * @param[out] lineHeight The logical height of the line. + */ + void GetPosition( Cursor cursor, float& x, float& y, float& cursorHeight, float& lineHeight ) const; + + /** + * @brief Sets the color for a cursor. + * + * @param[in] cursor Whether this color is for the primary or secondary cursor. + * @param[in] color The color to use. + */ + void SetColor( Cursor cursor, const Dali::Vector4& color ); + + /** + * @brief Retrieves the color for a cursor. + * + * @param[in] cursor Whether this color is for the primary or secondary cursor. + * @return The cursor color. + */ + const Dali::Vector4& GetColor( Cursor cursor ) const; + + /** + * @brief Start blinking the cursor; see also SetCursorBlinkDuration(). + */ + void StartCursorBlink(); + + /** + * @brief Stop blinking the cursor. + */ + void StopCursorBlink(); + + /** + * @brief Set the interval between cursor blinks. + * + * @param[in] seconds The interval in seconds. + */ + void SetCursorBlinkInterval( float seconds ); + + /** + * @brief Retrieves the blink-interval for a cursor. + * + * @return The cursor blink-interval. + */ + float GetCursorBlinkInterval() const; + + /** + * @brief The cursor will stop blinking after this duration. + * + * @param[in] seconds The duration in seconds. + */ + void SetCursorBlinkDuration( float seconds ); + + /** + * @brief Retrieves the blink-duration for a cursor. + * + * @return The cursor blink-duration. + */ + float GetCursorBlinkDuration() const; + + /** + * @brief Sets whether the grab handle is active. + * + * @note The grab handle follows the cursor position set with SetPosition(Cursor, ...) + * @param[in] active True if the grab handle should be active. + */ + void SetGrabHandleActive( bool active ); + + /** + * @brief Query whether the grab handle is active. + * + * @return True if the grab handle should be active. + */ + bool IsGrabHandleActive() const; + + /** + * @brief Sets the image for the grab handle. + * + * @param[in] image The image to use. + */ + void SetGrabHandleImage( Dali::Image image ); + + /** + * @brief Retrieves the image for the grab handle. + * + * @return The grab handle image. + */ + Dali::Image GetGrabHandleImage() const; + + /** + * @brief Sets whether the selection handles and highlight are active. + * + * @param[in] active True if the selection handles and highlight are active. + */ + void SetSelectionActive( bool active ); + + /** + * @brief Query whether the selection handles and highlight are active. + * + * @return True if the selection handles and highlight are active. + */ + bool IsSelectionActive() const; + + /** + * @brief Sets the position of a selection handle. + * + * @param[in] handle The handle to set. + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + * @param[in] lineHeight The logical line height at this position. + */ + void SetPosition( SelectionHandle handle, float x, float y, float lineHeight ); + + /** + * @brief Retrieves the position of a selection handle. + * + * @param[in] handle The handle to get. + * @param[out] x The x position relative to the top-left of the parent control. + * @param[out] y The y position relative to the top-left of the parent control. + * @param[out] cursorHeight The logical cursor height at this position. + */ + void GetPosition( SelectionHandle handle, float& x, float& y, float& cursorHeight ) const; + + /** + * @brief Sets the image for one of the selection handles. + * + * @param[in] handle The selection handle. + * @param[in] state A different image can be set for the pressed/released states. + * @param[in] image The image to use. + */ + void SetImage( SelectionHandle handle, SelectionHandleState state, Dali::Image image ); + + /** + * @brief Retrieves the image for a selection handle. + * + * @param[in] handle The selection handle. + * @param[in] state A different image can be set for the pressed/released states. + * @return The image. + */ + Dali::Image GetImage( SelectionHandle handle, SelectionHandleState state ) const; + + /** + * @brief Adds a quad to the existing selection highlights. + * + * @param[in] x1 The top-left x position. + * @param[in] y1 The top-left y position. + * @param[in] x2 The bottom-right x position. + * @param[in] y3 The bottom-right y position. + */ + void AddHighlight( float x1, float y1, float x2, float y2 ); + + /** + * @brief Removes all of the previously added highlights. + */ + void ClearHighlights(); + + /** + * @brief Set the Selection Popup to show or hide via the active flaf + * @param[in] active true to show, false to hide + */ + void SetPopupActive( bool active ); + + /** + * @brief Query whether the Selection Popup is active. + * + * @return True if the Selection Popup should be active. + */ + bool IsPopupActive() const; + + +protected: + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~Decorator(); + +private: + + /** + * @brief Private constructor. + * @param[in] parent Decorations will be added to this parent control. + * @param[in] observer A class which receives input events from Decorator components. + */ + Decorator(Dali::Toolkit::Internal::Control& parent, Observer& observer ); + + // Undefined + Decorator( const Decorator& handle ); + + // Undefined + Decorator& operator=( const Decorator& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_DECORATOR_H__ diff --git a/dali-toolkit/internal/text/font-run.h b/dali-toolkit/internal/text/font-run.h new file mode 100644 index 0000000..2a9680a --- /dev/null +++ b/dali-toolkit/internal/text/font-run.h @@ -0,0 +1,49 @@ +#ifndef __DALI_TOOLKIT_TEXT_FONT_RUN_H__ +#define __DALI_TOOLKIT_TEXT_FONT_RUN_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief Run of characters with the same font. + */ +struct FontRun +{ + CharacterRun characterRun; ///< The initial character index and the number of characters of the run. + FontId fontId; ///< Font id of the run. + bool isDefault; ///< Whether the font is a default font not defined by the user. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_FONT_RUN_H__ diff --git a/dali-toolkit/internal/text/layouts/layout-engine.cpp b/dali-toolkit/internal/text/layouts/layout-engine.cpp new file mode 100644 index 0000000..e165103 --- /dev/null +++ b/dali-toolkit/internal/text/layouts/layout-engine.cpp @@ -0,0 +1,620 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace +{ + +const float MAX_FLOAT = std::numeric_limits::max(); +const bool RTL = true; + +} //namespace + +/** + * @brief Stores temporary layout info of the line. + */ +struct LineLayout +{ + LineLayout() + : glyphIndex( 0u ), + characterIndex( 0u ), + numberOfCharacters( 0u ), + numberOfGlyphs( 0u ), + length( 0.f ), + widthAdvanceDiff( 0.f ), + wsLengthEndOfLine( 0.f ), + ascender( 0.f ), + descender( MAX_FLOAT ) + {} + + ~LineLayout() + {} + + void Clear() + { + glyphIndex = 0u; + characterIndex = 0u; + numberOfCharacters = 0u; + numberOfGlyphs = 0u; + length = 0.f; + widthAdvanceDiff = 0.f; + wsLengthEndOfLine = 0.f; + ascender = 0.f; + descender = MAX_FLOAT; + } + + GlyphIndex glyphIndex; ///< Index of the first glyph to be laid-out. + CharacterIndex characterIndex; ///< Index of the first character to be laid-out. + Length numberOfCharacters; ///< The number of characters which fit in one line. + Length numberOfGlyphs; ///< The number of glyph which fit in one line. + float length; ///< The length of the glyphs which fit in one line. + float widthAdvanceDiff; ///< The difference between the xBearing + width and the advance of the last glyph. + float wsLengthEndOfLine; ///< The length of the white spaces at the end of the line. + float ascender; ///< The maximum ascender of all fonts in the line. + float descender; ///< The minimum descender of all fonts in the line. +}; + +struct LayoutEngine::Impl +{ + Impl() + : mLayout( LayoutEngine::SINGLE_LINE_BOX ), + mHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ), + mVerticalAlignment( LayoutEngine::VERTICAL_ALIGN_TOP ) + { + mFontClient = TextAbstraction::FontClient::Get(); + } + + /** + * @brief Updates the line ascender and descender with the metrics of a new font. + * + * @param[in] fontId The id of the new font. + * @param[in,out] lineLayout The line layout. + */ + void UpdateLineHeight( FontId fontId, LineLayout& lineLayout ) + { + Text::FontMetrics fontMetrics; + mFontClient.GetFontMetrics( fontId, fontMetrics ); + + // Sets the maximum ascender. + if( fontMetrics.ascender > lineLayout.ascender ) + { + lineLayout.ascender = fontMetrics.ascender; + } + + // Sets the minimum descender. + if( fontMetrics.descender < lineLayout.descender ) + { + lineLayout.descender = fontMetrics.descender; + } + } + + /** + * @brief Merges a temporary line layout into the line layout. + * + * @param[in,out] lineLayout The line layout. + * @param[in] tmpLineLayout A temporary line layout. + */ + void MergeLineLayout( LineLayout& lineLayout, + const LineLayout& tmpLineLayout ) + { + lineLayout.numberOfCharacters += tmpLineLayout.numberOfCharacters; + lineLayout.numberOfGlyphs += tmpLineLayout.numberOfGlyphs; + lineLayout.length += tmpLineLayout.length; + + if( 0.f < tmpLineLayout.length ) + { + lineLayout.length += lineLayout.wsLengthEndOfLine; + + lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine; + lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff; + } + else + { + lineLayout.wsLengthEndOfLine += tmpLineLayout.wsLengthEndOfLine; + } + + if( tmpLineLayout.ascender > lineLayout.ascender ) + { + lineLayout.ascender = tmpLineLayout.ascender; + } + + if( tmpLineLayout.descender < lineLayout.descender ) + { + lineLayout.descender = tmpLineLayout.descender; + } + } + + /** + * Retrieves the line layout for a given box width. + */ + void GetLineLayoutForBox( const LayoutParameters& parameters, + LineLayout& lineLayout ) + { + // Stores temporary line layout which has not been added to the final line layout. + LineLayout tmpLineLayout; + + const bool isMultiline = mLayout == MULTI_LINE_BOX; + const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u; + + // If the first glyph has a negative bearing its absolute value needs to be added to the line length. + // In the case the line starts with a right to left character the bearing needs to be substracted to the line length. + const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + lineLayout.glyphIndex ); + float initialHorizontalBearing = glyphInfo.xBearing; + + lineLayout.characterIndex = *( parameters.glyphsToCharactersBuffer + lineLayout.glyphIndex ); + const CharacterDirection firstCharacterDirection = ( NULL == parameters.characterDirectionBuffer ) ? false : *( parameters.characterDirectionBuffer + lineLayout.characterIndex ); + + if( RTL == firstCharacterDirection ) + { + initialHorizontalBearing = -initialHorizontalBearing; + + if( 0.f < glyphInfo.xBearing ) + { + tmpLineLayout.length = glyphInfo.xBearing; + initialHorizontalBearing = 0.f; + } + } + else + { + if( 0.f > glyphInfo.xBearing ) + { + tmpLineLayout.length = -glyphInfo.xBearing; + initialHorizontalBearing = 0.f; + } + } + + // Calculate the line height if there is no characters. + FontId lastFontId = glyphInfo.fontId; + UpdateLineHeight( lastFontId, tmpLineLayout ); + + const float boundingBoxWidth = parameters.boundingBox.width - initialHorizontalBearing; + + bool oneWordLaidOut = false; + + for( GlyphIndex glyphIndex = lineLayout.glyphIndex; + glyphIndex < parameters.totalNumberOfGlyphs; + ++glyphIndex ) + { + const bool isLastGlyph = glyphIndex == lastGlyphIndex; + + // Get the glyph info. + const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex ); + + // Get the character indices for the current glyph. The last character index is needed + // because there are glyphs formed by more than one character but their break info is + // given only for the last character. + const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex ); + const CharacterIndex characterFirstIndex = *( parameters.glyphsToCharactersBuffer + glyphIndex ); + const CharacterIndex characterLastIndex = characterFirstIndex + ( ( 1u > charactersPerGlyph ) ? 0u : charactersPerGlyph - 1u ); + + // Get the line break info for the current character. + const LineBreakInfo lineBreakInfo = *( parameters.lineBreakInfoBuffer + characterLastIndex ); + + // Get the word break info for the current character. + const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex ); + + // Increase the number of characters. + tmpLineLayout.numberOfCharacters += charactersPerGlyph; + + // Increase the number of glyphs. + tmpLineLayout.numberOfGlyphs++; + + // Check whether is a white space. + const Character character = *( parameters.textBuffer + characterFirstIndex ); + const bool isWhiteSpace = TextAbstraction::IsWhiteSpace( character ); + + // Increase the accumulated length. + if( isWhiteSpace ) + { + // Add the length to the length of white spaces at the end of the line. + tmpLineLayout.wsLengthEndOfLine += glyphInfo.advance; // The advance is used as the width is always zero for the white spaces. + } + else + { + // Add as well any previous white space length. + tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphInfo.advance; + if( RTL == firstCharacterDirection ) + { + tmpLineLayout.widthAdvanceDiff = -glyphInfo.xBearing; + } + else + { + tmpLineLayout.widthAdvanceDiff = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance; + } + + // Clear the white space length at the end of the line. + tmpLineLayout.wsLengthEndOfLine = 0.f; + } + + // Check if the accumulated length fits in the width of the box. + if( isMultiline && oneWordLaidOut && !isWhiteSpace && + ( lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpLineLayout.widthAdvanceDiff > boundingBoxWidth ) ) + { + // Current word does not fit in the box's width. + return; + } + + if( ( isMultiline || isLastGlyph ) && + ( TextAbstraction::LINE_MUST_BREAK == lineBreakInfo ) ) + { + // Must break the line. Update the line layout and return. + MergeLineLayout( lineLayout, tmpLineLayout ); + + return; + } + + if( isMultiline && + ( TextAbstraction::WORD_BREAK == wordBreakInfo ) ) + { + if( !oneWordLaidOut && !isWhiteSpace ) + { + oneWordLaidOut = true; + } + + // Current glyph is the last one of the current word. + // Add the temporal layout to the current one. + MergeLineLayout( lineLayout, tmpLineLayout ); + + tmpLineLayout.Clear(); + } + + // Check if the font of the current glyph is the same of the previous one. + // If it's different the ascender and descender need to be updated. + if( lastFontId != glyphInfo.fontId ) + { + UpdateLineHeight( glyphInfo.fontId, tmpLineLayout ); + lastFontId = glyphInfo.fontId; + } + } + } + + bool LayoutText( const LayoutParameters& layoutParameters, + Vector& glyphPositions, + Vector& lines, + Size& actualSize ) + { + Vector2* glyphPositionsBuffer = glyphPositions.Begin(); + + float penY = 0.f; + for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; ) + { + // Get the layout for the line. + LineLayout layout; + layout.glyphIndex = index; + GetLineLayoutForBox( layoutParameters, + layout ); + + if( 0u == layout.numberOfGlyphs ) + { + // The width is too small and no characters are laid-out. + return false; + } + + LineRun lineRun; + lineRun.glyphIndex = index; + lineRun.numberOfGlyphs = layout.numberOfGlyphs; + lineRun.characterRun.characterIndex = layout.characterIndex; + lineRun.characterRun.numberOfCharacters = layout.numberOfCharacters; + lineRun.width = layout.length + layout.widthAdvanceDiff; + lineRun.ascender = layout.ascender; + lineRun.descender = layout.descender; + lineRun.extraLength = layout.wsLengthEndOfLine > 0.f ? layout.wsLengthEndOfLine - layout.widthAdvanceDiff : 0.f; + lineRun.direction = false; + + lines.PushBack( lineRun ); + + // Update the actual size. + if( lineRun.width > actualSize.width ) + { + actualSize.width = lineRun.width; + } + + actualSize.height += ( lineRun.ascender + -lineRun.descender ); + + // Traverse the glyphs and set the positions. + + penY += layout.ascender; + + // Check if the x bearing of the first character is negative. + // If it has a negative x bearing, it will exceed the boundaries of the actor, + // so the penX position needs to be moved to the right. + float penX = 0.f; + + const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + index ); + if( 0.f > glyph.xBearing ) + { + penX = -glyph.xBearing; + } + + for( GlyphIndex i = index; i < index + layout.numberOfGlyphs; ++i ) + { + const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + i ); + Vector2& position = *( glyphPositionsBuffer + i ); + + position.x = penX + glyph.xBearing; + position.y = penY - glyph.yBearing; + + penX += glyph.advance; + } + + penY += -layout.descender; + + // Increase the glyph index. + index += layout.numberOfGlyphs; + } + + return true; + } + + void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + Vector& glyphPositions ) + { + // Traverses the paragraphs with right to left characters. + for( LineIndex lineIndex = 0u; lineIndex < layoutParameters.numberOfBidirectionalInfoRuns; ++lineIndex ) + { + const BidirectionalLineInfoRun& bidiLine = *( layoutParameters.lineBidirectionalInfoRunsBuffer + lineIndex ); + + float penX = 0.f; + + const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *bidiLine.visualToLogicalMap; + const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) ); + + penX = -glyph.xBearing; + + Vector2* glyphPositionsBuffer = glyphPositions.Begin(); + + // Traverses the characters of the right to left paragraph. + for( CharacterIndex characterLogicalIndex = 0u; + characterLogicalIndex < bidiLine.characterRun.numberOfCharacters; + ++characterLogicalIndex ) + { + // Convert the character in the logical order into the character in the visual order. + const CharacterIndex characterVisualIndex = bidiLine.characterRun.characterIndex + *( bidiLine.visualToLogicalMap + characterLogicalIndex ); + + // Get the number of glyphs of the character. + const Length numberOfGlyphs = *( layoutParameters.glyphsPerCharacterBuffer + characterVisualIndex ); + + for( GlyphIndex index = 0u; index < numberOfGlyphs; ++index ) + { + // Convert the character in the visual order into the glyph in the visual order. + const GlyphIndex glyphIndex = *( layoutParameters.charactersToGlyphsBuffer + characterVisualIndex ) + index; + + DALI_ASSERT_DEBUG( 0u <= glyphIndex && glyphIndex < layoutParameters.totalNumberOfGlyphs ); + + const GlyphInfo& glyph = *( layoutParameters.glyphsBuffer + glyphIndex ); + Vector2& position = *( glyphPositionsBuffer + glyphIndex ); + + position.x = penX + glyph.xBearing; + penX += glyph.advance; + } + } + } + } + + void Align( const LayoutParameters& layoutParameters, + const Size& layoutSize, + const Vector& lines, + Vector& glyphPositions ) + { + Vector2* glyphPositionsBuffer = glyphPositions.Begin(); + + // Traverse all lines and align the glyphs. + // LayoutParameters contains bidirectional info for those lines with + // right to left text, this info includes the paragraph's direction. + + LineIndex bidiLineIndex = 0u; + for( Vector::ConstIterator it = lines.Begin(), endIt = lines.End(); + it != endIt; + ++it ) + { + const LineRun& line = *it; + + // 1) Get the paragrap's direction. + bool paragraphDirection = false; + + // Check if there is any right to left line. + if( ( NULL != layoutParameters.lineBidirectionalInfoRunsBuffer ) && + ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) ) + { + const BidirectionalLineInfoRun* bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex; + + // Get the right to left line that match with current line. + while( ( line.characterRun.characterIndex > bidiLine->characterRun.characterIndex ) && + ( bidiLineIndex < layoutParameters.numberOfBidirectionalInfoRuns ) ) + { + ++bidiLineIndex; + bidiLine = layoutParameters.lineBidirectionalInfoRunsBuffer + bidiLineIndex; + } + + if( line.characterRun.characterIndex == bidiLine->characterRun.characterIndex ) + { + paragraphDirection = bidiLine->direction; + } + } + + // 2) Calculate the alignment offset accordingly with the align option, + // the box width, line length, and the paragraphs direction. + float alignOffset = CalculateHorizontalAlignment( layoutSize.width, + line.width, + line.extraLength, + paragraphDirection ); + + // 3) Traverse all glyphs and update the 'x' position. + for( GlyphIndex index = line.glyphIndex, + endIndex = line.glyphIndex + line.numberOfGlyphs; + index < endIndex; + ++index ) + { + Vector2& position = *( glyphPositionsBuffer + index ); + + position.x += alignOffset; + } + } + } + + float CalculateHorizontalAlignment( float boxWidth, + float lineLength, + float extraLength, + bool paragraphDirection ) + { + float offset = 0.f; + + HorizontalAlignment alignment = mHorizontalAlignment; + if( paragraphDirection && + ( HORIZONTAL_ALIGN_CENTER != alignment ) ) + { + if( HORIZONTAL_ALIGN_BEGIN == alignment ) + { + alignment = HORIZONTAL_ALIGN_END; + } + else + { + alignment = HORIZONTAL_ALIGN_BEGIN; + } + } + + switch( alignment ) + { + case HORIZONTAL_ALIGN_BEGIN: + { + offset = 0.f; + break; + } + case HORIZONTAL_ALIGN_CENTER: + { + offset = 0.5f * ( boxWidth - lineLength ); + const int intOffset = static_cast( offset ); // try to avoid pixel alignment. + offset = static_cast( intOffset ); + break; + } + case HORIZONTAL_ALIGN_END: + { + offset = boxWidth - lineLength; + break; + } + } + + if( paragraphDirection ) + { + offset -= extraLength; + } + + return offset; + } + + LayoutEngine::Layout mLayout; + LayoutEngine::HorizontalAlignment mHorizontalAlignment; + LayoutEngine::VerticalAlignment mVerticalAlignment; + + TextAbstraction::FontClient mFontClient; +}; + +LayoutEngine::LayoutEngine() +: mImpl( NULL ) +{ + mImpl = new LayoutEngine::Impl(); +} + +LayoutEngine::~LayoutEngine() +{ + delete mImpl; +} + +void LayoutEngine::SetLayout( Layout layout ) +{ + mImpl->mLayout = layout; +} + +unsigned int LayoutEngine::GetLayout() const +{ + return mImpl->mLayout; +} + +void LayoutEngine::SetHorizontalAlignment( HorizontalAlignment alignment ) +{ + mImpl->mHorizontalAlignment = alignment; +} + +LayoutEngine::HorizontalAlignment LayoutEngine::GetHorizontalAlignment() const +{ + return mImpl->mHorizontalAlignment; +} + +void LayoutEngine::SetVerticalAlignment( VerticalAlignment alignment ) +{ + mImpl->mVerticalAlignment = alignment; +} + +LayoutEngine::VerticalAlignment LayoutEngine::GetVerticalAlignment() const +{ + return mImpl->mVerticalAlignment; +} + +bool LayoutEngine::LayoutText( const LayoutParameters& layoutParameters, + Vector& glyphPositions, + Vector& lines, + Size& actualSize ) +{ + return mImpl->LayoutText( layoutParameters, + glyphPositions, + lines, + actualSize ); +} + +void LayoutEngine::ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + Vector& glyphPositions ) +{ + mImpl->ReLayoutRightToLeftLines( layoutParameters, + glyphPositions ); +} + +void LayoutEngine::Align( const LayoutParameters& layoutParameters, + const Size& layoutSize, + const Vector& lines, + Vector& glyphPositions ) +{ + mImpl->Align( layoutParameters, + layoutSize, + lines, + glyphPositions ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/layouts/layout-engine.h b/dali-toolkit/internal/text/layouts/layout-engine.h new file mode 100644 index 0000000..0c17d68 --- /dev/null +++ b/dali-toolkit/internal/text/layouts/layout-engine.h @@ -0,0 +1,178 @@ +#ifndef __DALI_TOOLKIT_TEXT_LAYOUT_ENGINE_H__ +#define __DALI_TOOLKIT_TEXT_LAYOUT_ENGINE_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 INCLUDE +#include +#include + +// INTERNAL INCLUDE +#include + +namespace Dali +{ + +struct Vector2; + +namespace Toolkit +{ + +namespace Text +{ + +struct LayoutParameters; + +/** + * @brief LayoutEngine is responsible for calculating the visual position of glyphs in layout. + */ +class LayoutEngine +{ +public: + + enum Layout + { + SINGLE_LINE_BOX, + MULTI_LINE_BOX + }; + + enum HorizontalAlignment + { + HORIZONTAL_ALIGN_BEGIN, + HORIZONTAL_ALIGN_CENTER, + HORIZONTAL_ALIGN_END + }; + + enum VerticalAlignment + { + VERTICAL_ALIGN_TOP, + VERTICAL_ALIGN_CENTER, + VERTICAL_ALIGN_BOTTOM + }; + + /** + * @brief Create a new instance of a LayoutEngine. + */ + LayoutEngine(); + + /** + * @brief Virtual destructor. + */ + ~LayoutEngine(); + + /** + * @brief Choose the required layout. + * + * @param[in] layout The required layout. + */ + void SetLayout( Layout layout ); + + /** + * @brief Query the required layout. + * + * @return The required layout. + */ + unsigned int GetLayout() const; + + /** + * @brief Choose the required text horizontal alignment. + * + * @param[in] alignment The required alignment. + */ + void SetHorizontalAlignment( HorizontalAlignment alignment ); + + /** + * @brief Query the required text horizontal alignment. + * + * @return The required alignment. + */ + HorizontalAlignment GetHorizontalAlignment() const; + + /** + * @brief Choose the required text vertical alignment. + * + * @param[in] alignment The required alignment. + */ + void SetVerticalAlignment( VerticalAlignment alignment ); + + /** + * @brief Query the required text vertical alignment. + * + * @return The required alignment. + */ + VerticalAlignment GetVerticalAlignment() const; + + /** + * @brief Store the visual position of glyphs in the VisualModel. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[out] glyphPositions The positions of all the glyphs. + * @param[out] lines The laid-out lines. + * @param[out] actualSize The size of the text after it has been laid-out. + * + * @return \e true if the text has been re-laid-out. \e false means the given width is too small to layout even a single character. + */ + bool LayoutText( const LayoutParameters& layoutParameters, + Vector& glyphPositions, + Vector& lines, + Size& actualSize ); + + /** + * @brief Re-lays out those lines with right to left characters. + * + * It doesn't change the phisical position of the glyphs in the model but sets their new position. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in,out] glyphPositions The positions of all the glyphs. + */ + void ReLayoutRightToLeftLines( const LayoutParameters& layoutParameters, + Vector& glyphPositions ); + + /** + * @brief Aligns the laid out lines. + * + * @param[in] layoutParameters The parameters needed to layout the text. + * @param[in] layoutSize The size of the laid out the text. + * @param[in] lines The laid-out lines. + * @param[in,out] glyphPositions The positions of all the glyphs. + */ + void Align( const LayoutParameters& layoutParameters, + const Size& layoutSize, + const Vector& lines, + Vector& glyphPositions ); + +private: + + // Undefined + LayoutEngine( const LayoutEngine& handle ); + + // Undefined + LayoutEngine& operator=( const LayoutEngine& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LAYOUT_ENGINE_H__ diff --git a/dali-toolkit/internal/text/layouts/layout-parameters.h b/dali-toolkit/internal/text/layouts/layout-parameters.h new file mode 100644 index 0000000..8a49a91 --- /dev/null +++ b/dali-toolkit/internal/text/layouts/layout-parameters.h @@ -0,0 +1,100 @@ +#ifndef __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_H__ +#define __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct BidirectionalLineInfoRun; + +/** + * @brief Struct used to pass parameters. + */ +struct LayoutParameters +{ + /** + * Constructor with the needed parameters to layout the text. + * + * @param[in] boundingBox The size of the box containing the text. + * @param[in] textBuffer The text buffer. + * @param[in] lineBreakInfoBuffer The line break info. + * @param[in] wordBreakInfoBuffer The word break info. + * @param[in] totalNumberOfGlyphs The number of glyphs. + * @param[in] glyphsBuffer A vector with glyphs. + * @param[in] glyphsToCharactersBuffer Vector with indices pointing the first character of each glyph. + * @param[in] charactersPerGlyphBuffer Vector with the number of characters that forms each glyph. + */ + LayoutParameters( const Vector2& boundingBox, + const Character* const textBuffer, + const LineBreakInfo* const lineBreakInfoBuffer, + const WordBreakInfo* const wordBreakInfoBuffer, + const CharacterDirection* const characterDirectionBuffer, + Length totalNumberOfGlyphs, + const GlyphInfo* const glyphsBuffer, + const CharacterIndex* const glyphsToCharactersBuffer, + const Length* const charactersPerGlyphBuffer ) + : boundingBox( boundingBox ), + textBuffer( textBuffer ), + lineBreakInfoBuffer( lineBreakInfoBuffer ), + wordBreakInfoBuffer( wordBreakInfoBuffer ), + characterDirectionBuffer( characterDirectionBuffer ), + totalNumberOfGlyphs( totalNumberOfGlyphs ), + glyphsBuffer( glyphsBuffer ), + glyphsToCharactersBuffer( glyphsToCharactersBuffer ), + charactersPerGlyphBuffer( charactersPerGlyphBuffer ), + charactersToGlyphsBuffer( NULL ), + glyphsPerCharacterBuffer( NULL ), + lineBidirectionalInfoRunsBuffer( NULL ), + numberOfBidirectionalInfoRuns( 0u ) + {} + + Vector2 boundingBox; + const Character* const textBuffer; + const LineBreakInfo* const lineBreakInfoBuffer; + const WordBreakInfo* const wordBreakInfoBuffer; + const CharacterDirection* const characterDirectionBuffer; + Length totalNumberOfGlyphs; + const GlyphInfo* const glyphsBuffer; + const CharacterIndex* const glyphsToCharactersBuffer; + const Length* const charactersPerGlyphBuffer; + GlyphIndex* charactersToGlyphsBuffer; ///< The character to glyph conversion table. + Length* glyphsPerCharacterBuffer; ///< The number of glyphs per character. + BidirectionalLineInfoRun* lineBidirectionalInfoRunsBuffer; ///< Bidirectional conversion tables per line. + Length numberOfBidirectionalInfoRuns; ///< The number of lines with bidirectional info. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LAYOUT_PARAMETERS_H__ diff --git a/dali-toolkit/internal/text/line-run.h b/dali-toolkit/internal/text/line-run.h new file mode 100644 index 0000000..a71dc0f --- /dev/null +++ b/dali-toolkit/internal/text/line-run.h @@ -0,0 +1,57 @@ +#ifndef __DALI_TOOLKIT_TEXT_LINE_RUN_H__ +#define __DALI_TOOLKIT_TEXT_LINE_RUN_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief LineRun + */ +struct LineRun +{ + GlyphIndex glyphIndex; ///< The initial glyph index. + Length numberOfGlyphs; ///< The number of glyphs of the run. + CharacterRun characterRun; ///< The initial character and the number of characters. + float width; ///< The line's width. + float ascender; ///< The line's ascender. + float descender; ///< The line's descender. + float extraLength; ///< The length of the white spaces at the end of the line. + CharacterDirection direction; ///< Direction of the first character of the paragraph. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LINE_RUN_H__ diff --git a/dali-toolkit/internal/text/logical-model-impl.cpp b/dali-toolkit/internal/text/logical-model-impl.cpp new file mode 100644 index 0000000..5a43e35 --- /dev/null +++ b/dali-toolkit/internal/text/logical-model-impl.cpp @@ -0,0 +1,657 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +LogicalModelPtr LogicalModel::New() +{ + return LogicalModelPtr( new LogicalModel() ); +} + +void LogicalModel::SetText( const Character* const text, + Length numberOfCharacters ) +{ + if( 0u == numberOfCharacters ) + { + mText.Clear(); + } + else + { + mText.Resize( numberOfCharacters ); + memcpy( mText.Begin(), text, numberOfCharacters * sizeof( Character ) ); + } +} + +Length LogicalModel::GetNumberOfCharacters() const +{ + return mText.Count(); +} + +void LogicalModel::GetText( Character* text, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( text, mText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) ); +} + +Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const +{ + return mText[characterIndex]; +} + +void LogicalModel::ReplaceText( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const Character* const text, + Length numberOfCharactersToInsert ) +{ +} + +void LogicalModel::SetScripts( const ScriptRun* const scripts, + Length numberOfRuns ) +{ + if( 0u == numberOfRuns ) + { + mScriptRuns.Clear(); + } + else + { + mScriptRuns.Resize( numberOfRuns ); + memcpy( mScriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) ); + } +} + +void LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + ScriptRunIndex& firstScriptRun, + Length& numberOfScriptRuns ) const +{ + // Initialize the number of scripts and the index to the first script. + firstScriptRun = 0u; + numberOfScriptRuns = 0; + bool firstScriptFound = false; + + const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters; + + // Traverse the scripts and count those scripts within the range of characters. + for( Vector::ConstIterator it = mScriptRuns.Begin(), + endIt = mScriptRuns.End(); + it != endIt; + ++it ) + { + const ScriptRun& script = *it; + + if( ( script.characterRun.characterIndex + script.characterRun.numberOfCharacters > characterIndex ) && + ( lastCharacterIndex > script.characterRun.characterIndex ) ) + { + firstScriptFound = true; + ++numberOfScriptRuns; + } + else if( lastCharacterIndex <= script.characterRun.characterIndex ) + { + // nothing else to do. + break; + } + + if( !firstScriptFound ) + { + ++firstScriptRun; + } + } +} + +void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + ScriptRunIndex firstScriptRun = 0u; + Length numberOfScriptRuns = 0u; + + GetNumberOfScriptRuns( characterIndex, + numberOfCharacters, + firstScriptRun, + numberOfScriptRuns ); + + memcpy( scriptRuns, mScriptRuns.Begin() + firstScriptRun, numberOfScriptRuns * sizeof( ScriptRun ) ); +} + +Script LogicalModel::GetScript( CharacterIndex characterIndex ) const +{ + // If this operation is too slow, consider a binary search. + + for( Length index = 0u, length = mScriptRuns.Count(); index < length; ++index ) + { + const ScriptRun* const scriptRun = mScriptRuns.Begin() + index; + + if( ( scriptRun->characterRun.characterIndex <= characterIndex ) && + ( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) ) + { + return scriptRun->script; + } + } + + return TextAbstraction::UNKNOWN; +} + +void LogicalModel::ReplaceScripts( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const ScriptRun* const scriptRuns, + Length numberOfCharactersToInsert ) +{ +} + +void LogicalModel::SetFonts( const FontRun* const fonts, + Length numberOfRuns ) +{ + if( 0u == numberOfRuns ) + { + mFontRuns.Clear(); + } + else + { + mFontRuns.Resize( numberOfRuns ); + memcpy( mFontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) ); + } +} + +void LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + FontRunIndex& firstFontRun, + Length& numberOfFontRuns ) const +{ + // Initialize the number of fonts and the index to the first font. + firstFontRun = 0u; + numberOfFontRuns = 0; + bool firstFontFound = false; + + const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters; + + // Traverse the fonts and count those fonts within the range of characters. + for( Vector::ConstIterator it = mFontRuns.Begin(), + endIt = mFontRuns.End(); + it != endIt; + ++it ) + { + const FontRun& font = *it; + + if( ( font.characterRun.characterIndex + font.characterRun.numberOfCharacters > characterIndex ) && + ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) ) + { + firstFontFound = true; + ++numberOfFontRuns; + } + else if( lastCharacterIndex <= font.characterRun.characterIndex ) + { + // nothing else to do. + break; + } + + if( !firstFontFound ) + { + ++firstFontRun; + } + } +} + +void LogicalModel::GetFontRuns( FontRun* fontRuns, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + FontRunIndex firstFontRun = 0u; + Length numberOfFontRuns = 0u; + + GetNumberOfFontRuns( characterIndex, + numberOfCharacters, + firstFontRun, + numberOfFontRuns ); + + memcpy( fontRuns, mFontRuns.Begin() + firstFontRun, numberOfFontRuns * sizeof( FontRun ) ); +} + +FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const +{ + for( Length index = 0u, length = mFontRuns.Count(); index < length; ++index ) + { + const FontRun* const fontRun = mFontRuns.Begin() + index; + + if( ( fontRun->characterRun.characterIndex <= characterIndex ) && + ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) ) + { + return fontRun->fontId; + } + } + + return 0u; +} + +void LogicalModel::ReplaceFonts( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const FontRun* const fontRuns, + Length numberOfCharactersToInsert ) +{ +} + +void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo, + Length length ) +{ + if( 0u == length ) + { + mLineBreakInfo.Clear(); + } + else + { + mLineBreakInfo.Resize( length ); + memcpy( mLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) ); + } +} + +void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo, + CharacterIndex characterIndex, + Length numberOfItems ) const +{ + memcpy( lineBreakInfo, mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) ); +} + +LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const +{ + return *( mLineBreakInfo.Begin() + characterIndex ); +} + +void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex, + Length numberOfItemsToRemove, + const LineBreakInfo* const lineBreakInfo, + Length numberOfItemsToInsert ) +{ +} + +void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo, + Length length ) +{ + if( 0u == length ) + { + mWordBreakInfo.Clear(); + } + else + { + mWordBreakInfo.Resize( length ); + memcpy( mWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) ); + } +} + +void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo, + CharacterIndex characterIndex, + Length numberOfItems ) const +{ + memcpy( wordBreakInfo, mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) ); +} + +WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const +{ + return *( mWordBreakInfo.Begin() + characterIndex ); +} + +void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex, + Length numberOfItemsToRemove, + const WordBreakInfo* const wordBreakInfo, + Length numberOfItemsToInsert ) +{ +} + +void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo, + Length numberOfRuns ) +{ + if( 0u == numberOfRuns ) + { + mBidirectionalParagraphInfo.Clear(); + } + else + { + mBidirectionalParagraphInfo.Resize( numberOfRuns ); + memcpy( mBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) ); + } +} + +void LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + BidirectionalRunIndex& firstBidirectionalRun, + Length& numberOfFontRuns ) const +{ + // Initialize the number of bidi paragraphs and the index to the first paragraph. + firstBidirectionalRun = 0u; + numberOfFontRuns = 0; + bool firstParagraphFound = false; + + // Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters. + for( Vector::ConstIterator it = mBidirectionalParagraphInfo.Begin(), + endIt = mBidirectionalParagraphInfo.End(); + it != endIt; + ++it ) + { + const BidirectionalParagraphInfoRun& bidi = *it; + + if( ( bidi.characterRun.characterIndex + bidi.characterRun.numberOfCharacters > characterIndex ) && + ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) ) + { + firstParagraphFound = true; + ++numberOfFontRuns; + } + + if( !firstParagraphFound ) + { + ++firstBidirectionalRun; + } + } +} + +void LogicalModel::GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + BidirectionalRunIndex firstBidirectionalRun = 0u; + Length numberOfFontRuns = 0u; + + GetNumberOfBidirectionalInfoRuns( characterIndex, + numberOfCharacters, + firstBidirectionalRun, + numberOfFontRuns ); + + memcpy( bidirectionalInfo, mBidirectionalParagraphInfo.Begin() + firstBidirectionalRun, numberOfFontRuns * sizeof( BidirectionalParagraphInfoRun ) ); +} + +void ReplaceBidirectionalInfo( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const BidirectionalParagraphInfoRun* const bidirectionalInfo, + Length numberOfCharactersToInsert ) +{ +} + +void LogicalModel::SetCharacterDirections( const CharacterDirection* const directions, + Length numberOfCharacters ) +{ + if( 0u == numberOfCharacters ) + { + mCharacterDirections.Clear(); + } + else + { + mCharacterDirections.Resize( numberOfCharacters ); + memcpy( mCharacterDirections.Begin(), directions, numberOfCharacters * sizeof( CharacterDirection ) ); + } +} + +void LogicalModel::GetCharacterDirections( CharacterDirection* directions, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + if( 0u == mCharacterDirections.Count() ) + { + // Nothing to retrieve if the model has no right to left characters. + return; + } + + memcpy( directions, mCharacterDirections.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterDirection ) ); +} + +CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const +{ + if( characterIndex >= mCharacterDirections.Count() ) + { + // The model has no right to left characters, so the vector of directions is void. + return false; + } + + return *( mCharacterDirections.Begin() + characterIndex ); +} + +void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo, + Length numberOfRuns ) +{ + if( 0u == numberOfRuns ) + { + mVisualToLogicalMap.Clear(); + mLogicalToVisualMap.Clear(); + mVisualToLogicalCursorMap.Clear(); + } + else + { + const Length numberOfCharacters = mText.Count(); + mVisualToLogicalMap.Resize( numberOfCharacters ); + mLogicalToVisualMap.Resize( numberOfCharacters ); + + const Length numberOfCharactersPlus = numberOfCharacters + 1u; + mVisualToLogicalCursorMap.Resize( numberOfCharactersPlus ); + + CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin(); + CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin(); + + CharacterIndex* modelVisualToLogicalCursorMap = mVisualToLogicalCursorMap.Begin(); + + CharacterIndex lastIndex = 0u; + for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex ) + { + const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex ); + + if( lastIndex < bidiLineInfo.characterRun.characterIndex ) + { + // Fill with the identity. + for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex ) + { + *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex; + } + } + + // Fill the conversion table of the run. + for( CharacterIndex index = 0u; + index < bidiLineInfo.characterRun.numberOfCharacters; + ++index, ++lastIndex ) + { + *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index ); + } + } + + // Complete with the identity if there are some left to right characters after the last right to left. + for( ; lastIndex < numberOfCharacters; ++lastIndex ) + { + *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex; + } + + // Sets the logical to visual conversion map. + for( CharacterIndex index = 0u; index < numberOfCharacters; ++index ) + { + *( modelLogicalToVisualMapBuffer + *( modelVisualToLogicalMapBuffer + index ) ) = index; + } + + // Sets the visual to logical conversion map for cursor positions. + + const Length numberOfBidirectionalParagraphs = mBidirectionalParagraphInfo.Count(); + BidirectionalParagraphInfoRun* bidirectionalParagraphInfoBuffer = mBidirectionalParagraphInfo.Begin(); + BidirectionalParagraphInfoRun* bidirectionalParagraph = bidirectionalParagraphInfoBuffer; + + const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin(); + + Length bidirectionalParagraphIndex = 0u; + bool isRightToLeftParagraph = false; + for( CharacterIndex index = 0u; index < numberOfCharactersPlus; ++index ) + { + if( bidirectionalParagraph && + ( bidirectionalParagraph->characterRun.characterIndex == index ) ) + { + isRightToLeftParagraph = true; + } + + if( 0u == index ) + { + if( isRightToLeftParagraph ) + { + *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters; + } + else // else logical position is zero. + { + *( modelVisualToLogicalCursorMap + index ) = 0u; + } + } + else if( numberOfCharacters == index ) + { + if( isRightToLeftParagraph ) + { + *( modelVisualToLogicalCursorMap + index ) = 0u; + } + else // else logical position is the number of characters. + { + *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters; + } + } + else + { + // Get the character indexed by index - 1 and index + // and calculate the logical position according the directions of + // both characters and the direction of the paragraph. + + const CharacterIndex previousIndex = index - 1u; + const CharacterIndex logicalPosition0 = *( modelVisualToLogicalMapBuffer + previousIndex ); + const CharacterIndex logicalPosition1 = *( modelVisualToLogicalMapBuffer + index ); + + const CharacterDirection direction0 = *( modelCharacterDirections + logicalPosition0 ); + const CharacterDirection direction1 = *( modelCharacterDirections + logicalPosition1 ); + + if( direction0 == direction1 ) + { + // Both glyphs have the same direction. + if( direction0 ) + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition0; + } + else + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition1; + } + } + else + { + if( isRightToLeftParagraph ) + { + if( direction1 ) + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition1 + 1u; + } + else + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition0; + } + } + else + { + if( direction0 ) + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition1; + } + else + { + *( modelVisualToLogicalCursorMap + index ) = logicalPosition0 + 1u; + } + } + } + } + + if( bidirectionalParagraph && + ( bidirectionalParagraph->characterRun.characterIndex + bidirectionalParagraph->characterRun.numberOfCharacters == index ) ) + { + isRightToLeftParagraph = false; + ++bidirectionalParagraphIndex; + if( bidirectionalParagraphIndex < numberOfBidirectionalParagraphs ) + { + bidirectionalParagraph = bidirectionalParagraphInfoBuffer + bidirectionalParagraphIndex; + } + else + { + bidirectionalParagraph = NULL; + } + } + } + } +} + +void LogicalModel::ReplaceVisualToLogicalMap( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const BidirectionalLineInfoRun* const bidirectionalInfo, + Length numberOfCharactersToInsert ) +{ +} + +CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const +{ + if( 0u == mLogicalToVisualMap.Count() ) + { + // If there is no logical to visual info is because the whole text is left to right. + // Return the identity. + return logicalCharacterIndex; + } + + return *( mLogicalToVisualMap.Begin() + logicalCharacterIndex ); +} + +CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const +{ + if( 0u == mVisualToLogicalMap.Count() ) + { + // If there is no visual to logical info is because the whole text is left to right. + // Return the identity. + return visualCharacterIndex; + } + + return *( mVisualToLogicalMap.Begin() + visualCharacterIndex ); +} + +void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( logicalToVisualMap, mLogicalToVisualMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) ); +} + +void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( visualToLogicalMap, mVisualToLogicalMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) ); +} + +LogicalModel::~LogicalModel() +{ +} + +LogicalModel::LogicalModel() +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/logical-model-impl.h b/dali-toolkit/internal/text/logical-model-impl.h new file mode 100644 index 0000000..73d9230 --- /dev/null +++ b/dali-toolkit/internal/text/logical-model-impl.h @@ -0,0 +1,619 @@ +#ifndef __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_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 +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct BidirectionalLineInfoRun; +struct BidirectionalParagraphInfoRun; +struct FontRun; +class LogicalModel; +typedef IntrusivePtr LogicalModelPtr; +struct ScriptRun; + +/** + * @brief A logical text model contains layout independent information. + * + * This includes: + * - A series of UTF-32 characters in logical order + */ +class LogicalModel : public RefObject +{ +public: + + /** + * @brief Create a new instance of a LogicalModel. + * + * @return A pointer to a new LogicalModel. + */ + static LogicalModelPtr New(); + + // Text interface. + + /** + * @brief Replaces any text previously set. + * + * @note If the number of characters is zero the text buffer is cleared. + * + * @param[in] text An array of UTF-32 characters. + * @param[in] numberOfCharacters The length of the array. + */ + void SetText( const Character* const text, + Length numberOfCharacters ); + + /** + * @brief Retrieves the number of characters of the text. + * + * @return The number of characters. + */ + Length GetNumberOfCharacters() const; + + /** + * @brief Retrieves characters from the text in the given buffer. + * + * @pre The size of the @p text buffer needs to be big enough to copy the @p numberOfCharacters. + * @param[out] text Pointer to a buffer where the text is copied. + * @param[in] characterIndex The index to the first character to copy. + * @param[in] numberOfCharacters The number of characters to be copied. + */ + void GetText( Character* text, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves a character. + * + * @param[in] characterIndex Index to a character. + * + * @return A character. + */ + Character GetCharacter( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces characters from the text. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Where to replace the text. + * @param[in] numberOfCharactersToRemove The number of characters to be removed. + * @param[in] text Pointer to a buffer with the text encoded in utf32. + * @param[in] numberOfCharactersToInsert The number of characters in the buffer. + */ + void ReplaceText( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const Character* const text, + Length numberOfCharactersToInsert ); + + // Language support interface. + + /** + * @brief Sets the script runs. + * + * Replaces any scripts previously set. + * + * A run is a group of consecutive characters. A script run contains the script for a run. + * + * @note If the number of runs is zero the script buffer is cleared. + * + * @param[in] scripts Pointer to a buffer with all the script runs. + * @param[in] numberOfRuns The number of script runs. + */ + void SetScripts( const ScriptRun* const scripts, + Length numberOfRuns ); + + /** + * @brief Retrieves the number of script runs and the index to the first one for the given range of characters. + * + * A run is a group of consecutive characters. A script run contains the script for a run. + * + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + * @param[out] firstScriptRun Index to the script run containing the character index. + * @param[out] numberOfScriptRuns The number of script runs. + */ + void GetNumberOfScriptRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + ScriptRunIndex& firstScriptRun, + Length& numberOfScriptRuns ) const; + + /** + * @brief Retrieves the script runs for the given range of characters. + * + * The @p scriptRuns buffer needs to be big enough to copy the number of script runs. + * Call GetNumberOfScriptRuns() to retrieve the number of script runs. + * + * @param[out] scriptRuns Pointer to a buffer where the script runs are copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetScriptRuns( ScriptRun* scriptRuns, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the script for the given character index. + * + * @param[in] characterIndex Index to the character. + * + * @return The character's script. + */ + Script GetScript( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces script runs for the given range of characters. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Index of the first character where to replace the scripts. + * @param[in] numberOfCharactersToRemove The number of characters to be the script removed. + * @param[in] scriptRuns Pointer to a buffer with the script runs. + * @param[in] numberOfCharactersToInsert The number of characters to be the script inserted. + */ + void ReplaceScripts( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const ScriptRun* const scriptRuns, + Length numberOfCharactersToInsert ); + + /** + * @brief Sets the font runs. + * + * Replaces any fonts previously set. + * + * A run is a group of consecutive characters. A font run contains the font id for a run. + * + * @note If the number of runs is zero the font buffer is cleared. + * + * @param[in] fonts Pointer to a buffer with all the font runs. + * @param[in] numberOfRuns The number of font runs. + */ + void SetFonts( const FontRun* const fonts, + Length numberOfRuns ); + + /** + * @brief Retrieves the number of font runs and the index of the first one for the given range of characters. + * + * A run is a group of consecutive characters. A font run contains the font id for a run. + * + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + * @param[out] firstFontRun Index to the font run containing the character index. + * @param[out] numberOfFontRuns The number of font runs. + */ + void GetNumberOfFontRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + FontRunIndex& firstFontRun, + Length& numberOfFontRuns ) const; + + /** + * @brief Retrieves the font runs for the given range of characters. + * + * The @p fontRuns buffer needs to be big enough to copy the number of font runs. + * Call GetNumberOfFontRuns() to retrieve the number of font runs. + * + * @param[out] fontRuns Pointer to a buffer where the font runs are copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetFontRuns( FontRun* fontRuns, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the font id for the given character index. + * + * @param[in] characterIndex Index to the first character. + * + * @return The font id. + */ + FontId GetFont( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces font runs for the given range of characters. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Index of the first character where to replace the fonts. + * @param[in] numberOfCharactersToRemove The number of characters to be the font removed. + * @param[in] fontRuns Pointer to a buffer with the font runs. + * @param[in] numberOfCharactersToInsert The number of characters to be the font inserted. + */ + void ReplaceFonts( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const FontRun* const fontRuns, + Length numberOfCharactersToInsert ); + + // Break info interface. + + /** + * @brief Sets the line break info. + * + * See GetLineBreakInfo() to get how the line break info is encoded. + * + * Replaces any line break info previously set. + * + * @note If the @length is zero the break info buffer is cleared. + * + * @param[in] lineBreakInfo Pointer to a buffer with the line break info. + * @param[in] length The size of the buffer. + */ + void SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo, + Length length ); + + /** + * @brief Retrieves the line break info in the given buffer. + * + * The size of the @p lineBreakInfo buffer needs to be big enough to copy the @p numberOfItems. + * + * Possible values for LineBreakInfo are: + * + * - 0 is a LINE_MUST_BREAK. Text must be broken into a new line. + * - 1 is a LINE_ALLOW_BREAK. Is possible to break the text into a new line. + * - 2 is a LINE_NO_BREAK. Text can't be broken into a new line. + * + @verbatim + i.e. Hello big\nworld produces: + 2222212220 22220 + @endverbatim + * + * @param[out] lineBreakInfo Pointer to a buffer where the line break info is copied. + * @param[in] characterIndex Index to the first line break info item. + * @param[in] numberOfItems The number of items to be copied. + */ + void GetLineBreakInfo( LineBreakInfo* lineBreakInfo, + CharacterIndex characterIndex, + Length numberOfItems ) const; + + /** + * @brief Retrieves the line break info for the given item index. + * + * @param[in] characterIndex Index to the line break info item. + */ + LineBreakInfo GetLineBreakInfo( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces line break info. + * + * See GetLineBreakInfo() to get how the line break info is encoded. + * + * If the @p numberOfItemsToRemove is zero, this operation is like an insert. + * If the @p numberOfItemsToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Where to replace the line break info. + * @param[in] numberOfItemsToRemove The number of items to be removed. + * @param[in] lineBreakInfo Pointer to a buffer with the line break info. + * @param[in] numberOfItemsToInsert The number of items in the buffer. + */ + void ReplaceLineBreakInfo( CharacterIndex characterIndex, + Length numberOfItemsToRemove, + const LineBreakInfo* const lineBreakInfo, + Length numberOfItemsToInsert ); + + /** + * @brief Sets the word break info. + * + * See GetWordBreakInfo() to get how the word break info is encoded. + * + * Replaces any word break info previously set. + * + * @note If the @length is zero the break info buffer is cleared. + * + * @param[in] wordBreakInfo Pointer to a buffer with the word break info. + * @param[in] length The size of the buffer. + */ + void SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo, + Length length ); + + /** + * @brief Retrieves the word break info in the given buffer. + * + * The size of the @p wordBreakInfo buffer needs to be big enough to copy the @p numberOfItems. + * + * The size of the buffer has to be big enough to store the whole word break info per character. + * Call GetNumberOfCharacters() to get the number of characters. + * + * Possible values for WordBreakInfo are: + * + * - 0 is a WORD_BREAK. Text can be broken into a new word. + * - 1 is a WORD_NO_BREAK. Text can't be broken into a new word. + * + @verbatim + i.e. Hello big\nworld produces: + 1111001100 11110 + @endverbatim + * + * @param[out] wordBreakInfo Pointer to a buffer where the word break info is copied. + * @param[in] characterIndex Index to the first word break info item. + * @param[in] numberOfItems The number of items to be copied. + */ + void GetWordBreakInfo( WordBreakInfo* wordBreakInfo, + CharacterIndex characterIndex, + Length numberOfItems ) const; + + /** + * @brief Retrieves the word break info for the given item index. + * + * @param[in] characterIndex Index to the word break info item. + */ + WordBreakInfo GetWordBreakInfo( CharacterIndex characterIndex ) const; + + /** + * @brief Replaces word break info. + * + * See GetWordBreakInfo() to get how the word break info is encoded. + * + * If the @p numberOfItemsToRemove is zero, this operation is like an insert. + * If the @p numberOfItemsToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Where to replace the word break info. + * @param[in] numberOfItemsToRemove The number of items to be removed. + * @param[in] wordBreakInfo Pointer to a buffer with the word break info. + * @param[in] numberOfItemsToInsert The number of items in the buffer. + */ + void ReplaceWordBreakInfo( CharacterIndex characterIndex, + Length numberOfItemsToRemove, + const WordBreakInfo* const wordBreakInfo, + Length numberOfItemsToInsert ); + + // Bidirectional support interface. + + /** + * @brief Sets the bidirectional info runs. + * + * Replaces any bidirectional info previously set. + * + * Each bidirectional info run stores bidirectional info for a whole 'paragraph' of text which contains right to left scripts. + + * In terms of the bidirectional algorithm, a 'paragraph' is understood as a run of characters between Paragraph Separators or appropriate Newline Functions. + * A 'paragraph' may also be determined by higher-level protocols like a mark-up tag. + * + * @note If the number of runs is zero the bidirectional info buffer is cleared. + * + * @param[in] bidirectionalInfo Pointer to a buffer with all the bidirectional info runs. + * @param[in] numberOfRuns The number of bidirectional info runs. + */ + void SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo, + Length numberOfRuns ); + + /** + * @brief Retrieves the number of bidirectional info runs and the index to the first one for the given range of characters. + * + * It may be zero if there is no right to left scripts. + * + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + * + * @return The number of bidirectional info runs. + */ + void GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, + Length numberOfCharacters, + BidirectionalRunIndex& firstBidirectionalRun, + Length& numberOfFontRuns ) const; + + /** + * @brief Retrieves the bidirectional paragraph info runs for the given range of characters. + * + * The @p bidirectionalInfo buffer needs to be big enough to copy the number of bidirectional + * paragraph info runs. + * Call GetNumberOfBidirectionalInfoRuns() to retrieve the number of bidirectional runs. + * + * @param[out] bidirectionalInfo Pointer to a buffer where the bidirectional info runs are copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Replaces bidirectional info runs for the given range of characters. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Index of the first character where to replace the bidirectional info. + * @param[in] numberOfCharactersToRemove The number of characters to be the bidirectional info removed. + * @param[in] bidirectionalInfo Pointer to a buffer with the bidirectional info runs. + * @param[in] numberOfCharactersToInsert The number of characters to be the bidirectional info inserted. + */ + void ReplaceBidirectionalInfo( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const BidirectionalParagraphInfoRun* const bidirectionalInfo, + Length numberOfCharactersToInsert ); + + /** + * @brief Replaces the direction of the characters. + * + * @note If the number of characters is zero the directions buffer is cleared. + * + * @param[in] directions The directions of the characters. + * @param[in] numberOfCharacters The number of characters. + */ + void SetCharacterDirections( const CharacterDirection* const directions, + Length numberOfCharacters ); + + /** + * @brief Retrieves the direction of the characters. + * + * It sets @e true for right to left characters and @e false for left to right. + * For neutral characters it check's the next and previous character's directions: + * - If they are equals set that direction. If they are not, sets the paragraph's direction. + * - If there is no next, sets the paragraph's direction. + * + * See SetBidirectionalInfo() to get an explanation of the 'paragraph' meaning in the bidirectional algorithm. + * + * @pre the @p directions vector should be initialized to @e false (left to right) as this method is not going + * to update it if there is no right to left characters. + * + * @param[out] directions Whether the characters are right to left or left to right. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetCharacterDirections( CharacterDirection* directions, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the direction of a characters. + * + * See GetCharacterDirections(). + * + * @param[in] characterIndex Index to a character. + * + * @return The character's direction. + */ + CharacterDirection GetCharacterDirection( CharacterIndex characterIndex ) const; + + // Visual <--> Logical conversion tables. + + /** + * @brief Sets the visual to logical and the logical to visual map tables. + * + * Replaces any map tables previously set. + * + * @note If the number of runs is zero the bidirectional info buffer is cleared. + * + * @param[in] bidirectionalInfo Pointer to a buffer with all the bidirectional info runs. + * @param[in] numberOfRuns The number of bidirectional info runs. + */ + void SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo, + Length numberOfRuns ); + + /** + * @brief Replaces the visual to logical and logical to visual map tables for the given range of characters. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] characterIndex Index of the first character where to replace the map tables. + * @param[in] numberOfCharactersToRemove The number of characters to be removed. + * @param[in] bidirectionalInfo Pointer to a buffer with the bidirectional info runs. + * @param[in] numberOfCharactersToInsert The number of characters to be inserted. + */ + void ReplaceVisualToLogicalMap( CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + const BidirectionalLineInfoRun* const bidirectionalInfo, + Length numberOfCharactersToInsert ); + + /** + * @brief Retrieves the visual character index for the given logical character index. + * + * @param[in] logicalCharacterIndex The logical character index. + * + * @return The visual character index. + */ + CharacterIndex GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const; + + /** + * @brief Retrieves the logical character index for the given visual character index. + * + * @param[in] visualCharacterIndex The visual character index. + * + * @return The logical character index. + */ + CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const; + + /** + * @brief Retrieves the whole or part of the logical to visual conversion map. + * + * The size of the buffer needs to be big enough to copy the @p numberOfCharacters. + * + * @param[out] logicalToVisualMap Pointer to a buffer where the conversion map is copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the whole or part of the visual to logical conversion map. + * + * The size of the buffer needs to be big enough to copy the @p numberOfCharacters. + * + * @param[out] visualToLogicalMap Pointer to a buffer where the conversion map is copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + +protected: + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~LogicalModel(); + +private: + + /** + * @brief Private constructor. + */ + LogicalModel(); + + // Undefined + LogicalModel( const LogicalModel& handle ); + + // Undefined + LogicalModel& operator=( const LogicalModel& handle ); + +public: + + Vector mText; + Vector mScriptRuns; + Vector mFontRuns; + Vector mLineBreakInfo; + Vector mWordBreakInfo; + Vector mBidirectionalParagraphInfo; + Vector mCharacterDirections; ///< For each character, whether is right to left. ( @e flase is left to right, @e true right to left ). + Vector mBidirectionalLineInfo; + Vector mLogicalToVisualMap; ///< Bidirectional logical to visual conversion table. + Vector mVisualToLogicalMap; ///< Bidirectional visual to logical conversion table. + Vector mVisualToLogicalCursorMap; ///< Bidirectional visual to logical cursor conversion table. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LOGICAL_MODEL_IMPL_H__ diff --git a/dali-toolkit/internal/text/multi-language-support-impl.cpp b/dali-toolkit/internal/text/multi-language-support-impl.cpp new file mode 100644 index 0000000..6553c51 --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -0,0 +1,575 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace +{ +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_MULTI_LANGUAGE_SUPPORT"); +#endif + +const Dali::Toolkit::Text::Character UTF32_A = 0x0041; +} + +namespace Text +{ + +namespace Internal +{ + +/** + * @brief Retrieves the font Id from the font run for a given character's @p index. + * + * If the character's index exceeds the current font run it increases the iterator to get the next one. + * + * @param[in] index The character's index. + * @param[in,out] fontRunIt Iterator to the current font run. + * @param[in] fontRunEndIt Iterator to one after the last font run. + * + * @return The font id. + */ +FontId GetFontId( Length index, + Vector::ConstIterator& fontRunIt, + const Vector::ConstIterator& fontRunEndIt ) +{ + FontId fontId = 0u; + + if( fontRunIt != fontRunEndIt ) + { + const FontRun& fontRun = *fontRunIt; + + if( ( index >= fontRun.characterRun.characterIndex ) && + ( index < fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) ) + { + fontId = fontRun.fontId; + } + + if( index + 1u == fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) + { + // All the characters of the current run have been traversed. Get the next one for the next iteration. + ++fontRunIt; + } + } + + return fontId; +} + +/** + * @brief Retrieves the script Id from the script run for a given character's @p index. + * + * If the character's index exceeds the current script run it increases the iterator to get the next one. + * + * @param[in] index The character's index. + * @param[in,out] scriptRunIt Iterator to the current font run. + * @param[in] scriptRunEndIt Iterator to one after the last script run. + * + * @return The script. + */ +Script GetScript( Length index, + Vector::ConstIterator& scriptRunIt, + const Vector::ConstIterator& scriptRunEndIt ) +{ + Script script = TextAbstraction::UNKNOWN; + + if( scriptRunIt != scriptRunEndIt ) + { + const ScriptRun& scriptRun = *scriptRunIt; + + if( ( index >= scriptRun.characterRun.characterIndex ) && + ( index < scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ) ) + { + script = scriptRun.script; + } + + if( index + 1u == scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ) + { + // All the characters of the current run have been traversed. Get the next one for the next iteration. + ++scriptRunIt; + } + } + + return script; +} + +/** + * @brief Whether the character is valid for all scripts. i.e. the white space. + * + * @param[in] character The character. + * + * @return @e true if the character is valid for all scripts. + */ +bool IsValidForAllScripts( Character character ) +{ + return ( TextAbstraction::IsWhiteSpace( character ) || + TextAbstraction::IsZeroWidthNonJoiner( character ) || + TextAbstraction::IsZeroWidthJoiner( character ) || + TextAbstraction::IsZeroWidthSpace( character ) || + TextAbstraction::IsLeftToRightMark( character ) || + TextAbstraction::IsRightToLeftMark( character ) || + TextAbstraction::IsThinSpace( character ) ); +} + +bool ValidateFontsPerScript::FindValidFont( FontId fontId ) const +{ + for( Vector::ConstIterator it = mValidFonts.Begin(), + endIt = mValidFonts.End(); + it != endIt; + ++it ) + { + if( fontId == *it ) + { + return true; + } + } + + return false; +} + +MultilanguageSupport::MultilanguageSupport() +: mDefaultFontPerScriptCache(), + mValidFontsPerScriptCache() +{ + // Initializes the default font cache to zero (invalid font). + // Reserves space to cache the default fonts and access them with the script as an index. + mDefaultFontPerScriptCache.Resize( TextAbstraction::UNKNOWN, 0u ); + + // Initializes the valid fonts cache to NULL (no valid fonts). + // Reserves space to cache the valid fonts and access them with the script as an index. + mValidFontsPerScriptCache.Resize( TextAbstraction::UNKNOWN, NULL ); +} + +MultilanguageSupport::~MultilanguageSupport() +{ + // Destroy the valid fonts per script cache. + + for( Vector::Iterator it = mValidFontsPerScriptCache.Begin(), + endIt = mValidFontsPerScriptCache.End(); + it != endIt; + ++it ) + { + delete *it; + } +} + +Text::MultilanguageSupport MultilanguageSupport::Get() +{ + Text::MultilanguageSupport multilanguageSupportHandle; + + SingletonService service( SingletonService::Get() ); + if( service ) + { + // Check whether the singleton is already created + Dali::BaseHandle handle = service.GetSingleton( typeid( Text::MultilanguageSupport ) ); + if( handle ) + { + // If so, downcast the handle + MultilanguageSupport* impl = dynamic_cast< Internal::MultilanguageSupport* >( handle.GetObjectPtr() ); + multilanguageSupportHandle = Text::MultilanguageSupport( impl ); + } + else // create and register the object + { + multilanguageSupportHandle = Text::MultilanguageSupport( new MultilanguageSupport ); + service.Register( typeid( multilanguageSupportHandle ), multilanguageSupportHandle ); + } + } + + return multilanguageSupportHandle; +} + +void MultilanguageSupport::SetScripts( const Vector& text, + const Vector& lineBreakInfo, + Vector& scripts ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + // Stores the current script run. + ScriptRun currentScriptRun; + currentScriptRun.characterRun.characterIndex = 0u; + currentScriptRun.characterRun.numberOfCharacters = 0u; + currentScriptRun.script = TextAbstraction::UNKNOWN; + + // Reserve some space to reduce the number of reallocations. + scripts.Reserve( numberOfCharacters << 2u ); + + // Whether the first valid script need to be set. + bool firstValidScript = true; + + // Whether the first valid script is a right to left script. + bool isParagraphRTL = false; + + // Count the number of characters which are valid for all scripts. i.e. white spaces or '\n'. + Length numberOfAllScriptCharacters = 0u; + + // Pointers to the text and break info buffers. + const Character* textBuffer = text.Begin(); + const LineBreakInfo* breakInfoBuffer = lineBreakInfo.Begin(); + + // Traverse all characters and set the scripts. + for( Length index = 0u; index < numberOfCharacters; ++index ) + { + Character character = *( textBuffer + index ); + LineBreakInfo breakInfo = *( breakInfoBuffer + index ); + + // Some characters (like white spaces) are valid for many scripts. The rules to set a script + // for them are: + // - If they are at the begining of a paragraph they get the script of the first character with + // a defined script. If they are at the end, they get the script of the last one. + // - If they are between two scripts with the same direction, they get the script of the previous + // character with a defined script. If the two scripts have different directions, they get the + // script of the first character of the paragraph with a defined script. + + // Skip those characters valid for many scripts like white spaces or '\n'. + bool endOfText = index == numberOfCharacters; + while( !endOfText && + IsValidForAllScripts( character ) ) + { + // Count all these characters to be added into a script. + ++numberOfAllScriptCharacters; + + if( TextAbstraction::LINE_MUST_BREAK == breakInfo ) + { + // The next character is a new paragraph. + // Know when there is a new paragraph is needed because if there is a white space + // between two scripts with different directions, it is added to the script with + // the same direction than the first script of the paragraph. + firstValidScript = true; + isParagraphRTL = false; + } + + // Get the next character. + ++index; + endOfText = index == numberOfCharacters; + if( !endOfText ) + { + character = *( textBuffer + index ); + breakInfo = *( breakInfoBuffer + index ); + } + } + + if( endOfText ) + { + // Last characters of the text are 'white spaces'. + // There is nothing else to do. Just add the remaining characters to the last script after this bucle. + break; + } + + // Get the script of the character. + Script script = TextAbstraction::GetCharacterScript( character ); + + // Check if it is the first character of a paragraph. + if( firstValidScript && + ( TextAbstraction::UNKNOWN != script ) ) + { + // Sets the direction of the first valid script. + isParagraphRTL = TextAbstraction::IsRightToLeftScript( script ); + firstValidScript = false; + } + + if( script != currentScriptRun.script ) + { + // Current run needs to be stored and a new one initialized. + + if( isParagraphRTL != TextAbstraction::IsRightToLeftScript( script ) ) + { + // Current script has different direction than the first script of the paragraph. + // All the previously skipped characters need to be added to the previous script before it's stored. + currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; + numberOfAllScriptCharacters = 0u; + } + + if( 0u != currentScriptRun.characterRun.numberOfCharacters ) + { + // Store the script run. + scripts.PushBack( currentScriptRun ); + } + + // Initialize the new one. + currentScriptRun.characterRun.characterIndex = currentScriptRun.characterRun.characterIndex + currentScriptRun.characterRun.numberOfCharacters; + currentScriptRun.characterRun.numberOfCharacters = numberOfAllScriptCharacters; // Adds the white spaces which are at the begining of the script. + currentScriptRun.script = script; + numberOfAllScriptCharacters = 0u; + } + else + { + // Adds white spaces between characters. + currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; + numberOfAllScriptCharacters = 0u; + } + + if( TextAbstraction::LINE_MUST_BREAK == breakInfo ) + { + // The next character is a new paragraph. + firstValidScript = true; + isParagraphRTL = false; + } + + // Add one more character to the run. + ++currentScriptRun.characterRun.numberOfCharacters; + } + + // Add remaining characters into the last script. + currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters; + if( 0u != currentScriptRun.characterRun.numberOfCharacters ) + { + if( TextAbstraction::UNKNOWN == currentScriptRun.script ) + { + // There are only white spaces in the last script. Set the latin script. + currentScriptRun.script = TextAbstraction::LATIN; + } + + // Store the last run. + scripts.PushBack( currentScriptRun ); + } +} + +void MultilanguageSupport::ReplaceScripts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +void MultilanguageSupport::ValidateFonts( const Vector& text, + const Vector& scripts, + Vector& fonts ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + // Copy the fonts set by application developers. + const Length numberOfFontRuns = fonts.Count(); + const Vector definedFonts = fonts; + fonts.Clear(); + + // Traverse the characters and validate/set the fonts. + + // Get the caches. + FontId* defaultFontPerScriptCacheBuffer = mDefaultFontPerScriptCache.Begin(); + ValidateFontsPerScript** validFontsPerScriptCacheBuffer = mValidFontsPerScriptCache.Begin(); + + // Stores the validated font runs. + fonts.Reserve( numberOfFontRuns ); + + // Initializes a validated font run. + FontRun currentFontRun; + currentFontRun.characterRun.characterIndex = 0u; + currentFontRun.characterRun.numberOfCharacters = 0u; + currentFontRun.fontId = 0u; + currentFontRun.isDefault = false; + + // Get the font client. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + + // Iterators of the font and script runs. + Vector::ConstIterator fontRunIt = definedFonts.Begin(); + Vector::ConstIterator fontRunEndIt = definedFonts.End(); + Vector::ConstIterator scriptRunIt = scripts.Begin(); + Vector::ConstIterator scriptRunEndIt = scripts.End(); + + for( Length index = 0u; index < numberOfCharacters; ++index ) + { + // Get the character. + const Character character = *( text.Begin() + index ); + + // Get the font for the character. + FontId fontId = GetFontId( index, + fontRunIt, + fontRunEndIt ); + + // Get the script for the character. + Script script = GetScript( index, + scriptRunIt, + scriptRunEndIt ); + + if( TextAbstraction::UNKNOWN == script ) + { + DALI_LOG_WARNING( "MultilanguageSupport::ValidateFonts. Unknown script!" ); + script = TextAbstraction::LATIN; + } + + // Whether the font being validated is a default one not set by the user. + const bool isDefault = ( 0u == fontId ); + + // The default font point size. + PointSize26Dot6 pointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE; + + if( !isDefault ) + { + // Validate if the font set by the user supports the character. + + // Check first in the caches. + + // The user may have set the default font. Check it. Otherwise check in the valid fonts cache. + if( fontId != *( defaultFontPerScriptCacheBuffer + script ) ) + { + // Check in the valid fonts cache. + ValidateFontsPerScript* validateFontsPerScript = *( validFontsPerScriptCacheBuffer + script ); + + if( NULL == validateFontsPerScript ) + { + validateFontsPerScript = new ValidateFontsPerScript(); + } + + if( NULL != validateFontsPerScript ) + { + if( !validateFontsPerScript->FindValidFont( fontId ) ) + { + // Use the font client to validate the font. + GlyphIndex glyphIndex = fontClient.GetGlyphIndex( fontId, character ); + + // Emojis are present in many monochrome fonts; prefer color by default. + if( TextAbstraction::EMOJI == script && + 0u != glyphIndex ) + { + BufferImage bitmap = fontClient.CreateBitmap( fontId, glyphIndex ); + if( bitmap && + Pixel::BGRA8888 != bitmap.GetPixelFormat() ) + { + glyphIndex = 0; + } + } + + if( 0u == glyphIndex ) + { + // Get the point size of the current font. It will be used to get a default font id. + pointSize = fontClient.GetPointSize( fontId ); + + // The font is not valid. Set to zero and a default one will be set. + fontId = 0u; + } + else + { + // Add the font to the valid font cache. + validateFontsPerScript->mValidFonts.PushBack( fontId ); + } + } + } + } + } // !isDefault + + // The font has not been validated. Find a default one. + if( 0u == fontId ) + { + // The character has no font assigned. Get a default one from the cache + fontId = *( defaultFontPerScriptCacheBuffer + script ); + + // If the cache has not a default font, get one from the font client. + if( 0u == fontId ) + { + // Emojis are present in many monochrome fonts; prefer color by default. + bool preferColor = ( TextAbstraction::EMOJI == script ); + + // Find a default font. + fontId = fontClient.FindDefaultFont( character, pointSize, preferColor ); + + // If the system does not support a suitable font, fallback to Latin + if( 0u == fontId ) + { + fontId = *( defaultFontPerScriptCacheBuffer + TextAbstraction::LATIN ); + } + if( 0u == fontId ) + { + fontId = fontClient.FindDefaultFont( UTF32_A, pointSize ); + } + +#ifdef DEBUG_ENABLED + Dali::TextAbstraction::FontDescription description; + fontClient.GetDescription( fontId, description ); + DALI_LOG_INFO( gLogFilter, Debug::Concise, "Script: %s; Selected font: %s\n", Dali::TextAbstraction::ScriptName[script], description.path.c_str() ); +#endif + // Cache the font. + *( defaultFontPerScriptCacheBuffer + script ) = fontId; + } + } + + // The font is now validated. + + if( ( fontId != currentFontRun.fontId ) || + ( isDefault != currentFontRun.isDefault ) ) + { + // Current run needs to be stored and a new one initialized. + + if( 0u != currentFontRun.characterRun.numberOfCharacters ) + { + // Store the font run. + fonts.PushBack( currentFontRun ); + } + + // Initialize the new one. + currentFontRun.characterRun.characterIndex = currentFontRun.characterRun.characterIndex + currentFontRun.characterRun.numberOfCharacters; + currentFontRun.characterRun.numberOfCharacters = 0u; + currentFontRun.fontId = fontId; + currentFontRun.isDefault = isDefault; + } + + // Add one more character to the run. + ++currentFontRun.characterRun.numberOfCharacters; + } + + if( 0u != currentFontRun.characterRun.numberOfCharacters ) + { + // Store the last run. + fonts.PushBack( currentFontRun ); + } +} + +void MultilanguageSupport::ValidateFonts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +} // namespace Internal + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/multi-language-support-impl.h b/dali-toolkit/internal/text/multi-language-support-impl.h new file mode 100644 index 0000000..0f7e177 --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-support-impl.h @@ -0,0 +1,149 @@ +#ifndef __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal +{ + +/** + * @brief Stores valid font ids per script. + */ +struct ValidateFontsPerScript +{ + /** + * Default constructor. + */ + ValidateFontsPerScript() + : mValidFonts() + {} + + /** + * Default destructor. + */ + ~ValidateFontsPerScript() + {} + + /** + * @brief Whether the given @p fontId is in the vector of valid fonts. + * + * @param[in] fontId The font id. + * + * @return @e true if the font is in the vector of valid fonts. + */ + bool FindValidFont( FontId fontId ) const; + + Vector mValidFonts; +}; + +/** + * @brief Multi-language support implementation. @see Text::MultilanguageSupport. + */ +class MultilanguageSupport : public BaseObject +{ +public: + + /** + * Constructor + */ + MultilanguageSupport(); + + /** + * Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~MultilanguageSupport(); + + /** + * @copydoc Dali::MultilanguageSupport::Get() + */ + static Text::MultilanguageSupport Get(); + + /** + * @copydoc Dali::MultilanguageSupport::SetScripts() + */ + void SetScripts( const Vector& text, + const Vector& lineBreakInfo, + Vector& scripts ); + + /** + * @copydoc Dali::MultilanguageSupport::ReplaceScripts() + */ + void ReplaceScripts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + + /** + * @copydoc Dali::MultilanguageSupport::ValidateFonts( const Vector& text, const Vector& scripts, Vector& fonts ) + */ + void ValidateFonts( const Vector& text, + const Vector& scripts, + Vector& fonts ); + + /** + * @copydoc Dali::MultilanguageSupport::ValidateFonts( LogicalModel& model, CharacterIndex characterIndex, Length numberOfCharactersToRemove, Length numberOfCharactersToInsert ) + */ + void ValidateFonts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); +private: + Vector mDefaultFontPerScriptCache; ///< Caches the default font for a script. + Vector mValidFontsPerScriptCache; ///< Caches valid fonts for a script. +}; + +} // namespace Internal + +inline static Internal::MultilanguageSupport& GetImplementation( MultilanguageSupport& multilanguageSupport ) +{ + DALI_ASSERT_ALWAYS( multilanguageSupport && "multi-language handle is empty" ); + BaseObject& handle = multilanguageSupport.GetBaseObject(); + return static_cast( handle ); +} + +inline static const Internal::MultilanguageSupport& GetImplementation( const MultilanguageSupport& multilanguageSupport ) +{ + DALI_ASSERT_ALWAYS( multilanguageSupport && "multi-language handle is empty" ); + const BaseObject& handle = multilanguageSupport.GetBaseObject(); + return static_cast( handle ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_IMPL_H__ diff --git a/dali-toolkit/internal/text/multi-language-support.cpp b/dali-toolkit/internal/text/multi-language-support.cpp new file mode 100644 index 0000000..4416dba --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-support.cpp @@ -0,0 +1,95 @@ +/* + * 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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +MultilanguageSupport::MultilanguageSupport() +{ +} + +MultilanguageSupport::~MultilanguageSupport() +{ +} + +MultilanguageSupport::MultilanguageSupport( Internal::MultilanguageSupport* implementation ) +: BaseHandle( implementation ) +{ +} + +MultilanguageSupport MultilanguageSupport::Get() +{ + return Internal::MultilanguageSupport::Get(); +} + +void MultilanguageSupport::SetScripts( const Vector& text, + const Vector& lineBreakInfo, + Vector& scripts ) +{ + GetImplementation( *this ).SetScripts( text, + lineBreakInfo, + scripts ); +} + +void MultilanguageSupport::ReplaceScripts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ + GetImplementation( *this ).ReplaceScripts( model, + characterIndex, + numberOfCharactersToRemove, + numberOfCharactersToInsert ); +} + +void MultilanguageSupport::ValidateFonts( const Vector& text, + const Vector& scripts, + Vector& fonts ) +{ + GetImplementation( *this ).ValidateFonts( text, + scripts, + fonts ); +} + +void MultilanguageSupport::ValidateFonts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ + GetImplementation( *this ).ValidateFonts( model, + characterIndex, + numberOfCharactersToRemove, + numberOfCharactersToInsert ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/multi-language-support.h b/dali-toolkit/internal/text/multi-language-support.h new file mode 100644 index 0000000..b70f672 --- /dev/null +++ b/dali-toolkit/internal/text/multi-language-support.h @@ -0,0 +1,169 @@ +#ifndef __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_H__ +#define __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_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 +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal DALI_INTERNAL +{ + +class MultilanguageSupport; + +} // Internal + +class LogicalModel; + +/** + * @brief Sets the character's scripts to the model and validates the fonts set by the user or assigns default ones. + */ +class MultilanguageSupport : public BaseHandle +{ +public: + + /** + * @brief Create an uninitialized MultilanguageSupport handle. + */ + MultilanguageSupport(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~MultilanguageSupport(); + + /** + * @brief This constructor is used by MultilanguageSupport::Get(). + * + * @param[in] implementation A pointer to the internal multi-language support object. + */ + explicit DALI_INTERNAL MultilanguageSupport( Internal::MultilanguageSupport* implementation ); + + /** + * @brief Retrieve a handle to the MultilanguageSupport instance. + * + * @return A handle to the MultilanguageSupport. + */ + static MultilanguageSupport Get(); + + /** + * @brief Sets the scripts of the whole text. + * + * Scripts are used to validate and set default fonts and to shape the text in further steps. + * + * Some characters (like white spaces) are valid for many scripts. The rules to set a script + * for them are: + * - If they are at the begining of a paragraph they get the script of the first character with + * a defined script. If they are at the end, they get the script of the last one. + * - If they are between two scripts with the same direction, they get the script of the previous + * character with a defined script. If the two scripts have different directions, they get the + * script of the first character of the paragraph with a defined script. + * + * @param[in] text Vector of UTF-32 characters. + * @param[in] lineBreakInfo Vector with the line break info. + * @param[out] scripts Vector containing the script runs for the whole text. + */ + void SetScripts( const Vector& text, + const Vector& lineBreakInfo, + Vector& scripts ); + + /** + * Replaces the scrips of the given range of characters. + * + * @pre The @p model needs to have a text set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ + void ReplaceScripts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + + /** + * @brief Validates the character's font of the whole text. + * + * It may update fonts set by application developers. + * + * This method ensures all characters are going to be rendered using an appropriate font. Provided a valid font + * exists in the platform. + * + * For those characters with no font set, it sets a default one. + * + * If a font has been set by the application developer, this method checks if the font supports the character. + * If it doesn't, this method replaces it by a default one. + * + * @param[in] text Vector of UTF-32 characters. + * @param[in] scripts Vector containing the script runs for the whole text. + * @param[in,out] fonts Initially contains the fonts set by the application developers. Returns the validated fonts. + */ + void ValidateFonts( const Vector& text, + const Vector& scripts, + Vector& fonts ); + + /** + * Validates the character's font of the given range of characters. + * + * It may update fonts set by the mark-up processor. + * It sets default fonts based on the script to those characters without a font set. + * + * @pre The @p model needs to have a text set. + * @pre The @p model needs to have the scripts set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ + void ValidateFonts( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_MULTI_LANGUAGE_SUPPORT_H__ diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp new file mode 100644 index 0000000..734b82a --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp @@ -0,0 +1,158 @@ + /* + * 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. + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +//#define DISPLAY_ATLAS + +AtlasGlyphManager::AtlasGlyphManager() +: mCount( 0 ) +{ + mAtlasManager = Dali::Toolkit::AtlasManager::New(); +} + +AtlasGlyphManager::~AtlasGlyphManager() +{ +} + +AtlasGlyphManagerPtr AtlasGlyphManager::New() +{ + AtlasGlyphManagerPtr internal = new AtlasGlyphManager(); + return internal; +} + +void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph, + const BufferImage& bitmap, + Dali::Toolkit::AtlasManager::AtlasSlot& slot ) +{ + GlyphRecord record; + record.mFontId = glyph.fontId; + record.mIndex = glyph.index; + + mAtlasManager.Add( bitmap, slot ); + record.mImageId = slot.mImageId; + mGlyphRecords.PushBack( record ); + +#ifdef DISPLAY_ATLAS + { + uint32_t atlasCount = mAtlasManager.GetAtlasCount(); + if ( atlasCount > mCount ) + { + for ( uint32_t i = 0; i < atlasCount; ++i ) + { + ImageActor actor = ImageActor::New( mAtlasManager.GetAtlasContainer( i + 1u ) ); + actor.SetParentOrigin( Vector3( 0.5f, 0.25f + ( static_cast< float >( i ) * 0.25f ), 0.5f ) ); + actor.SetAnchorPoint( AnchorPoint::CENTER ); + actor.SetSize( 256.0f, 256.0f ); + Stage::GetCurrent().Add( actor ); + } + } + mCount = atlasCount; + } +#endif +} + +void AtlasGlyphManager::GenerateMeshData( uint32_t imageId, + const Vector2& position, + MeshData& meshData ) +{ + mAtlasManager.GenerateMeshData( imageId, position, meshData ); +} + +void AtlasGlyphManager::StitchMesh( MeshData& first, + const MeshData& second ) +{ + mAtlasManager.StitchMesh( first, second ); +} + +void AtlasGlyphManager::Cached( Text::FontId fontId, + uint32_t index, + Dali::Toolkit::AtlasManager::AtlasSlot& slot ) +{ + for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i ) + { + if ( fontId == mGlyphRecords[ i ].mFontId && index == mGlyphRecords[ i ].mIndex ) + { + slot.mImageId = mGlyphRecords[ i ].mImageId; + slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId ); + return; + } + } + slot.mImageId = 0; +} + +Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId ) +{ + Toolkit::AtlasManager::AtlasSize size = mAtlasManager.GetAtlasSize( atlasId ); + return Vector2( static_cast< float >( size.mWidth ), static_cast< float >( size.mHeight ) ); +} + +void AtlasGlyphManager::SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight ) +{ + Toolkit::AtlasManager::AtlasSize size; + size.mWidth = width; + size.mHeight = height; + size.mBlockWidth = blockWidth; + size.mBlockHeight = blockHeight; + mAtlasManager.SetNewAtlasSize( size ); +} + +void AtlasGlyphManager::Remove( uint32_t imageId ) +{ + if ( mAtlasManager.Remove( imageId ) ) + { + for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i ) + { + if ( mGlyphRecords[ i ].mImageId == imageId ) + { + mGlyphRecords.Remove( mGlyphRecords.Begin() + i ); + return; + } + } + } +} + +Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId ) +{ + return mAtlasManager.GetPixelFormat( atlasId ); +} + +const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics() +{ + mMetrics.mGlyphCount = mGlyphRecords.Size(); + mAtlasManager.GetMetrics( mMetrics.mAtlasMetrics ); + return mMetrics; +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h new file mode 100644 index 0000000..cbbe732 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h @@ -0,0 +1,153 @@ + +#ifndef __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__ +#define __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_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 +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +class AtlasGlyphManager; + +} // namespace Toolkit + +namespace Toolkit +{ + +namespace Internal +{ + +class AtlasGlyphManager; +typedef IntrusivePtr AtlasGlyphManagerPtr; + +class AtlasGlyphManager : public Dali::BaseObject +{ +public: + + struct GlyphRecord + { + Text::FontId mFontId; + Text::GlyphIndex mIndex; + uint32_t mImageId; + }; + + AtlasGlyphManager(); + + virtual ~AtlasGlyphManager(); + +/** + * Create a new AtlasGlyphManager + */ + static AtlasGlyphManagerPtr New(); + + /** + * @copydoc Toolkit::AtlasGlyphManager::Add + */ + void Add( const Text::GlyphInfo& glyph, + const BufferImage& bitmap, + Dali::Toolkit::AtlasManager::AtlasSlot& slot ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::GenerateMeshData + */ + void GenerateMeshData( uint32_t imageId, + const Vector2& position, + MeshData& meshData ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::StitchMesh + */ + void StitchMesh( MeshData& first, + const MeshData& second ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::Cached + */ + void Cached( Text::FontId fontId, + Text::GlyphIndex index, + Dali::Toolkit::AtlasManager::AtlasSlot& slot ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::GetAtlasSize + */ + Vector2 GetAtlasSize( uint32_t atlasId ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::SetNewAtlasSize + */ + void SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight ); + + /** + * @copydoc Toolkit::AtlasGlyphManager::Remove + */ + void Remove( uint32_t imageId ); + + /** + * @copydoc toolkit::AtlasGlyphManager::GetPixelFormat + */ + Pixel::Format GetPixelFormat( uint32_t atlasId ); + + /** + * @copydoc toolkit::AtlasGlyphManager::GetMetrics + */ + const Toolkit::AtlasGlyphManager::Metrics& GetMetrics(); + +private: + + Dali::Toolkit::AtlasManager mAtlasManager; + Vector< GlyphRecord > mGlyphRecords; + uint32_t mCount; + Toolkit::AtlasGlyphManager::Metrics mMetrics; +}; + +} // namespace Internal + +inline const Internal::AtlasGlyphManager& GetImplementation(const Toolkit::AtlasGlyphManager& manager) +{ + DALI_ASSERT_ALWAYS( manager && "AtlasGlyphManager handle is empty" ); + + const BaseObject& handle = manager.GetBaseObject(); + + return static_cast(handle); +} + +inline Internal::AtlasGlyphManager& GetImplementation(Toolkit::AtlasGlyphManager& manager) +{ + DALI_ASSERT_ALWAYS( manager && "AtlasGlyphManager handle is empty" ); + + BaseObject& handle = manager.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Toolkit + +} // namespace Dali + + + #endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__ \ No newline at end of file diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp new file mode 100644 index 0000000..ccb0efc --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp @@ -0,0 +1,128 @@ + /* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +AtlasGlyphManager::AtlasGlyphManager() +{ +} + +AtlasGlyphManager::~AtlasGlyphManager() +{ +} + +AtlasGlyphManager AtlasGlyphManager::Get() +{ + AtlasGlyphManager manager; + + // Check whether the AtlasGlyphManager is already created + SingletonService singletonService( SingletonService::Get() ); + if ( singletonService ) + { + Dali::BaseHandle handle = singletonService.GetSingleton(typeid(AtlasGlyphManager)); + if(handle) + { + // If so, downcast the handle of singleton to AtlasGlyphManager + manager = AtlasGlyphManager(dynamic_cast(handle.GetObjectPtr())); + } + + if(!manager) + { + // If not, create the AtlasGlyphManager and register it as a singleton + manager = AtlasGlyphManager(new Internal::AtlasGlyphManager()); + singletonService.Register(typeid(manager), manager); + } + } + return manager; +} + +AtlasGlyphManager::AtlasGlyphManager(Internal::AtlasGlyphManager *impl) + : BaseHandle(impl) +{ +} + +void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph, + const BufferImage& bitmap, + AtlasManager::AtlasSlot& slot ) +{ + GetImplementation(*this).Add( glyph, bitmap, slot ); +} + +void AtlasGlyphManager::GenerateMeshData( uint32_t imageId, + const Vector2& position, + MeshData& meshData ) +{ + GetImplementation(*this).GenerateMeshData( imageId, + position, + meshData ); +} + +void AtlasGlyphManager::StitchMesh( MeshData& first, + const MeshData& second ) +{ + GetImplementation(*this).StitchMesh( first, second ); +} + +void AtlasGlyphManager::Cached( Text::FontId fontId, + Text::GlyphIndex index, + AtlasManager::AtlasSlot& slot ) +{ + GetImplementation(*this).Cached( fontId, index, slot ); +} + +void AtlasGlyphManager::SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight ) +{ + GetImplementation(*this).SetNewAtlasSize( width, height, blockWidth, blockHeight ); +} + +Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId ) +{ + return GetImplementation(*this).GetAtlasSize( atlasId ); +} + +void AtlasGlyphManager::Remove( uint32_t imageId ) +{ + GetImplementation(*this).Remove( imageId ); +} + +Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId ) +{ + return GetImplementation(*this).GetPixelFormat( atlasId ); +} + +const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics() +{ + return GetImplementation(*this).GetMetrics(); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h new file mode 100644 index 0000000..ad2c5ea --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h @@ -0,0 +1,165 @@ +#ifndef __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__ +#define __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_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. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal DALI_INTERNAL +{ +class AtlasGlyphManager; +} + + +class AtlasGlyphManager : public BaseHandle +{ +public: + + /** + * Description of GlyphManager state + */ + struct Metrics + { + uint32_t mGlyphCount; // number of glyphs being managed + AtlasManager::Metrics mAtlasMetrics; // metrics from the Atlas Manager + }; + + /** + * @brief Create a AtlasGlyphManager handle. + * + * Calling member functions with an uninitialised handle is not allowed. + */ + AtlasGlyphManager(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~AtlasGlyphManager(); + + /** + * @brief Create or retrieve AtlasGlyphManager singleton. + * + * @return A handle to the AtlasGlyphManager control. + */ + static AtlasGlyphManager Get(); + + /** + * @brief Ask Atlas Manager to add a glyph + * + * @param[in] glyph glyph to add to an atlas + * @param[in] bitmap bitmap to use for glyph addition + * @param[out] slot information returned by atlas manager for addition + */ + void Add( const Text::GlyphInfo& glyph, + const BufferImage& bitmap, + AtlasManager::AtlasSlot& slot ); + + /** + * @brief Generate mesh data for an image contained in an atlas + * + * @param[in] imageId ID of image to generate geometry for + * @param[in] position top left of image + * @param[out] meshData generated MeshData + */ + void GenerateMeshData( uint32_t imageId, + const Vector2& position, + MeshData& meshData ); + + /** + * @brief Stitch Two Meshes together + * + * @param[in] first first mesh + * @param[in] second second mesh + */ + void StitchMesh( MeshData& first, + const MeshData& second ); + + /** + * @brief Check to see if a glyph is being cached + * + * @param[in] fontId The font that this glyph comes from + * @param[in] index The GlyphIndex of this glyph + * @param[out] slot container holding information about the glyph( mImage = 0 indicates not being cached ) + */ + void Cached( Text::FontId fontId, + Text::GlyphIndex index, + AtlasManager::AtlasSlot& slot ); + + /** + * @brief Retrieve the size of an atlas + * + * @param[in] atlasId Id of the atlas to interrogate + * + * @return The pixel size of the atlas + */ + Vector2 GetAtlasSize( uint32_t atlasId ); + + /** + * @brief Set the atlas size and block size for subsequent Atlas generation + * + * @param[in] width width of atlas in pixels + * @param[in] height height of atlas in pixels + * @param[in] blockWidth width of a block in pixels + * @param[in] blockHeight height of a block in pixels + */ + void SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight ); + + /** + * @brief Unreference an image from the atlas and remove from cache if no longer needed + * + * @param[in] imageId ID of the image + */ + void Remove( uint32_t imageId ); + + /** + * @brief Get the Pixel Format used by an atlas + * + * @param[in] atlasId Id of atlas to check + * + * @return The pixel format of the atlas + */ + Pixel::Format GetPixelFormat( uint32_t atlasId ); + + /** + * @brief Get Glyph Manager metrics + * + * @return const reference to glyph manager metrics + */ + const Metrics& GetMetrics(); + +private: + + explicit DALI_INTERNAL AtlasGlyphManager(Internal::AtlasGlyphManager *impl); + +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_H__ diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp new file mode 100644 index 0000000..b82b07b --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp @@ -0,0 +1,726 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#if defined(DEBUG_ENABLED) +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_ATLAS_RENDERER"); +#endif + +using namespace Dali; +using namespace Dali::Toolkit; +using namespace Dali::Toolkit::Text; + +namespace +{ + const float ZERO( 0.0f ); + const float HALF( 0.5f ); + const float ONE( 1.0f ); + const float TWO( 2.0f ); + const uint32_t DEFAULT_ATLAS_WIDTH = 512u; + const uint32_t DEFAULT_ATLAS_HEIGHT = 512u; +} + +struct AtlasRenderer::Impl : public ConnectionTracker +{ + + enum Style + { + STYLE_NORMAL, + STYLE_DROP_SHADOW + }; + + struct MeshRecord + { + Vector4 mColor; + uint32_t mAtlasId; + MeshData mMeshData; + FrameBufferImage mBuffer; + bool mIsUnderline; + }; + + struct Extent + { + float mBaseLine; + float mLeft; + float mRight; + float mUnderlinePosition; + float mUnderlineThickness; + uint32_t mMeshRecordIndex; + }; + + struct AtlasRecord + { + uint32_t mImageId; + Text::GlyphIndex mIndex; + }; + + struct MaxBlockSize + { + FontId mFontId; + uint32_t mNeededBlockWidth; + uint32_t mNeededBlockHeight; + }; + + Impl() + { + mGlyphManager = AtlasGlyphManager::Get(); + mFontClient = TextAbstraction::FontClient::Get(); + mBasicShader = BasicShader::New(); + mBgraShader = BgraShader::New(); + mBasicShadowShader = BasicShadowShader::New(); + + mFace.reserve( 6u ); + mFace.push_back( 0 ); mFace.push_back( 2u ); mFace.push_back( 1u ); + mFace.push_back( 1u ); mFace.push_back( 2u ); mFace.push_back( 3u ); + } + + void AddGlyphs( const std::vector& positions, + const Vector& glyphs, + const Vector4& textColor, + const Vector2& shadowOffset, + const Vector4& shadowColor, + bool underlineEnabled, + const Vector4& underlineColor, + float underlineHeight ) + { + AtlasManager::AtlasSlot slot; + std::vector< MeshRecord > meshContainer; + Vector< Extent > extents; + + float currentUnderlinePosition = ZERO; + float currentUnderlineThickness = underlineHeight; + uint32_t currentBlockSize = 0; + FontId lastFontId = 0; + Style style = STYLE_NORMAL; + + if ( fabsf( shadowOffset.x ) > Math::MACHINE_EPSILON_1 || fabsf( shadowOffset.y ) > Math::MACHINE_EPSILON_1 ) + { + style = STYLE_DROP_SHADOW; + } + + if ( mImageIds.Size() ) + { + // Unreference any currently used glyphs + RemoveText(); + } + + CalculateBlocksSize( glyphs ); + + for ( uint32_t i = 0; i < glyphs.Size(); ++i ) + { + GlyphInfo glyph = glyphs[ i ]; + + // No operation for white space + if ( glyph.width && glyph.height ) + { + // Are we still using the same fontId as previous + if ( glyph.fontId != lastFontId ) + { + // We need to fetch fresh font underline metrics + FontMetrics fontMetrics; + mFontClient.GetFontMetrics( glyph.fontId, fontMetrics ); + currentUnderlinePosition = ceil( fabsf( fontMetrics.underlinePosition ) ); + float descender = ceil( fabsf( fontMetrics.descender ) ); + + if ( underlineHeight == ZERO ) + { + currentUnderlineThickness = fontMetrics.underlineThickness; + + // Ensure underline will be at least a pixel high + if ( currentUnderlineThickness < ONE ) + { + currentUnderlineThickness = ONE; + } + else + { + currentUnderlineThickness = ceil( currentUnderlineThickness ); + } + } + + // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font + if ( currentUnderlinePosition > descender ) + { + currentUnderlinePosition = descender; + } + if ( ZERO == currentUnderlinePosition ) + { + // Move offset down by one ( EFL behavior ) + currentUnderlinePosition = ONE; + } + } + + Vector2 position = positions[ i ]; + MeshData newMeshData; + mGlyphManager.Cached( glyph.fontId, glyph.index, slot ); + + if ( slot.mImageId ) + { + // This glyph already exists so generate mesh data plugging in our supplied position + mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData ); + mImageIds.PushBack( slot.mImageId ); + } + else + { + + // Select correct size for new atlas if needed....? + if ( lastFontId != glyph.fontId ) + { + for ( uint32_t j = 0; j < mBlockSizes.size(); ++j ) + { + if ( mBlockSizes[ j ].mFontId == glyph.fontId ) + { + currentBlockSize = j; + mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, + DEFAULT_ATLAS_HEIGHT, + mBlockSizes[ j ].mNeededBlockWidth, + mBlockSizes[ j ].mNeededBlockHeight ); + } + } + } + + // Create a new image for the glyph + BufferImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index ); + + // Ensure that the next image will fit into the current block size + bool setSize = false; + if ( bitmap.GetWidth() > mBlockSizes[ currentBlockSize ].mNeededBlockWidth ) + { + setSize = true; + mBlockSizes[ currentBlockSize ].mNeededBlockWidth = bitmap.GetWidth(); + } + if ( bitmap.GetHeight() > mBlockSizes[ currentBlockSize ].mNeededBlockHeight ) + { + setSize = true; + mBlockSizes[ currentBlockSize ].mNeededBlockHeight = bitmap.GetHeight(); + } + + if ( setSize ) + { + mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH, + DEFAULT_ATLAS_HEIGHT, + mBlockSizes[ currentBlockSize ].mNeededBlockWidth, + mBlockSizes[ currentBlockSize ].mNeededBlockHeight ); + } + + // Locate a new slot for our glyph + mGlyphManager.Add( glyph, bitmap, slot ); + + // Generate mesh data for this quad, plugging in our supplied position + if ( slot.mImageId ) + { + mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData ); + mImageIds.PushBack( slot.mImageId ); + } + } + // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas) + StitchTextMesh( meshContainer, + newMeshData, + extents, + textColor, + position.y + glyph.yBearing, + currentUnderlinePosition, + currentUnderlineThickness, + slot ); + lastFontId = glyph.fontId; + } + } + + if ( underlineEnabled ) + { + // Check to see if any of the text needs an underline + GenerateUnderlines( meshContainer, extents, underlineColor, textColor ); + } + + // For each MeshData object, create a mesh actor and add to the renderable actor + if ( meshContainer.size() ) + { + for ( std::vector< MeshRecord >::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt ) + { + MeshActor actor = MeshActor::New( Mesh::New( mIt->mMeshData ) ); + actor.SetColor( mIt->mColor ); + + // Ensure that text rendering is unfiltered + actor.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); + if ( mIt->mIsUnderline ) + { + actor.SetColorMode( USE_OWN_COLOR ); + } + else + { + actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + } + + // Check to see what pixel format the shader should be + if ( mGlyphManager.GetPixelFormat( mIt->mAtlasId ) == Pixel::L8 ) + { + // Create an effect if necessary + if ( style == STYLE_DROP_SHADOW ) + { + actor.Add( GenerateShadow( *mIt, shadowOffset, shadowColor ) ); + } + actor.SetShaderEffect( mBasicShader ); + } + else + { + actor.SetShaderEffect( mBgraShader ); + } + + if ( mActor ) + { + mActor.Add( actor ); + } + else + { + mActor = actor; + } + } + mActor.OffStageSignal().Connect( this, &AtlasRenderer::Impl::OffStageDisconnect ); + } +#if defined(DEBUG_ENABLED) + Toolkit::AtlasGlyphManager::Metrics metrics = mGlyphManager.GetMetrics(); + DALI_LOG_INFO( gLogFilter, Debug::Concise, "TextAtlasRenderer::GlyphManager::GlyphCount: %i, AtlasCount: %i, TextureMemoryUse: %iK\n", + metrics.mGlyphCount, + metrics.mAtlasMetrics.mAtlasCount, + metrics.mAtlasMetrics.mTextureMemoryUsed / 1024 ); + for ( uint32_t i = 0; i < metrics.mAtlasMetrics.mAtlasCount; ++i ) + { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Atlas [%i] %sPixels: %s Size: %ix%i, BlockSize: %ix%i, BlocksUsed: %i/%i\n", + i + 1, i > 8 ? "" : " ", + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mPixelFormat == Pixel::L8 ? "L8 " : "BGRA", + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mSize.mWidth, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mSize.mHeight, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mSize.mBlockWidth, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mSize.mBlockHeight, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mBlocksUsed, + metrics.mAtlasMetrics.mAtlasMetrics[ i ].mTotalBlocks ); + } +#endif + } + + void StitchTextMesh( std::vector< MeshRecord >& meshContainer, + MeshData& newMeshData, + Vector< Extent >& extents, + const Vector4& color, + float baseLine, + float underlinePosition, + float underlineThickness, + AtlasManager::AtlasSlot& slot ) + { + if ( slot.mImageId ) + { + MeshData::VertexContainer verts = newMeshData.GetVertices(); + float left = verts[ 0 ].x; + float right = verts[ 1 ].x; + + // Check to see if there's a mesh data object that references the same atlas ? + uint32_t index = 0; + for ( std::vector< MeshRecord >::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt, ++index ) + { + if ( slot.mAtlasId == mIt->mAtlasId && color == mIt->mColor ) + { + // Stitch the mesh to the existing mesh and adjust any extents + mGlyphManager.StitchMesh( mIt->mMeshData, newMeshData ); + AdjustExtents( extents, + meshContainer, + index, + left, + right, + baseLine, + underlinePosition, + underlineThickness ); + return; + } + } + + // No mesh data object currently exists that references this atlas, so create a new one + MeshRecord meshRecord; + meshRecord.mAtlasId = slot.mAtlasId; + meshRecord.mMeshData = newMeshData; + meshRecord.mColor = color; + meshRecord.mIsUnderline = false; + meshContainer.push_back( meshRecord ); + + // Adjust extents for this new meshrecord + AdjustExtents( extents, + meshContainer, + meshContainer.size() - 1u, + left, + right, + baseLine, + underlinePosition, + underlineThickness ); + + } + } + + void AdjustExtents( Vector< Extent >& extents, + std::vector< MeshRecord>& meshRecords, + uint32_t index, + float left, + float right, + float baseLine, + float underlinePosition, + float underlineThickness ) + { + bool foundExtent = false; + for ( Vector< Extent >::Iterator eIt = extents.Begin(); eIt != extents.End(); ++eIt ) + { + if ( Equals( baseLine, eIt->mBaseLine ) ) + { + foundExtent = true; + if ( left < eIt->mLeft ) + { + eIt->mLeft = left; + } + if ( right > eIt->mRight ) + { + eIt->mRight = right; + } + + if ( underlinePosition > eIt->mUnderlinePosition ) + { + eIt->mUnderlinePosition = underlinePosition; + } + if ( underlineThickness > eIt->mUnderlineThickness ) + { + eIt->mUnderlineThickness = underlineThickness; + } + } + } + if ( !foundExtent ) + { + Extent extent; + extent.mLeft = left; + extent.mRight = right; + extent.mBaseLine = baseLine; + extent.mUnderlinePosition = underlinePosition; + extent.mUnderlineThickness = underlineThickness; + extent.mMeshRecordIndex = index; + extents.PushBack( extent ); + } + } + + // Unreference any glyphs that were used with this actor + void OffStageDisconnect( Dali::Actor actor ) + { + RemoveText(); + } + + void RemoveText() + { + for ( uint32_t i = 0; i < mImageIds.Size(); ++i ) + { + mGlyphManager.Remove( mImageIds[ i ] ); + } + mImageIds.Resize( 0 ); + } + + void CalculateBlocksSize( const Vector& glyphs ) + { + MaxBlockSize maxBlockSize; + for ( uint32_t i = 0; i < glyphs.Size(); ++i ) + { + FontId fontId = glyphs[ i ].fontId; + bool foundFont = false; + for ( uint32_t j = 0; j < mBlockSizes.size(); ++j ) + { + if ( mBlockSizes[ j ].mFontId == fontId ) + { + foundFont = true; + } + } + if ( !foundFont ) + { + FontMetrics fontMetrics; + mFontClient.GetFontMetrics( fontId, fontMetrics ); + maxBlockSize.mNeededBlockWidth = static_cast< uint32_t >( fontMetrics.height ); + maxBlockSize.mNeededBlockHeight = static_cast< uint32_t >( fontMetrics.height ); + maxBlockSize.mFontId = fontId; + mBlockSizes.push_back( maxBlockSize ); + } + } + } + + void GenerateUnderlines( std::vector< MeshRecord>& meshRecords, + Vector< Extent >& extents, + const Vector4& underlineColor, + const Vector4& textColor ) + { + MeshData newMeshData; + for ( Vector< Extent >::ConstIterator eIt = extents.Begin(); eIt != extents.End(); ++eIt ) + { + MeshData::VertexContainer newVerts; + newVerts.reserve( 4u ); + uint32_t index = eIt->mMeshRecordIndex; + Vector2 uv = mGlyphManager.GetAtlasSize( meshRecords[ index ].mAtlasId ); + + // Make sure we don't hit texture edge for single pixel texture ( filled pixel is in top left of every atlas ) + float u = HALF / uv.x; + float v = HALF / uv.y; + float thickness = eIt->mUnderlineThickness; + float baseLine = eIt->mBaseLine + eIt->mUnderlinePosition - ( thickness * HALF ); + float tlx = eIt->mLeft; + float brx = eIt->mRight; + + newVerts.push_back( MeshData::Vertex( Vector3( tlx, baseLine, ZERO ), + Vector2::ZERO, + Vector3::ZERO ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( brx, baseLine, ZERO ), + Vector2( u, ZERO ), + Vector3::ZERO ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( tlx, baseLine + thickness, ZERO ), + Vector2( ZERO, v ), + Vector3::ZERO ) ); + + newVerts.push_back( MeshData::Vertex( Vector3( brx, baseLine + thickness, ZERO ), + Vector2( u, v ), + Vector3::ZERO ) ); + + newMeshData.SetVertices( newVerts ); + newMeshData.SetFaceIndices( mFace ); + + if ( underlineColor == textColor ) + { + mGlyphManager.StitchMesh( meshRecords[ index ].mMeshData, newMeshData ); + } + else + { + MeshRecord record; + newMeshData.SetMaterial( meshRecords[ index ].mMeshData.GetMaterial() ); + newMeshData.SetHasNormals( true ); + newMeshData.SetHasColor( false ); + newMeshData.SetHasTextureCoords( true ); + record.mMeshData = newMeshData; + record.mAtlasId = meshRecords[ index ].mAtlasId; + record.mColor = underlineColor; + record.mIsUnderline = true; + meshRecords.push_back( record ); + } + } + } + + MeshActor GenerateShadow( MeshRecord& meshRecord, + const Vector2& shadowOffset, + const Vector4& shadowColor ) + { + // Scan vertex buffer to determine width and height of effect buffer needed + MeshData::VertexContainer verts = meshRecord.mMeshData.GetVertices(); + float tlx = verts[ 0 ].x; + float tly = verts[ 0 ].y; + float brx = ZERO; + float bry = ZERO; + + for ( uint32_t i = 0; i < verts.size(); ++i ) + { + if ( verts[ i ].x < tlx ) + { + tlx = verts[ i ].x; + } + if ( verts[ i ].y < tly ) + { + tly = verts[ i ].y; + } + if ( verts[ i ].x > brx ) + { + brx = verts[ i ].x; + } + if ( verts[ i ].y > bry ) + { + bry = verts[ i ].y; + } + } + + float width = brx - tlx; + float height = bry - tly; + float divWidth = TWO / width; + float divHeight = TWO / height; + + // Create a buffer to render to + meshRecord.mBuffer = FrameBufferImage::New( width, height ); + + // Create a mesh actor to contain the post-effect render + MeshData::VertexContainer vertices; + MeshData::FaceIndices face; + + vertices.push_back( MeshData::Vertex( Vector3( tlx + shadowOffset.x, tly + shadowOffset.y, ZERO ), + Vector2::ZERO, + Vector3::ZERO ) ); + + vertices.push_back( MeshData::Vertex( Vector3( brx + shadowOffset.x, tly + shadowOffset.y, ZERO ), + Vector2( ONE, ZERO ), + Vector3::ZERO ) ); + + vertices.push_back( MeshData::Vertex( Vector3( tlx + shadowOffset.x, bry + shadowOffset.y, ZERO ), + Vector2( ZERO, ONE ), + Vector3::ZERO ) ); + + vertices.push_back( MeshData::Vertex( Vector3( brx + shadowOffset.x, bry + shadowOffset.y, ZERO ), + Vector2::ONE, + Vector3::ZERO ) ); + + MeshData meshData; + Material newMaterial = Material::New("effect buffer"); + newMaterial.SetDiffuseTexture( meshRecord.mBuffer ); + meshData.SetMaterial( newMaterial ); + meshData.SetVertices( vertices ); + meshData.SetFaceIndices( mFace ); + meshData.SetHasNormals( true ); + meshData.SetHasColor( false ); + meshData.SetHasTextureCoords( true ); + MeshActor actor = MeshActor::New( Mesh::New( meshData ) ); + actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + actor.SetShaderEffect( mBgraShader ); + actor.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); + actor.SetSortModifier( 0.1f ); // force behind main text + + // Create a sub actor to render once with normalized vertex positions + MeshData newMeshData; + MeshData::VertexContainer newVerts; + MeshData::FaceIndices newFaces; + MeshData::FaceIndices faces = meshRecord.mMeshData.GetFaces(); + for ( uint32_t i = 0; i < verts.size(); ++i ) + { + MeshData::Vertex vertex = verts[ i ]; + vertex.x = ( ( vertex.x - tlx ) * divWidth ) - ONE; + vertex.y = ( ( vertex.y - tly ) * divHeight ) - ONE; + newVerts.push_back( vertex ); + } + + // Reverse triangle winding order + uint32_t faceCount = faces.size() / 3; + for ( uint32_t i = 0; i < faceCount; ++i ) + { + uint32_t index = i * 3; + newFaces.push_back( faces[ index + 2 ] ); + newFaces.push_back( faces[ index + 1 ] ); + newFaces.push_back( faces[ index ] ); + } + + newMeshData.SetMaterial( meshRecord.mMeshData.GetMaterial() ); + newMeshData.SetVertices( newVerts ); + newMeshData.SetFaceIndices( newFaces ); + newMeshData.SetHasNormals( true ); + newMeshData.SetHasColor( false ); + newMeshData.SetHasTextureCoords( true ); + + MeshActor subActor = MeshActor::New( Mesh::New( newMeshData ) ); + subActor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + subActor.SetColor( shadowColor ); + subActor.SetShaderEffect( mBasicShadowShader ); + subActor.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); + + // Create a render task to render the effect + RenderTask task = Stage::GetCurrent().GetRenderTaskList().CreateTask(); + task.SetTargetFrameBuffer( meshRecord.mBuffer ); + task.SetSourceActor( subActor ); + task.SetClearEnabled( true ); + task.SetClearColor( Vector4::ZERO ); + task.SetExclusive( true ); + task.SetRefreshRate( RenderTask::REFRESH_ONCE ); + task.FinishedSignal().Connect( this, &AtlasRenderer::Impl::RenderComplete ); + actor.Add( subActor ); + return actor; + } + + void RenderComplete( RenderTask& renderTask ) + { + // Disconnect and remove this single shot render task + renderTask.FinishedSignal().Disconnect( this, &AtlasRenderer::Impl::RenderComplete ); + Stage::GetCurrent().GetRenderTaskList().RemoveTask( renderTask ); + + // Get the actor used for render to buffer and remove it from the parent + Actor renderActor = renderTask.GetSourceActor(); + if ( renderActor ) + { + Actor parent = renderActor.GetParent(); + if ( parent ) + { + parent.Remove( renderActor ); + } + } + } + + RenderableActor mActor; ///< The actor parent which renders the text + AtlasGlyphManager mGlyphManager; ///< Glyph Manager to handle upload and caching + Vector< uint32_t > mImageIds; ///< A list of imageIDs used by the renderer + TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information + ShaderEffect mBasicShader; ///> Shader used to render L8 glyphs + ShaderEffect mBgraShader; ///> Shader used to render BGRA glyphs + ShaderEffect mBasicShadowShader; ///> Shader used to render drop shadow into buffer + std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas + std::vector< MeshData::FaceIndex > mFace; ///> Face indices for a quad +}; + +Text::RendererPtr AtlasRenderer::New() +{ + return Text::RendererPtr( new AtlasRenderer() ); +} + +RenderableActor AtlasRenderer::Render( Text::ViewInterface& view ) +{ + + UnparentAndReset( mImpl->mActor ); + + Text::Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + if( numberOfGlyphs > 0 ) + { + Vector glyphs; + glyphs.Resize( numberOfGlyphs ); + + view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs ); + + std::vector positions; + positions.resize( numberOfGlyphs ); + view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs ); + mImpl->AddGlyphs( positions, + glyphs, + view.GetTextColor(), + view.GetShadowOffset(), + view.GetShadowColor(), + view.IsUnderlineEnabled(), + view.GetUnderlineColor(), + view.GetUnderlineHeight() ); + } + return mImpl->mActor; +} + +AtlasRenderer::AtlasRenderer() +{ + mImpl = new Impl(); + +} + +AtlasRenderer::~AtlasRenderer() +{ + delete mImpl; +} diff --git a/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.h b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.h new file mode 100644 index 0000000..e259621 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.h @@ -0,0 +1,87 @@ +#ifndef __DALI_TOOLKIT_TEXT_ATLAS_RENDERER_H__ +#define __DALI_TOOLKIT_TEXT_ATLAS_RENDERER_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. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief Implementation of a text renderer based on dynamic atlases. + * + */ +class AtlasRenderer : public Renderer +{ +public: + + /** + * @brief Create the renderer. + */ + static RendererPtr New(); + + /** + * @brief Render the glyphs from a ViewInterface. + * + * @param[in] view The interface to a view. + * @return The Renderable actor used to position the text. + */ + virtual RenderableActor Render( ViewInterface& view ); + +protected: + + /** + * @brief Constructor. + */ + AtlasRenderer(); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~AtlasRenderer(); + +private: + + // Undefined + AtlasRenderer( const AtlasRenderer& handle ); + + // Undefined + AtlasRenderer& operator=( const AtlasRenderer& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_ATLAS_RENDERER_H__ diff --git a/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp new file mode 100644 index 0000000..dc6ec3e --- /dev/null +++ b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.cpp @@ -0,0 +1,407 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include + + +using namespace Dali; +using namespace Dali::Toolkit; +using namespace Dali::Toolkit::Text; + +namespace +{ + +const std::size_t PADDING = 2; //< To avoid GL filtering artefacts + +struct TextureCoordinates +{ + TextureCoordinates() + : topLeft( 0.0f, 0.0f ), + topRight( 1.0f, 0.0f ), + bottomLeft( 0.0f, 1.0f ), + bottomRight( 1.0f, 1.0f ) + { + } + + Vector2 topLeft; + Vector2 topRight; + Vector2 bottomLeft; + Vector2 bottomRight; +}; + +struct AtlasGlyph +{ + AtlasGlyph() + : fontId( 0 ), + index( 0 ), + xOffset( 0 ), + width( 0 ), + height( 0 ) + { + } + + AtlasGlyph( FontId id, + GlyphIndex glyphIndex, + std::size_t offset, + std::size_t widthPixels, + std::size_t heightPixels, + BufferImage bitmap ) + : fontId( id ), + index( glyphIndex ), + xOffset( offset ), + width( widthPixels ), + height( heightPixels ), + mBitmap( bitmap ) + { + } + + FontId fontId; + GlyphIndex index; + std::size_t xOffset; + std::size_t width; + std::size_t height; + BufferImage mBitmap; + TextureCoordinates coords; +}; + +} // unnamed namespace + +struct BasicRenderer::Impl +{ + /** + * @brief Create the renderer implementation. + */ + Impl() + : mWidthL8( 0.0f ), + mHeightL8( 0.0f ), + mWidthBGRA8888( 0.0f ), + mHeightBGRA8888( 0.0f ) + { + mFontClient = TextAbstraction::FontClient::Get(); + } + + /** + * @brief Reset the previous glyph calculations. + * + * @param[in] size The glyph space to reserve. + */ + void Reset( std::size_t size ) + { + mWidthL8 = 0.0f; + mHeightL8 = 0.0f; + mWidthBGRA8888 = 0.0f; + mHeightBGRA8888 = 0.0f; + mGlyphs.clear(); + mGlyphs.reserve( size ); + mAtlasL8.Reset(); + mAtlasBGRA8888.Reset(); + } + + /** + * @brief Ccreate an Atlas, uploading the necessary glyph bitmaps + * + * @param[in] glyphs The glyphs to upload. + */ + void CreateAtlases( const Vector& glyphs ) + { + // Clear previous atlas + Reset( glyphs.Count() ); + + for( unsigned int i=0; i 0 && + height > 0 ) // skip whitespace + { + if( !GlyphFound( glyphs[i].fontId, glyphs[i].index ) ) + { + AddGlyph( glyphs[i] ); + } + } + } + + mAtlasL8 = CreateAtlas( mWidthL8, mHeightL8, Pixel::L8 ); + mAtlasBGRA8888 = CreateAtlas( mWidthBGRA8888, mHeightBGRA8888, Pixel::BGRA8888 ); + } + + Atlas CreateAtlas( unsigned int width, unsigned int height, Pixel::Format format ) + { + Atlas atlas; + + if( width > 0 && height > 0 ) + { + atlas = Atlas::New( width, height, format ); + + for( unsigned int i=0; i(glyph.xOffset) / static_cast(width); + coords.topLeft.y = 0.0f; + coords.topRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(width); + coords.topRight.y = 0.0f; + coords.bottomLeft.x = static_cast(glyph.xOffset) / static_cast(width); + coords.bottomLeft.y = static_cast(glyph.height) / static_cast(height); + coords.bottomRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(width); + coords.bottomRight.y = static_cast(glyph.height) / static_cast(height); + } + } + } + + return atlas; + } + + /** + * @brief Check whether we already have the glyph. + */ + bool GlyphFound( FontId fontId, GlyphIndex index ) const + { + for( unsigned int i=0; i& glyphs, const std::vector& positions, Pixel::Format format, Image image ) + { + MeshData::VertexContainer vertices( 4 * glyphs.Count() ); // 1 quad per glyph + + MeshData::FaceIndices faces; + faces.reserve( 6 * glyphs.Count() ); // 2 triangles per quad + + for( unsigned int i=0; i 0 && + height > 0 ) // skip whitespace + { + const Vector2& position = positions[i]; + + TextureCoordinates coords; + if( GetTextureCoordinates( format, glyphs[i].fontId, glyphs[i].index, coords ) ) + { + vertices[ i*4 + 0 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 0.0f*height, 0.0f ), coords.topLeft, Vector3( 1.0f, 0.0f, 0.0f ) ); + vertices[ i*4 + 1 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 0.0f*height, 0.0f ), coords.topRight, Vector3( 1.0f, 1.0f, 0.0f ) ); + vertices[ i*4 + 2 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomLeft, Vector3( 0.0f, 1.0f, 0.0f ) ); + vertices[ i*4 + 3 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomRight, Vector3( 0.0f, 0.0f, 1.0f ) ); + + faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 3 ); faces.push_back( i*4 + 1 ); + faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 2 ); faces.push_back( i*4 + 3 ); + } + } + } + + Material material = Material::New( "Material" ); + material.SetDiffuseTexture( image ); + + // Create the mesh data from the vertices and faces + MeshData meshData; + meshData.SetHasColor( false ); + meshData.SetMaterial( material ); + meshData.SetVertices( vertices ); + meshData.SetFaceIndices( faces ); + + // Create a mesh from the data + Dali::Mesh mesh = Mesh::New( meshData ); + return mesh; + } + + RenderableActor mActor; ///< The actor which renders the text + + Atlas mAtlasL8; + unsigned int mWidthL8; + unsigned int mHeightL8; + + // A separate Atlas is used for color Emojis + Atlas mAtlasBGRA8888; + unsigned int mWidthBGRA8888; + unsigned int mHeightBGRA8888; + + std::vector mGlyphs; + + TextAbstraction::FontClient mFontClient; +}; + +Text::RendererPtr BasicRenderer::New() +{ + return Text::RendererPtr( new BasicRenderer() ); +} + +RenderableActor BasicRenderer::Render( Text::ViewInterface& view ) +{ + // Remove the previous text + UnparentAndReset( mImpl->mActor ); + + Text::Length numberOfGlyphs = view.GetNumberOfGlyphs(); + + if( numberOfGlyphs > 0 ) + { + Vector glyphs; + glyphs.Resize( numberOfGlyphs ); + + view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs ); + + std::vector positions; + positions.resize( numberOfGlyphs ); + view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs ); + + mImpl->CreateAtlases( glyphs ); + + MeshActor actorL8; + if( mImpl->mAtlasL8 ) + { + actorL8 = MeshActor::New( mImpl->CreateMesh( glyphs, positions, Pixel::L8, mImpl->mAtlasL8 ) ); + actorL8.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + + ShaderEffect shader = BasicShader::New(); + actorL8.SetShaderEffect( shader ); + } + + MeshActor actorBGRA8888; + if( mImpl->mAtlasBGRA8888 ) + { + actorBGRA8888 = MeshActor::New( mImpl->CreateMesh( glyphs, positions, Pixel::BGRA8888, mImpl->mAtlasBGRA8888 ) ); + actorBGRA8888.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + + ShaderEffect shader = BgraShader::New(); + actorBGRA8888.SetShaderEffect( shader ); + } + + // If we have both monochrome & color glyphs, two mesh actors are returned in a container + if( actorL8 && actorBGRA8888 ) + { + mImpl->mActor = ImageActor::New(); + mImpl->mActor.Add( actorL8 ); + mImpl->mActor.Add( actorBGRA8888 ); + } + else + { + if( actorL8 ) + { + mImpl->mActor = actorL8; + } + else if( actorBGRA8888 ) + { + mImpl->mActor = actorBGRA8888; + } + } + } + + return mImpl->mActor; +} + +BasicRenderer::BasicRenderer() +{ + mImpl = new Impl(); +} + +BasicRenderer::~BasicRenderer() +{ + delete mImpl; +} diff --git a/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.h b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.h new file mode 100644 index 0000000..1cf8469 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/basic/text-basic-renderer.h @@ -0,0 +1,90 @@ +#ifndef __DALI_TOOLKIT_TEXT_BASIC_RENDERER_H__ +#define __DALI_TOOLKIT_TEXT_BASIC_RENDERER_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. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A reference implementation of Text::Renderer. + * + * This is intended for testing & performance comparisons with more complex solutions. + * Each basic renderer creates its own texture atlas, and uses a simple packing algorithm, + * in which glyphs are stored in a single row. + */ +class BasicRenderer : public Renderer +{ +public: + + /** + * @brief Create the renderer. + */ + static RendererPtr New(); + + /** + * @brief Render the glyphs from a ViewInterface. + * + * @param[in] view The interface to a view. + * @return The Renderable actor used to position the text. + */ + virtual RenderableActor Render( ViewInterface& view ); + +protected: + + /** + * @brief Constructor. + */ + BasicRenderer(); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~BasicRenderer(); + +private: + + // Undefined + BasicRenderer( const BasicRenderer& handle ); + + // Undefined + BasicRenderer& operator=( const BasicRenderer& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BASIC_RENDERER_H__ diff --git a/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.cpp b/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.cpp new file mode 100644 index 0000000..0afddbb --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.cpp @@ -0,0 +1,64 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace BasicShader +{ + +Dali::ShaderEffect New() +{ + std::string vertexShader = DALI_COMPOSE_SHADER( + uniform mediump vec4 uTextureRect;\n + void main()\n + {\n + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + }\n + ); + + std::string fragmentShader = DALI_COMPOSE_SHADER( + void main()\n + {\n + mediump vec4 color = texture2D( sTexture, vTexCoord ); + gl_FragColor = vec4(uColor.rgb, uColor.a*color.r); + }\n + ); + + Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( vertexShader, fragmentShader, + Dali::GeometryType( Dali::GEOMETRY_TYPE_TEXTURED_MESH ), + Dali::ShaderEffect::GeometryHints( Dali::ShaderEffect::HINT_NONE ) ); + return shaderEffect; +} + +} // namespace BasicShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h b/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h new file mode 100644 index 0000000..cc97d1b --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h @@ -0,0 +1,53 @@ +#ifndef __DALI_TOOLKIT_TEXT_BASIC_SHADER_H__ +#define __DALI_TOOLKIT_TEXT_BASIC_SHADER_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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A basic shader for rendering glyphs in Pixel::L8 format. + */ +namespace BasicShader +{ + +/** + * Create a basic text shader. + * @return A handle to a newly allocated ShaderEffect + */ +Dali::ShaderEffect New(); + +} // namespace BasicShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BASIC_SHADER_H__ diff --git a/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.cpp b/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.cpp new file mode 100644 index 0000000..f7789f1 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.cpp @@ -0,0 +1,63 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace BasicShadowShader +{ + +Dali::ShaderEffect New() +{ + std::string vertexShader = DALI_COMPOSE_SHADER( + void main()\n + {\n + gl_Position = vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + }\n + ); + + std::string fragmentShader = DALI_COMPOSE_SHADER( + void main()\n + {\n + mediump vec4 color = texture2D( sTexture, vTexCoord ); + gl_FragColor = vec4(uColor.rgb, uColor.a*color.r); + }\n + ); + + Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( vertexShader, fragmentShader, + Dali::GeometryType( Dali::GEOMETRY_TYPE_TEXTURED_MESH ), + Dali::ShaderEffect::GeometryHints( Dali::ShaderEffect::HINT_NONE ) ); + return shaderEffect; +} + +} // namespace BasicShadowShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.h b/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.h new file mode 100644 index 0000000..93bd0a3 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-basic-shadow-shader.h @@ -0,0 +1,53 @@ +#ifndef __DALI_TOOLKIT_TEXT_BASIC_SHADOW_SHADER_H__ +#define __DALI_TOOLKIT_TEXT_BASIC_SHADOW_SHADER_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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A basic shader for rendering glyphs in Pixel::L8 format. + */ +namespace BasicShadowShader +{ + +/** + * Create a basic text shadow shader. + * @return A handle to a newly allocated ShaderEffect + */ +Dali::ShaderEffect New(); + +} // namespace BasicShadowShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BASIC_SHADOW_SHADER_H__ diff --git a/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.cpp b/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.cpp new file mode 100644 index 0000000..7f2f2a5 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.cpp @@ -0,0 +1,64 @@ +/* + * 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. + * + */ + +// INTERNAL HEADERS +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace BgraShader +{ + +Dali::ShaderEffect New() +{ + std::string vertexShader = DALI_COMPOSE_SHADER( + uniform mediump vec4 uTextureRect;\n + void main()\n + {\n + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + }\n + ); + + std::string fragmentShader = DALI_COMPOSE_SHADER( + void main()\n + {\n + gl_FragColor = texture2D( sTexture, vTexCoord ); + }\n + ); + + Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( vertexShader, fragmentShader, + Dali::GeometryType( Dali::GEOMETRY_TYPE_TEXTURED_MESH ), + Dali::ShaderEffect::GeometryHints( Dali::ShaderEffect::HINT_NONE ) ); + return shaderEffect; +} + +} // namespace BGRAShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + diff --git a/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h b/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h new file mode 100644 index 0000000..16293c6 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h @@ -0,0 +1,54 @@ + +#ifndef __DALI_TOOLKIT_TEXT_BGRA_SHADER_H__ +#define __DALI_TOOLKIT_TEXT_BGRA_SHADER_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 + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief A BGRA shader for rendering glyphs. + */ +namespace BgraShader +{ + +/** + * Create a basic text shader. + * @return A handle to a newly allocated ShaderEffect + */ +Dali::ShaderEffect New(); + +} // namespace BGRAShader + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BGRA_SHADER_H__ diff --git a/dali-toolkit/internal/text/rendering/text-backend-impl.cpp b/dali-toolkit/internal/text/rendering/text-backend-impl.cpp new file mode 100644 index 0000000..5653ebf --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-backend-impl.cpp @@ -0,0 +1,117 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal +{ + +struct Backend::Impl +{ + int temp; // placeholder for future backend implemenations +}; + +Backend::Backend() +: mImpl( NULL ) +{ + mImpl = new Impl(); +} + +Backend::~Backend() +{ + delete mImpl; +} + +Dali::Toolkit::Text::Backend Backend::Get() +{ + Dali::Toolkit::Text::Backend backendHandle; + + Dali::SingletonService service( SingletonService::Get() ); + if ( service ) + { + // Check whether the singleton is already created + Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::Toolkit::Text::Backend ) ); + if(handle) + { + // If so, downcast the handle + Backend* impl = dynamic_cast< Dali::Toolkit::Text::Internal::Backend* >( handle.GetObjectPtr() ); + backendHandle = Dali::Toolkit::Text::Backend( impl ); + } + else // create and register the object + { + backendHandle = Dali::Toolkit::Text::Backend( new Backend ); + service.Register( typeid( backendHandle ), backendHandle ); + } + } + + return backendHandle; +} + +RendererPtr Backend::NewRenderer( unsigned int renderingType ) +{ + RendererPtr renderer; + + switch( renderingType ) + { + case Dali::Toolkit::Text::RENDERING_BASIC: + { + renderer = Dali::Toolkit::Text::BasicRenderer::New(); + } + break; + + case Dali::Toolkit::Text::RENDERING_SHARED_ATLAS: + { + renderer = Dali::Toolkit::Text::AtlasRenderer::New(); + } + break; + + default: + { + DALI_LOG_WARNING( "Unknown renderer type: %d", renderingType ); + break; + } + } + + return renderer; +} + +} // namespace Internal + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/text-backend-impl.h b/dali-toolkit/internal/text/rendering/text-backend-impl.h new file mode 100644 index 0000000..a185ee2 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-backend-impl.h @@ -0,0 +1,103 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_BACKEND_H__ +#define __DALI_TOOLKIT_INTERNAL_TEXT_BACKEND_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal +{ + +/** + * Implementation of the text rendering backend + */ +class Backend : public BaseObject +{ +public: + + /** + * Constructor + */ + Backend(); + + /** + * Destructor + */ + ~Backend(); + + /** + * @copydoc Dali::Toolkit::Text::Backend::Get() + */ + static Dali::Toolkit::Text::Backend Get(); + + /** + * @copydoc Dali::Toolkit::Text::Backend::NewRenderer() + */ + RendererPtr NewRenderer( unsigned int renderingType ); + +private: + + // Undefined copy constructor. + Backend( const Backend& ); + + // Undefined assignment constructor. + Backend& operator=( Backend& ); + +private: + + struct Impl; + Impl* mImpl; + +}; // class Backend + +} // namespace Internal + +inline static Internal::Backend& GetImplementation(Backend& backend) +{ + DALI_ASSERT_ALWAYS( backend && "backend handle is empty" ); + BaseObject& handle = backend.GetBaseObject(); + return static_cast(handle); +} + +inline static const Internal::Backend& GetImplementation(const Backend& backend) +{ + DALI_ASSERT_ALWAYS( backend && "backend handle is empty" ); + const BaseObject& handle = backend.GetBaseObject(); + return static_cast(handle); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_INTERNAL_TEXT_BACKEND_H__ diff --git a/dali-toolkit/internal/text/rendering/text-backend.cpp b/dali-toolkit/internal/text/rendering/text-backend.cpp new file mode 100644 index 0000000..ee48026 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-backend.cpp @@ -0,0 +1,71 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +Backend Backend::Get() +{ + return Internal::Backend::Get(); +} + +RendererPtr Backend::NewRenderer( unsigned int renderingType ) +{ + return GetImplementation(*this).NewRenderer( renderingType ); +} + +Backend::Backend() +{ +} + +Backend::~Backend() +{ +} + +Backend::Backend( const Backend& handle ) +: BaseHandle( handle ) +{ +} + +Backend& Backend::operator=( const Backend& handle ) +{ + BaseHandle::operator=( handle ); + return *this; +} + +Backend::Backend( Internal::Backend* internal ) +: BaseHandle( internal ) +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/text-backend.h b/dali-toolkit/internal/text/rendering/text-backend.h new file mode 100644 index 0000000..42eacff --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-backend.h @@ -0,0 +1,106 @@ +#ifndef __DALI_TOOLKIT_TEXT_BACKEND_H__ +#define __DALI_TOOLKIT_TEXT_BACKEND_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +namespace Internal DALI_INTERNAL +{ +class Backend; +} + +/** + * @brief Provides access to different text rendering backends. + */ +class Backend : public BaseHandle +{ +public: + + /** + * @brief Retrieve a handle to the Backend instance. + * + * @return A handle to the Backend + */ + static Backend Get(); + + /** + * @brief Create a renderer from a particluar rendering type. + * + * @param[in] renderingType The type of rendering required. + * @return A handle to the newly created renderer. + */ + RendererPtr NewRenderer( unsigned int renderingType ); + + /** + * @brief Create an uninitialized TextAbstraction handle. + */ + Backend(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~Backend(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @param[in] handle A reference to the copied handle. + */ + Backend( const Backend& handle ); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @param [in] handle A reference to the copied handle. + * @return A reference to this. + */ + Backend& operator=( const Backend& handle ); + +public: // Not intended for application developers + + /** + * @brief This constructor is used by Backend::Get(). + * + * @param[in] backend A pointer to the internal backend object. + */ + explicit DALI_INTERNAL Backend( Internal::Backend* backend ); +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_BACKEND_H__ diff --git a/plugins/dali-script-v8/src/actors/text-actor-api.h b/dali-toolkit/internal/text/rendering/text-renderer.cpp similarity index 59% rename from plugins/dali-script-v8/src/actors/text-actor-api.h rename to dali-toolkit/internal/text/rendering/text-renderer.cpp index f074703..4d74934 100644 --- a/plugins/dali-script-v8/src/actors/text-actor-api.h +++ b/dali-toolkit/internal/text/rendering/text-renderer.cpp @@ -1,6 +1,3 @@ -#ifndef __DALI_V8PLUGIN_TEXT_ACTOR_API_H__ -#define __DALI_V8PLUGIN_TEXT_ACTOR_API_H__ - /* * Copyright (c) 2015 Samsung Electronics Co., Ltd. * @@ -18,26 +15,28 @@ * */ - -// EXTERNAL INCLUDES -#include -#include +// CLASS HEADER +#include namespace Dali { -namespace V8Plugin +namespace Toolkit { -namespace TextActorApi +namespace Text { - Actor New( const v8::FunctionCallbackInfo< v8::Value >& args ); - void SetToNaturalSize( const v8::FunctionCallbackInfo< v8::Value >& args ); -}; // namespace TextActorApi +Renderer::Renderer() +{ +} -} // namespace V8Plugin +Renderer::~Renderer() +{ +} -} // namespace Dali +} // namespace Text + +} // namespace Toolkit -#endif // header __DALI_V8PLUGIN_TEXT_ACTOR_API_H__ +} // namespace Dali diff --git a/dali-toolkit/internal/text/rendering/text-renderer.h b/dali-toolkit/internal/text/rendering/text-renderer.h new file mode 100644 index 0000000..3485f16 --- /dev/null +++ b/dali-toolkit/internal/text/rendering/text-renderer.h @@ -0,0 +1,86 @@ +#ifndef __DALI_TOOLKIT_TEXT_RENDERER_H__ +#define __DALI_TOOLKIT_TEXT_RENDERER_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 +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class Renderer; +typedef IntrusivePtr RendererPtr; + +/** + * @brief Abstract base class for Text renderers. + * + * This is reponsible for rendering the glyphs from a ViewInterface in the specified positions. + * It is implemented by returning a RenderableActor intended as the child of a UI control. + */ +class Renderer : public RefObject +{ +public: + + /** + * @brief Render the glyphs from a ViewInterface. + * + * @param[in] view The interface to a view. + * @return The Renderable actor used to position the text. + */ + virtual RenderableActor Render( ViewInterface& view ) = 0; + +protected: + + /** + * @brief Constructor. + */ + Renderer(); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~Renderer(); + +private: + + // Undefined + Renderer( const Renderer& handle ); + + // Undefined + Renderer& operator=( const Renderer& handle ); +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_RENDERER_H__ diff --git a/dali-toolkit/internal/text/script-run.h b/dali-toolkit/internal/text/script-run.h new file mode 100644 index 0000000..3533df6 --- /dev/null +++ b/dali-toolkit/internal/text/script-run.h @@ -0,0 +1,48 @@ +#ifndef __DALI_TOOLKIT_TEXT_SCRIPT_RUN_H__ +#define __DALI_TOOLKIT_TEXT_SCRIPT_RUN_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief Run of characters with the same script. + */ +struct ScriptRun +{ + CharacterRun characterRun; ///< The initial character index and the number of characters of the run. + Script script; ///< Script of the run. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_SCRIPT_RUN_H__ diff --git a/dali-toolkit/internal/text/segmentation.cpp b/dali-toolkit/internal/text/segmentation.cpp new file mode 100644 index 0000000..efac834 --- /dev/null +++ b/dali-toolkit/internal/text/segmentation.cpp @@ -0,0 +1,87 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +void SetLineBreakInfo( const Vector& text, + Vector& lineBreakInfo ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + // Retrieve the line break info. + lineBreakInfo.Resize( numberOfCharacters ); + TextAbstraction::Segmentation::Get().GetLineBreakPositions( text.Begin(), + numberOfCharacters, + lineBreakInfo.Begin() ); +} + +void ReplaceLineBreakInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +void SetWordBreakInfo( const Vector& text, + Vector& wordBreakInfo ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + + // Retrieve the word break info. + wordBreakInfo.Resize( numberOfCharacters ); + TextAbstraction::Segmentation::Get().GetWordBreakPositions( text.Begin(), + numberOfCharacters, + wordBreakInfo.Begin() ); +} + +void ReplaceWordBreakInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/segmentation.h b/dali-toolkit/internal/text/segmentation.h new file mode 100644 index 0000000..949b1c9 --- /dev/null +++ b/dali-toolkit/internal/text/segmentation.h @@ -0,0 +1,107 @@ +#ifndef __DALI_TOOLKIT_TEXT_SEGMENTATION_H__ +#define __DALI_TOOLKIT_TEXT_SEGMENTATION_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class LogicalModel; + +/** + * Sets line break info. + * + * Possible values for LineBreakInfo are: + * + * - 0 is a LINE_MUST_BREAK. Text must be broken into a new line. + * - 1 is a LINE_ALLOW_BREAK. Is possible to break the text into a new line. + * - 2 is a LINE_NO_BREAK. Text can't be broken into a new line. + * + * @param[in] text Vector of UTF-32 characters. + * @param[out] lineBreakInfo The line break info + */ +void SetLineBreakInfo( const Vector& text, + Vector& lineBreakInfo ); + +/** + * Replaces line break info. + * + * @pre The @p model needs to have a text set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ReplaceLineBreakInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +/** + * Sets word break info. + * + * - 0 is a WORD_BREAK. Text can be broken into a new word. + * - 1 is a WORD_NO_BREAK. Text can't be broken into a new word. + * + * @param[in] text Vector of UTF-32 characters. + * @param[out] wordBreakInfo The word break info. + */ +void SetWordBreakInfo( const Vector& text, + Vector& wordBreakInfo ); + +/** + * Replaces word break info. + * + * @pre The @p model needs to have a text set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in,out] model The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ReplaceWordBreakInfo( LogicalModel& model, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_SEGMENTATION_H__ diff --git a/dali-toolkit/internal/text/shaper.cpp b/dali-toolkit/internal/text/shaper.cpp new file mode 100644 index 0000000..8e2eed1 --- /dev/null +++ b/dali-toolkit/internal/text/shaper.cpp @@ -0,0 +1,240 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +CharacterIndex min( CharacterIndex index0, + CharacterIndex index1 ) +{ + return ( index0 < index1 ) ? index0 : index1; +} + +void ShapeText( const Vector& text, + const Vector& lineBreakInfo, + const Vector& scripts, + const Vector& fonts, + Vector& glyphs, + Vector& glyphToCharacterMap, + Vector& charactersPerGlyph ) +{ + const Length numberOfCharacters = text.Count(); + + if( 0u == numberOfCharacters ) + { + // Nothing to do if there are no characters. + return; + } + +#ifdef DEBUG_ENABLED + const Length numberOfFontRuns = fonts.Count(); + const Length numberOfScriptRuns = scripts.Count(); +#endif + + DALI_ASSERT_DEBUG( ( 0u != numberOfFontRuns ) && + ( numberOfCharacters == fonts[numberOfFontRuns - 1u].characterRun.characterIndex + fonts[numberOfFontRuns - 1u].characterRun.numberOfCharacters ) && + "Toolkit::Text::ShapeText. All characters must have a font set." ); + + DALI_ASSERT_DEBUG( ( 0u != numberOfScriptRuns ) && + ( numberOfCharacters == scripts[numberOfScriptRuns - 1u].characterRun.characterIndex + scripts[numberOfScriptRuns - 1u].characterRun.numberOfCharacters ) && + "Toolkit::Text::ShapeText. All characters must have a script set." ); + + // The text needs to be split in chunks of consecutive characters. + // Each chunk must contain characters with the same font id and script set. + // A chunk of consecutive characters must not contain a LINE_MUST_BREAK, if there is one a new chunk have to be created. + + TextAbstraction::Shaping shaping = TextAbstraction::Shaping::Get(); + + // To shape the text a font and an script is needed. + Vector::ConstIterator fontRunIt = fonts.Begin(); + Vector::ConstIterator scriptRunIt = scripts.Begin(); + + // Index to the the next one to be shaped. Is pointing the character after the last one it was shaped. + CharacterIndex previousIndex = 0u; + + // The current font id and script used to shape the text. + FontId currentFontId = 0u; + Script currentScript = TextAbstraction::UNKNOWN; + + // Reserve some space to allocate the glyphs and the glyph to character map. + // There is no way to know the number of glyphs before shaping the text. + // To avoid reallocations it's reserved space for a slightly biger number of glyphs than the number of characters. + + Length numberOfGlyphsReserved = static_cast( numberOfCharacters * 1.3f ); + glyphs.Resize( numberOfGlyphsReserved ); + glyphToCharacterMap.Resize( numberOfGlyphsReserved ); + + // The actual number of glyphs. + Length totalNumberOfGlyphs = 0u; + + const Character* textBuffer = text.Begin(); + const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + GlyphInfo* glyphsBuffer = glyphs.Begin(); + CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + + // Traverse the characters and shape the text. + for( previousIndex = 0; previousIndex < numberOfCharacters; ) + { + // Get the font id and the script. + const FontRun& fontRun = *fontRunIt; + const ScriptRun& scriptRun = *scriptRunIt; + + currentFontId = fontRun.fontId; + currentScript = scriptRun.script; + + // Get the min index to the last character of both runs. + CharacterIndex currentIndex = min( fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters, + scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ); + + // Check if there is a line must break. + bool mustBreak = false; + for( CharacterIndex index = previousIndex; index < currentIndex; ++index ) + { + mustBreak = TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ); + if( mustBreak ) + { + currentIndex = index; + break; + } + } + + // Check if the current index is a new paragraph character. + // A \n is going to be shaped in order to not to mess the conversion tables. + // After the \n character is shaped, the glyph is going to be reset to its + // default in order to not to get any metric or font index for it. + const bool isNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + currentIndex ) ); + + // The last character is always a must-break even if it's not a \n. + Length numberOfCharactersToShape = currentIndex - previousIndex; + if( mustBreak ) + { + // Add one more character to shape. + ++numberOfCharactersToShape; + } + + // Shape the text for the current chunk. + const Length numberOfGlyphs = shaping.Shape( textBuffer + previousIndex, + numberOfCharactersToShape, + currentFontId, + currentScript ); + + const Length glyphIndex = totalNumberOfGlyphs; + totalNumberOfGlyphs += numberOfGlyphs; + + if( totalNumberOfGlyphs > numberOfGlyphsReserved ) + { + // Resize the vectors to get enough space. + numberOfGlyphsReserved = static_cast( totalNumberOfGlyphs * 1.3f ); + glyphs.Resize( numberOfGlyphsReserved ); + glyphToCharacterMap.Resize( numberOfGlyphsReserved ); + + // Iterators are not valid anymore, set them again. + glyphsBuffer = glyphs.Begin(); + glyphToCharacterMapBuffer = glyphToCharacterMap.Begin(); + } + + // Retrieve the glyphs and the glyph to character conversion map. + shaping.GetGlyphs( glyphsBuffer + glyphIndex, + glyphToCharacterMapBuffer + glyphIndex ); + + if( isNewParagraph ) + { + // TODO : This is a work around to avoid drawing a square in the + // place of a new line character. + + // If the last character is a \n, it resets the glyph to the default + // to avoid getting any metric for it. + GlyphInfo& glyph = *( glyphsBuffer + glyphIndex + ( numberOfGlyphs - 1u ) ); + + glyph = GlyphInfo(); + } + + // Update indices. + if( 0u != glyphIndex ) + { + for( Length index = glyphIndex; index < glyphIndex + numberOfGlyphs; ++index ) + { + CharacterIndex& characterIndex = *( glyphToCharacterMapBuffer + index ); + characterIndex += previousIndex; + } + } + + // Update the iterators to get the next font or script run. + if( currentIndex == fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters ) + { + ++fontRunIt; + } + if( currentIndex == scriptRun.characterRun.characterIndex + scriptRun.characterRun.numberOfCharacters ) + { + ++scriptRunIt; + } + + // Update the previous index. Jumps the \n if needed. + previousIndex = mustBreak ? currentIndex + 1u : currentIndex; + } + + // Add the number of characters per glyph. + charactersPerGlyph.Reserve( totalNumberOfGlyphs ); + previousIndex = 0u; + for( Length index = 1u; index < totalNumberOfGlyphs; ++index ) + { + const CharacterIndex characterIndex = *( glyphToCharacterMapBuffer + index ); + + charactersPerGlyph.PushBack( characterIndex - previousIndex ); + + previousIndex = characterIndex; + } + + charactersPerGlyph.PushBack( numberOfCharacters - previousIndex ); + + // Resize the vectors to set the right number of items. + glyphs.Resize( totalNumberOfGlyphs ); + glyphToCharacterMap.Resize( totalNumberOfGlyphs ); +} + +void ShapeText( const LogicalModel& logicalModel, + VisualModel& visualModel, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ) +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/shaper.h b/dali-toolkit/internal/text/shaper.h new file mode 100644 index 0000000..d423cc5 --- /dev/null +++ b/dali-toolkit/internal/text/shaper.h @@ -0,0 +1,88 @@ +#ifndef __DALI_TOOLKIT_TEXT_SHAPER_H__ +#define __DALI_TOOLKIT_TEXT_SHAPER_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 + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class LogicalModel; +class VisualModel; + +/** + * Shapes the whole text. + * + * @param[in] text Vector of UTF-32 characters. + * @param[in] lineBreakInfo The line break info. + * @param[in] scripts Vector containing the script runs for the whole text. + * @param[in] fonts Vector with validated fonts. + * @param[out] glyphs Vector of glyphs in the visual order. + * @param[out] glyphToCharacterMap Vector containing the first character in the logical model that each glyph relates to. + * @param[out] charactersPerGlyph Vector containing the number of characters per glyph. + */ +void ShapeText( const Vector& text, + const Vector& lineBreakInfo, + const Vector& scripts, + const Vector& fonts, + Vector& glyphs, + Vector& glyphToCharacterMap, + Vector& charactersPerGlyph ); + +/** + * Replaces the shape info of the given range of characters. + * + * @pre The @p model needs to have a text set. + * @pre The @p model needs to have the scripts set. + * @pre The @p model needs to have the fonts set. + * @pre The @p model needs to have the bidirectional info set. + * + * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. + * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. + * + * @param[in] logicalModel The text's logical model. + * @param[in,out] visualModel The text's logical model. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharactersToRemove The number of characters removed from the text. + * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. + */ +void ShapeText( const LogicalModel& logicalModel, + VisualModel& visualModel, + CharacterIndex characterIndex, + Length numberOfCharactersToRemove, + Length numberOfCharactersToInsert ); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_SHAPER_H__ diff --git a/dali-toolkit/internal/text/text-control-interface.cpp b/dali-toolkit/internal/text/text-control-interface.cpp new file mode 100644 index 0000000..8ac77d1 --- /dev/null +++ b/dali-toolkit/internal/text/text-control-interface.cpp @@ -0,0 +1,42 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +ControlInterface::ControlInterface() +{ +} + +ControlInterface::~ControlInterface() +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-control-interface.h b/dali-toolkit/internal/text/text-control-interface.h new file mode 100644 index 0000000..3eb26b6 --- /dev/null +++ b/dali-toolkit/internal/text/text-control-interface.h @@ -0,0 +1,59 @@ +#ifndef __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__ +#define __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_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. + * + */ + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief An interface that the Text::Controller uses to request a text relayout. + */ +class ControlInterface +{ +public: + + /** + * @brief Constructor. + */ + ControlInterface(); + + /** + * @brief Virtual destructor. + */ + virtual ~ControlInterface(); + + /** + * @brief Called to request a text relayout. + */ + virtual void RequestTextRelayout() = 0; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__ diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp new file mode 100644 index 0000000..705b44b --- /dev/null +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -0,0 +1,2148 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::vector; + +namespace +{ + +const float MAX_FLOAT = std::numeric_limits::max(); + +enum ModifyType +{ + REPLACE_TEXT, ///< Replace the entire text + INSERT_TEXT, ///< Insert characters at the current cursor position + DELETE_TEXT ///< Delete a character at the current cursor position +}; + +struct ModifyEvent +{ + ModifyType type; + std::string text; +}; + +const std::string EMPTY_STRING(""); + +} // namespace + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct Controller::FontDefaults +{ + FontDefaults() + : mDefaultPointSize(0.0f), + mFontId(0u) + { + } + + FontId GetFontId( TextAbstraction::FontClient& fontClient ) + { + if( !mFontId ) + { + Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64; + mFontId = fontClient.GetFontId( mDefaultFontFamily, mDefaultFontStyle, pointSize ); + } + + return mFontId; + } + + std::string mDefaultFontFamily; + std::string mDefaultFontStyle; + float mDefaultPointSize; + FontId mFontId; +}; + +struct Controller::TextInput +{ + // Used to queue input events until DoRelayout() + enum EventType + { + KEYBOARD_FOCUS_GAIN_EVENT, + KEYBOARD_FOCUS_LOST_EVENT, + CURSOR_KEY_EVENT, + TAP_EVENT, + PAN_EVENT, + GRAB_HANDLE_EVENT + }; + + union Param + { + int mInt; + unsigned int mUint; + float mFloat; + }; + + struct Event + { + Event( EventType eventType ) + : type( eventType ) + { + p1.mInt = 0; + p2.mInt = 0; + } + + EventType type; + Param p1; + Param p2; + Param p3; + }; + + struct CursorInfo + { + CursorInfo() + : primaryPosition(), + secondaryPosition(), + lineHeight( 0.f ), + primaryCursorHeight( 0.f ), + secondaryCursorHeight( 0.f ), + isSecondaryCursor( false ) + {} + + ~CursorInfo() + {} + + Vector2 primaryPosition; ///< The primary cursor's position. + Vector2 secondaryPosition; ///< The secondary cursor's position. + float lineHeight; ///< The height of the line where the cursor is placed. + float primaryCursorHeight; ///< The primary cursor's height. + float secondaryCursorHeight; ///< The secondary cursor's height. + bool isSecondaryCursor; ///< Whether the secondary cursor is valid. + }; + + /** + * @brief Some characters can be shaped in more than one glyph. + * This struct is used to retrieve metrics from these group of glyphs. + */ + struct GlyphMetrics + { + GlyphMetrics() + : fontHeight( 0.f ), + advance( 0.f ), + ascender( 0.f ), + xBearing( 0.f ) + {} + + ~GlyphMetrics() + {} + + float fontHeight; ///< The font's height of that glyphs. + float advance; ///< The sum of all the advances of all the glyphs. + float ascender; ///< The font's ascender. + float xBearing; ///< The x bearing of the first glyph. + }; + + enum State + { + INACTIVE, + SELECTING, + EDITING, + EDITING_WITH_POPUP + }; + + TextInput( LogicalModelPtr logicalModel, + VisualModelPtr visualModel, + DecoratorPtr decorator, + FontDefaults* fontDefaults, + TextAbstraction::FontClient& fontClient ) + : mLogicalModel( logicalModel ), + mVisualModel( visualModel ), + mDecorator( decorator ), + mFontDefaults( fontDefaults ), + mFontClient( fontClient ), + mState( INACTIVE ), + mPrimaryCursorPosition( 0u ), + mSecondaryCursorPosition( 0u ), + mDecoratorUpdated( false ), + mCursorBlinkEnabled( true ), + mGrabHandleEnabled( true ), + mGrabHandlePopupEnabled( true ), + mSelectionEnabled( true ), + mHorizontalScrollingEnabled( true ), + mVerticalScrollingEnabled( false ), + mUpdateCursorPosition( false ) + {} + + /** + * @brief Helper to move the cursor, grab handle etc. + */ + bool ProcessInputEvents( const Vector2& controlSize, + const Vector2& alignmentOffset ) + { + mDecoratorUpdated = false; + + if( mDecorator ) + { + for( vector::iterator iter = mEventQueue.begin(); iter != mEventQueue.end(); ++iter ) + { + switch( iter->type ) + { + case KEYBOARD_FOCUS_GAIN_EVENT: + { + OnKeyboardFocus( true ); + break; + } + case KEYBOARD_FOCUS_LOST_EVENT: + { + OnKeyboardFocus( false ); + break; + } + case CURSOR_KEY_EVENT: + { + OnCursorKeyEvent( *iter ); + break; + } + case TAP_EVENT: + { + OnTapEvent( *iter, alignmentOffset ); + break; + } + case PAN_EVENT: + { + OnPanEvent( *iter, controlSize, alignmentOffset ); + break; + } + case GRAB_HANDLE_EVENT: + { + OnGrabHandleEvent( *iter ); + break; + } + } + } + } + + // The cursor must also be repositioned after inserts into the model + if( mUpdateCursorPosition ) + { + UpdateCursorPosition(); + mUpdateCursorPosition = false; + } + + mEventQueue.clear(); + + return mDecoratorUpdated; + } + + void OnKeyboardFocus( bool hasFocus ) + { + if( !hasFocus ) + { + ChangeState( INACTIVE ); + } + else + { + ChangeState( EDITING ); + } + } + + void OnCursorKeyEvent( const Event& event ) + { + int keyCode = event.p1.mInt; + + if( Dali::DALI_KEY_CURSOR_LEFT == keyCode ) + { + if( mPrimaryCursorPosition > 0u ) + { + mPrimaryCursorPosition = CalculateNewCursorIndex( mPrimaryCursorPosition - 1u ); + } + } + else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode ) + { + if( mLogicalModel->GetNumberOfCharacters() > mPrimaryCursorPosition ) + { + mPrimaryCursorPosition = CalculateNewCursorIndex( mPrimaryCursorPosition ); + } + } + else if( Dali::DALI_KEY_CURSOR_UP == keyCode ) + { + // TODO + } + else if( Dali::DALI_KEY_CURSOR_DOWN == keyCode ) + { + // TODO + } + + UpdateCursorPosition(); + } + + void HandleCursorKey( int keyCode ) + { + // TODO + } + + void OnTapEvent( const Event& event, + const Vector2& alignmentOffset ) + { + unsigned int tapCount = event.p1.mUint; + + if( 1u == tapCount ) + { + ChangeState( EDITING ); + + float xPosition = event.p2.mFloat - alignmentOffset.x; + float yPosition = event.p3.mFloat - alignmentOffset.y; + + mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, + yPosition ); + + UpdateCursorPosition(); + } + else if( mSelectionEnabled && + 2u == tapCount ) + { + ChangeState( SELECTING ); + + RepositionSelectionHandles( event.p2.mFloat, event.p3.mFloat ); + } + } + + void OnPanEvent( const Event& event, + const Vector2& controlSize, + const Vector2& alignmentOffset ) + { + int state = event.p1.mInt; + + if( Gesture::Started == state || + Gesture::Continuing == state ) + { + const Vector2& actualSize = mVisualModel->GetActualSize(); + + if( mHorizontalScrollingEnabled ) + { + const float displacementX = event.p2.mFloat; + mScrollPosition.x += displacementX; + + // Clamp between -space & 0 (and the text alignment). + const float contentWidth = actualSize.width; + if( contentWidth > controlSize.width ) + { + const float space = ( contentWidth - controlSize.width ) + alignmentOffset.x; + mScrollPosition.x = ( mScrollPosition.x < -space ) ? -space : mScrollPosition.x; + mScrollPosition.x = ( mScrollPosition.x > -alignmentOffset.x ) ? -alignmentOffset.x : mScrollPosition.x; + + mDecoratorUpdated = true; + } + else + { + mScrollPosition.x = 0.f; + } + } + + if( mVerticalScrollingEnabled ) + { + const float displacementY = event.p3.mFloat; + mScrollPosition.y += displacementY; + + // Clamp between -space & 0 (and the text alignment). + if( actualSize.height > controlSize.height ) + { + const float space = ( actualSize.height - controlSize.height ) + alignmentOffset.y; + mScrollPosition.y = ( mScrollPosition.y < -space ) ? -space : mScrollPosition.y; + mScrollPosition.y = ( mScrollPosition.y > -alignmentOffset.y ) ? -alignmentOffset.y : mScrollPosition.y; + + mDecoratorUpdated = true; + } + else + { + mScrollPosition.y = 0.f; + } + } + } + } + + void OnGrabHandleEvent( const Event& event ) + { + unsigned int state = event.p1.mUint; + + if( GRAB_HANDLE_PRESSED == state ) + { + float xPosition = event.p2.mFloat + mScrollPosition.x; + float yPosition = event.p3.mFloat + mScrollPosition.y; + + mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, + yPosition ); + + UpdateCursorPosition(); + + //mDecorator->HidePopup(); + ChangeState ( EDITING ); + } + else if ( mGrabHandlePopupEnabled && + GRAB_HANDLE_RELEASED == state ) + { + //mDecorator->ShowPopup(); + ChangeState ( EDITING_WITH_POPUP ); + mDecoratorUpdated = true; + } + } + + void RepositionSelectionHandles( float visualX, float visualY ) + { + // TODO - Find which word was selected + + const Vector& glyphs = mVisualModel->mGlyphs; + const Vector::SizeType glyphCount = glyphs.Count(); + + const Vector& positions = mVisualModel->mGlyphPositions; + const Vector::SizeType positionCount = positions.Count(); + + // Guard against glyphs which did not fit inside the layout + const Vector::SizeType count = (positionCount < glyphCount) ? positionCount : glyphCount; + + if( count ) + { + float primaryX = positions[0].x; + float secondaryX = positions[count-1].x + glyphs[count-1].width; + + // TODO - multi-line selection + const Vector& lines = mVisualModel->mLines; + float height = lines.Count() ? lines[0].ascender + -lines[0].descender : 0.0f; + + mDecorator->SetPosition( PRIMARY_SELECTION_HANDLE, primaryX, 0.0f, height ); + mDecorator->SetPosition( SECONDARY_SELECTION_HANDLE, secondaryX, 0.0f, height ); + + mDecorator->ClearHighlights(); + mDecorator->AddHighlight( primaryX, 0.0f, secondaryX, height ); + } + } + + void ChangeState( State newState ) + { + if( mState != newState ) + { + mState = newState; + + if( INACTIVE == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); + mDecorator->StopCursorBlink(); + mDecorator->SetGrabHandleActive( false ); + mDecorator->SetSelectionActive( false ); + mDecorator->SetPopupActive( false ); + mDecoratorUpdated = true; + } + else if ( SELECTING == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE ); + mDecorator->StopCursorBlink(); + mDecorator->SetGrabHandleActive( false ); + mDecorator->SetSelectionActive( true ); + mDecoratorUpdated = true; + } + else if( EDITING == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + if( mCursorBlinkEnabled ) + { + mDecorator->StartCursorBlink(); + } + if( mGrabHandleEnabled ) + { + mDecorator->SetGrabHandleActive( true ); + } + if( mGrabHandlePopupEnabled ) + { + mDecorator->SetPopupActive( false ); + } + mDecorator->SetSelectionActive( false ); + mDecoratorUpdated = true; + } + else if( EDITING_WITH_POPUP == mState ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + if( mCursorBlinkEnabled ) + { + mDecorator->StartCursorBlink(); + } + if( mGrabHandleEnabled ) + { + mDecorator->SetGrabHandleActive( true ); + } + if( mGrabHandlePopupEnabled ) + { + mDecorator->SetPopupActive( true ); + } + mDecorator->SetSelectionActive( false ); + mDecoratorUpdated = true; + } + } + } + + LineIndex GetClosestLine( float y ) const + { + float totalHeight = 0.f; + LineIndex lineIndex = 0u; + + const Vector& lines = mVisualModel->mLines; + for( LineIndex endLine = lines.Count(); + lineIndex < endLine; + ++lineIndex ) + { + const LineRun& lineRun = lines[lineIndex]; + totalHeight += lineRun.ascender + -lineRun.descender; + if( y < totalHeight ) + { + return lineIndex; + } + } + + return lineIndex-1; + } + + /** + * @brief Retrieves the cursor's logical position for a given touch point x,y + * + * @param[in] visualX The touch point x. + * @param[in] visualY The touch point y. + * + * @return The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character. + */ + CharacterIndex GetClosestCursorIndex( float visualX, + float visualY ) const + { + CharacterIndex logicalIndex = 0u; + + const Length numberOfGlyphs = mVisualModel->mGlyphs.Count(); + const Length numberOfLines = mVisualModel->mLines.Count(); + if( 0 == numberOfGlyphs || + 0 == numberOfLines ) + { + return logicalIndex; + } + + // Transform to visual model coords + visualX -= mScrollPosition.x; + visualY -= mScrollPosition.y; + + // Find which line is closest + const LineIndex lineIndex = GetClosestLine( visualY ); + const LineRun& line = mVisualModel->mLines[lineIndex]; + + // Get the positions of the glyphs. + const Vector& positions = mVisualModel->mGlyphPositions; + const Vector2* const positionsBuffer = positions.Begin(); + + // Get the visual to logical conversion tables. + const CharacterIndex* const visualToLogicalBuffer = ( 0u != mLogicalModel->mVisualToLogicalMap.Count() ) ? mLogicalModel->mVisualToLogicalMap.Begin() : NULL; + const CharacterIndex* const visualToLogicalCursorBuffer = mLogicalModel->mVisualToLogicalCursorMap.Begin(); + + // Get the character to glyph conversion table. + const GlyphIndex* const charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin(); + + // Get the glyphs per character table. + const Length* const glyphsPerCharacterBuffer = mVisualModel->mGlyphsPerCharacter.Begin(); + + // If the vector is void, there is no right to left characters. + const bool hasRightToLeftCharacters = NULL != visualToLogicalBuffer; + + const CharacterIndex startCharacter = line.characterRun.characterIndex; + const CharacterIndex endCharacter = line.characterRun.characterIndex + line.characterRun.numberOfCharacters; + DALI_ASSERT_DEBUG( endCharacter <= mLogicalModel->mText.Count() && "Invalid line info" ); + + // Whether there is a hit on a glyph. + bool matched = false; + + // Traverses glyphs in visual order. To do that use the visual to logical conversion table. + CharacterIndex visualIndex = startCharacter; + for( ; !matched && ( visualIndex < endCharacter ); ++visualIndex ) + { + // The character in logical order. + const CharacterIndex characterLogicalOrderIndex = hasRightToLeftCharacters ? *( visualToLogicalBuffer + visualIndex ) : visualIndex; + + // The first glyph for that character in logical order. + const GlyphIndex glyphLogicalOrderIndex = *( charactersToGlyphBuffer + characterLogicalOrderIndex ); + + // The number of glyphs for that character + const Length numberOfGlyphs = *( glyphsPerCharacterBuffer + characterLogicalOrderIndex ); + + // Get the metrics for the group of glyphs. + GlyphMetrics glyphMetrics; + GetGlyphsMetrics( glyphLogicalOrderIndex, + numberOfGlyphs, + glyphMetrics ); + + const Vector2& position = *( positionsBuffer + glyphLogicalOrderIndex ); + + const float glyphX = -glyphMetrics.xBearing + position.x + 0.5f * glyphMetrics.advance; + + if( visualX < glyphX ) + { + matched = true; + break; + } + } + + // Return the logical position of the cursor in characters. + + if( !matched ) + { + visualIndex = endCharacter; + } + + return hasRightToLeftCharacters ? *( visualToLogicalCursorBuffer + visualIndex ) : visualIndex; + } + + /** + * @brief Calculates the cursor's position for a given character index in the logical order. + * + * It retrieves as well the line's height and the cursor's height and + * if there is a valid alternative cursor, its position and height. + * + * @param[in] logical The logical cursor position (in characters). 0 is just before the first character, a value equal to the number of characters is just after the last character. + * @param[out] cursorInfo The line's height, the cursor's height, the cursor's position and whether there is an alternative cursor. + */ + void GetCursorPosition( CharacterIndex logical, + CursorInfo& cursorInfo ) const + { + // TODO: Check for multiline with \n, etc... + + // Check if the logical position is the first or the last one of the text. + const bool isFirstPosition = 0u == logical; + const bool isLastPosition = mLogicalModel->GetNumberOfCharacters() == logical; + + if( isFirstPosition && isLastPosition ) + { + // There is zero characters. Get the default font. + + FontId defaultFontId = 0u; + if( NULL == mFontDefaults ) + { + defaultFontId = mFontClient.GetFontId( EMPTY_STRING, + EMPTY_STRING ); + } + else + { + defaultFontId = mFontDefaults->GetFontId( mFontClient ); + } + + Text::FontMetrics fontMetrics; + mFontClient.GetFontMetrics( defaultFontId, fontMetrics ); + + cursorInfo.lineHeight = fontMetrics.ascender - fontMetrics.descender; + cursorInfo.primaryCursorHeight = cursorInfo.lineHeight; + + cursorInfo.primaryPosition.x = 0.f; + cursorInfo.primaryPosition.y = 0.f; + + // Nothing else to do. + return; + } + + // Get the previous logical index. + const CharacterIndex previousLogical = isFirstPosition ? 0u : logical - 1u; + + // Decrease the logical index if it's the last one. + if( isLastPosition ) + { + --logical; + } + + // Get the direction of the character and the previous one. + const CharacterDirection* const modelCharacterDirectionsBuffer = ( 0u != mLogicalModel->mCharacterDirections.Count() ) ? mLogicalModel->mCharacterDirections.Begin() : NULL; + + CharacterDirection isCurrentRightToLeft = false; + CharacterDirection isPreviousRightToLeft = false; + if( NULL != modelCharacterDirectionsBuffer ) // If modelCharacterDirectionsBuffer is NULL, it means the whole text is left to right. + { + isCurrentRightToLeft = *( modelCharacterDirectionsBuffer + logical ); + isPreviousRightToLeft = *( modelCharacterDirectionsBuffer + previousLogical ); + } + + // Get the line where the character is laid-out. + const LineRun* modelLines = mVisualModel->mLines.Begin(); + + const LineIndex lineIndex = mVisualModel->GetLineOfCharacter( logical ); + const LineRun& line = *( modelLines + lineIndex ); + + // Get the paragraph's direction. + const CharacterDirection isRightToLeftParagraph = line.direction; + + // Check whether there is an alternative position: + + cursorInfo.isSecondaryCursor = ( isCurrentRightToLeft != isPreviousRightToLeft ) || + ( isLastPosition && ( isRightToLeftParagraph != isCurrentRightToLeft ) ); + + // Set the line height. + cursorInfo.lineHeight = line.ascender + -line.descender; + + // Convert the cursor position into the glyph position. + CharacterIndex characterIndex = logical; + if( cursorInfo.isSecondaryCursor && + ( isRightToLeftParagraph != isCurrentRightToLeft ) ) + { + characterIndex = previousLogical; + } + + const GlyphIndex currentGlyphIndex = *( mVisualModel->mCharactersToGlyph.Begin() + characterIndex ); + const Length numberOfGlyphs = *( mVisualModel->mGlyphsPerCharacter.Begin() + characterIndex ); + const Length numberOfCharacters = *( mVisualModel->mCharactersPerGlyph.Begin() +currentGlyphIndex ); + + // Get the metrics for the group of glyphs. + GlyphMetrics glyphMetrics; + GetGlyphsMetrics( currentGlyphIndex, + numberOfGlyphs, + glyphMetrics ); + + float interGlyphAdvance = 0.f; + if( !isLastPosition && + ( numberOfCharacters > 1u ) ) + { + const CharacterIndex firstIndex = *( mVisualModel->mGlyphsToCharacters.Begin() + currentGlyphIndex ); + interGlyphAdvance = static_cast( characterIndex - firstIndex ) * glyphMetrics.advance / static_cast( numberOfCharacters ); + } + + // Get the glyph position and x bearing. + const Vector2& currentPosition = *( mVisualModel->mGlyphPositions.Begin() + currentGlyphIndex ); + + // Set the cursor's height. + cursorInfo.primaryCursorHeight = glyphMetrics.fontHeight; + + // Set the position. + cursorInfo.primaryPosition.x = -glyphMetrics.xBearing + currentPosition.x + ( isCurrentRightToLeft ? glyphMetrics.advance : interGlyphAdvance ); + cursorInfo.primaryPosition.y = line.ascender - glyphMetrics.ascender; + + if( isLastPosition ) + { + // The position of the cursor after the last character needs special + // care depending on its direction and the direction of the paragraph. + + if( cursorInfo.isSecondaryCursor ) + { + // Need to find the first character after the last character with the paragraph's direction. + // i.e l0 l1 l2 r0 r1 should find r0. + + // TODO: check for more than one line! + characterIndex = isRightToLeftParagraph ? line.characterRun.characterIndex : line.characterRun.characterIndex + line.characterRun.numberOfCharacters - 1u; + characterIndex = mLogicalModel->GetLogicalCharacterIndex( characterIndex ); + + const GlyphIndex glyphIndex = *( mVisualModel->mCharactersToGlyph.Begin() + characterIndex ); + const Length numberOfGlyphs = *( mVisualModel->mGlyphsPerCharacter.Begin() + characterIndex ); + + const Vector2& position = *( mVisualModel->mGlyphPositions.Begin() + glyphIndex ); + + // Get the metrics for the group of glyphs. + GlyphMetrics glyphMetrics; + GetGlyphsMetrics( glyphIndex, + numberOfGlyphs, + glyphMetrics ); + + cursorInfo.primaryPosition.x = -glyphMetrics.xBearing + position.x + ( isRightToLeftParagraph ? 0.f : glyphMetrics.advance ); + + cursorInfo.primaryPosition.y = line.ascender - glyphMetrics.ascender; + } + else + { + if( !isCurrentRightToLeft ) + { + cursorInfo.primaryPosition.x += glyphMetrics.advance; + } + else + { + cursorInfo.primaryPosition.x -= glyphMetrics.advance; + } + } + } + + // Set the alternative cursor position. + if( cursorInfo.isSecondaryCursor ) + { + // Convert the cursor position into the glyph position. + const CharacterIndex previousCharacterIndex = ( ( isRightToLeftParagraph != isCurrentRightToLeft ) ? logical : previousLogical ); + const GlyphIndex previousGlyphIndex = *( mVisualModel->mCharactersToGlyph.Begin() + previousCharacterIndex ); + const Length numberOfGlyphs = *( mVisualModel->mGlyphsPerCharacter.Begin() + previousCharacterIndex ); + + // Get the glyph position. + const Vector2& previousPosition = *( mVisualModel->mGlyphPositions.Begin() + previousGlyphIndex ); + + // Get the metrics for the group of glyphs. + GlyphMetrics glyphMetrics; + GetGlyphsMetrics( previousGlyphIndex, + numberOfGlyphs, + glyphMetrics ); + + // Set the cursor position and height. + cursorInfo.secondaryPosition.x = -glyphMetrics.xBearing + previousPosition.x + ( ( ( isLastPosition && !isCurrentRightToLeft ) || + ( !isLastPosition && isCurrentRightToLeft ) ) ? glyphMetrics.advance : 0.f ); + + cursorInfo.secondaryCursorHeight = 0.5f * glyphMetrics.fontHeight; + + cursorInfo.secondaryPosition.y = cursorInfo.lineHeight - cursorInfo.secondaryCursorHeight - line.descender - ( glyphMetrics.fontHeight - glyphMetrics.ascender ); + + // Update the primary cursor height as well. + cursorInfo.primaryCursorHeight *= 0.5f; + } + } + + /** + * @brief Get some glyph's metrics of a group of glyphs formed as a result of shaping one character. + * + * @param[in] glyphIndex The index to the first glyph. + * @param[in] numberOfGlyphs The number of glyphs. + * @param[out] glyphMetrics Some glyph metrics (font height, advance, ascender and x bearing). + */ + void GetGlyphsMetrics( GlyphIndex glyphIndex, + Length numberOfGlyphs, + GlyphMetrics& glyphMetrics ) const + { + const GlyphInfo* glyphsBuffer = mVisualModel->mGlyphs.Begin(); + + const GlyphInfo& firstGlyph = *( glyphsBuffer + glyphIndex ); + + Text::FontMetrics fontMetrics; + mFontClient.GetFontMetrics( firstGlyph.fontId, fontMetrics ); + + glyphMetrics.fontHeight = fontMetrics.height; + glyphMetrics.advance = firstGlyph.advance; + glyphMetrics.ascender = fontMetrics.ascender; + glyphMetrics.xBearing = firstGlyph.xBearing; + + for( unsigned int i = 1u; i < numberOfGlyphs; ++i ) + { + const GlyphInfo& glyphInfo = *( glyphsBuffer + glyphIndex + i ); + + glyphMetrics.advance += glyphInfo.advance; + } + } + + /** + * @brief Calculates the new cursor index. + * + * It takes into account that in some scripts multiple characters can form a glyph and all of them + * need to be jumped with one key event. + * + * @param[in] index The initial new index. + * + * @return The new cursor index. + */ + CharacterIndex CalculateNewCursorIndex( CharacterIndex index ) const + { + CharacterIndex cursorIndex = mPrimaryCursorPosition; + + const Script script = mLogicalModel->GetScript( index ); + const GlyphIndex* charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin(); + const Length* charactersPerGlyphBuffer = mVisualModel->mCharactersPerGlyph.Begin(); + + Length numberOfCharacters = 0u; + if( TextAbstraction::LATIN == script ) + { + // Prevents to jump the whole Latin ligatures like fi, ff, ... + numberOfCharacters = 1u; + } + else + { + GlyphIndex glyphIndex = *( charactersToGlyphBuffer + index ); + numberOfCharacters = *( charactersPerGlyphBuffer + glyphIndex ); + + while( 0u == numberOfCharacters ) + { + numberOfCharacters = *( charactersPerGlyphBuffer + glyphIndex ); + ++glyphIndex; + } + } + + if( index < mPrimaryCursorPosition ) + { + cursorIndex -= numberOfCharacters; + } + else + { + cursorIndex += numberOfCharacters; + } + + return cursorIndex; + } + + void UpdateCursorPosition() + { + CursorInfo cursorInfo; + + GetCursorPosition( mPrimaryCursorPosition, + cursorInfo ); + + mDecorator->SetPosition( PRIMARY_CURSOR, + cursorInfo.primaryPosition.x, + cursorInfo.primaryPosition.y, + cursorInfo.primaryCursorHeight, + cursorInfo.lineHeight ); + + if( cursorInfo.isSecondaryCursor ) + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_BOTH ); + mDecorator->SetPosition( SECONDARY_CURSOR, + cursorInfo.secondaryPosition.x, + cursorInfo.secondaryPosition.y, + cursorInfo.secondaryCursorHeight, + cursorInfo.lineHeight ); + } + else + { + mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY ); + } + + mUpdateCursorPosition = false; + mDecoratorUpdated = true; + } + + LogicalModelPtr mLogicalModel; + VisualModelPtr mVisualModel; + DecoratorPtr mDecorator; + FontDefaults* mFontDefaults; + TextAbstraction::FontClient& mFontClient; + std::string mPlaceholderText; + + /** + * This is used to delay handling events until after the model has been updated. + * The number of updates to the model is minimized to improve performance. + */ + vector mEventQueue; ///< The queue of touch events etc. + + State mState; ///< Selection mode, edit mode etc. + + CharacterIndex mPrimaryCursorPosition; ///< Index into logical model for primary cursor + CharacterIndex mSecondaryCursorPosition; ///< Index into logical model for secondary cursor + + /** + * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control. + * Typically this will have a negative value with scrolling occurs. + */ + Vector2 mScrollPosition; ///< The text is offset by this position when scrolling. + + bool mDecoratorUpdated : 1; ///< True if the decorator was updated during event processing + bool mCursorBlinkEnabled : 1; ///< True if cursor should blink when active + bool mGrabHandleEnabled : 1; ///< True if grab handle is enabled + bool mGrabHandlePopupEnabled : 1; ///< True if the grab handle popu-up should be shown + bool mSelectionEnabled : 1; ///< True if selection handles, highlight etc. are enabled + bool mHorizontalScrollingEnabled : 1; ///< True if horizontal scrolling is enabled + bool mVerticalScrollingEnabled : 1; ///< True if vertical scrolling is enabled + bool mUpdateCursorPosition : 1; ///< True if the visual position of the cursor must be recalculated +}; + +struct Controller::Impl +{ + Impl( ControlInterface& controlInterface ) + : mControlInterface( controlInterface ), + mLogicalModel(), + mVisualModel(), + mFontDefaults( NULL ), + mTextInput( NULL ), + mFontClient(), + mView(), + mLayoutEngine(), + mModifyEvents(), + mControlSize(), + mAlignmentOffset(), + mOperationsPending( NO_OPERATION ), + mRecalculateNaturalSize( true ) + { + mLogicalModel = LogicalModel::New(); + mVisualModel = VisualModel::New(); + + mFontClient = TextAbstraction::FontClient::Get(); + + mView.SetVisualModel( mVisualModel ); + + // Set the text properties to default + mVisualModel->SetTextColor( Color::WHITE ); + mVisualModel->SetShadowOffset( Vector2::ZERO ); + mVisualModel->SetShadowColor( Vector4::ZERO ); + mVisualModel->SetUnderlineEnabled( false ); + mVisualModel->SetUnderlineHeight( 0.0f ); + } + + ~Impl() + { + delete mTextInput; + } + + ControlInterface& mControlInterface; ///< Reference to the text controller. + LogicalModelPtr mLogicalModel; ///< Pointer to the logical model. + VisualModelPtr mVisualModel; ///< Pointer to the visual model. + FontDefaults* mFontDefaults; ///< Avoid allocating this when the user does not specify a font. + Controller::TextInput* mTextInput; ///< Avoid allocating everything for text input until EnableTextInput(). + TextAbstraction::FontClient mFontClient; ///< Handle to the font client. + View mView; ///< The view interface to the rendering back-end. + LayoutEngine mLayoutEngine; ///< The layout engine. + std::vector mModifyEvents; ///< Temporary stores the text set until the next relayout. + Size mControlSize; ///< The size of the control. + 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. + bool mRecalculateNaturalSize:1; ///< Whether the natural size needs to be recalculated. +}; + +ControllerPtr Controller::New( ControlInterface& controlInterface ) +{ + return ControllerPtr( new Controller( controlInterface ) ); +} + +void Controller::SetText( const std::string& text ) +{ + // Cancel previously queued inserts etc. + mImpl->mModifyEvents.clear(); + + // Keep until size negotiation + ModifyEvent event; + event.type = REPLACE_TEXT; + event.text = text; + mImpl->mModifyEvents.push_back( event ); + + if( mImpl->mTextInput ) + { + // Cancel previously queued events + mImpl->mTextInput->mEventQueue.clear(); + + // TODO - Hide selection decorations + } +} + +void Controller::GetText( std::string& text ) const +{ + if( !mImpl->mModifyEvents.empty() && + REPLACE_TEXT == mImpl->mModifyEvents[0].type ) + { + text = mImpl->mModifyEvents[0].text; + } + else + { + // TODO - Convert from UTF-32 + } +} + +void Controller::SetPlaceholderText( const std::string& text ) +{ + if( !mImpl->mTextInput ) + { + mImpl->mTextInput->mPlaceholderText = text; + } +} + +void Controller::GetPlaceholderText( std::string& text ) const +{ + if( !mImpl->mTextInput ) + { + text = mImpl->mTextInput->mPlaceholderText; + } +} + +void Controller::SetDefaultFontFamily( const std::string& defaultFontFamily ) +{ + if( !mImpl->mFontDefaults ) + { + mImpl->mFontDefaults = new Controller::FontDefaults(); + } + + mImpl->mFontDefaults->mDefaultFontFamily = defaultFontFamily; + mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + RequestRelayout(); +} + +const std::string& Controller::GetDefaultFontFamily() const +{ + if( mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->mDefaultFontFamily; + } + + return EMPTY_STRING; +} + +void Controller::SetDefaultFontStyle( const std::string& defaultFontStyle ) +{ + if( !mImpl->mFontDefaults ) + { + mImpl->mFontDefaults = new Controller::FontDefaults(); + } + + mImpl->mFontDefaults->mDefaultFontStyle = defaultFontStyle; + mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + RequestRelayout(); +} + +const std::string& Controller::GetDefaultFontStyle() const +{ + if( mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->mDefaultFontStyle; + } + + return EMPTY_STRING; +} + +void Controller::SetDefaultPointSize( float pointSize ) +{ + if( !mImpl->mFontDefaults ) + { + mImpl->mFontDefaults = new Controller::FontDefaults(); + } + + mImpl->mFontDefaults->mDefaultPointSize = pointSize; + mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID + mImpl->mOperationsPending = ALL_OPERATIONS; + mImpl->mRecalculateNaturalSize = true; + + // Clear the font-specific data + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + RequestRelayout(); +} + +float Controller::GetDefaultPointSize() const +{ + if( mImpl->mFontDefaults ) + { + return mImpl->mFontDefaults->mDefaultPointSize; + } + + return 0.0f; +} + +void Controller::GetDefaultFonts( Vector& fonts, Length numberOfCharacters ) const +{ + if( mImpl->mFontDefaults ) + { + FontRun fontRun; + fontRun.characterRun.characterIndex = 0; + fontRun.characterRun.numberOfCharacters = numberOfCharacters; + fontRun.fontId = mImpl->mFontDefaults->GetFontId( mImpl->mFontClient ); + fontRun.isDefault = true; + + fonts.PushBack( fontRun ); + } +} + +const Vector4& Controller::GetTextColor() const +{ + return mImpl->mVisualModel->GetTextColor(); +} + +const Vector2& Controller::GetShadowOffset() const +{ + return mImpl->mVisualModel->GetShadowOffset(); +} + +const Vector4& Controller::GetShadowColor() const +{ + return mImpl->mVisualModel->GetShadowColor(); +} + +const Vector4& Controller::GetUnderlineColor() const +{ + return mImpl->mVisualModel->GetUnderlineColor(); +} + +bool Controller::IsUnderlineEnabled() const +{ + return mImpl->mVisualModel->IsUnderlineEnabled(); +} + +float Controller::GetUnderlineHeight() const +{ + return mImpl->mVisualModel->GetUnderlineHeight(); +} + +void Controller::SetTextColor( const Vector4& textColor ) +{ + mImpl->mVisualModel->SetTextColor( textColor ); +} + +void Controller::SetShadowOffset( const Vector2& shadowOffset ) +{ + mImpl->mVisualModel->SetShadowOffset( shadowOffset ); +} + +void Controller::SetShadowColor( const Vector4& shadowColor ) +{ + mImpl->mVisualModel->SetShadowColor( shadowColor ); +} + +void Controller::SetUnderlineColor( const Vector4& color ) +{ + mImpl->mVisualModel->SetUnderlineColor( color ); +} + +void Controller::SetUnderlineEnabled( bool enabled ) +{ + mImpl->mVisualModel->SetUnderlineEnabled( enabled ); +} + +void Controller::SetUnderlineHeight( float height ) +{ + mImpl->mVisualModel->SetUnderlineHeight( height ); +} + +void Controller::EnableTextInput( DecoratorPtr decorator ) +{ + if( !mImpl->mTextInput ) + { + mImpl->mTextInput = new TextInput( mImpl->mLogicalModel, + mImpl->mVisualModel, + decorator, + mImpl->mFontDefaults, + mImpl->mFontClient ); + } +} + +void Controller::SetEnableCursorBlink( bool enable ) +{ + DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "TextInput disabled" ); + + if( mImpl->mTextInput ) + { + mImpl->mTextInput->mCursorBlinkEnabled = enable; + + if( !enable && + mImpl->mTextInput->mDecorator ) + { + mImpl->mTextInput->mDecorator->StopCursorBlink(); + } + } +} + +bool Controller::GetEnableCursorBlink() const +{ + if( mImpl->mTextInput ) + { + return mImpl->mTextInput->mCursorBlinkEnabled; + } + + return false; +} + +const Vector2& Controller::GetScrollPosition() const +{ + if( mImpl->mTextInput ) + { + return mImpl->mTextInput->mScrollPosition; + } + + return Vector2::ZERO; +} + +const Vector2& Controller::GetAlignmentOffset() const +{ + return mImpl->mAlignmentOffset; +} + +Vector3 Controller::GetNaturalSize() +{ + Vector3 naturalSize; + + // Make sure the model is up-to-date before layouting + ProcessModifyEvents(); + + if( mImpl->mRecalculateNaturalSize ) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + GET_WORD_BREAKS | + BIDI_INFO | + SHAPE_TEXT | + GET_GLYPH_METRICS ); + // Make sure the model is up-to-date before layouting + UpdateModel( onlyOnceOperations ); + + // Operations that need to be done if the size changes. + const OperationsMask sizeOperations = static_cast( LAYOUT | + ALIGN | + REORDER ); + + DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ), + static_cast( onlyOnceOperations | + sizeOperations ), + naturalSize.GetVectorXY() ); + + // Do not do again the only once operations. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); + + // Do the size related operations again. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); + + // Stores the natural size to avoid recalculate it again + // unless the text/style changes. + mImpl->mVisualModel->SetNaturalSize( naturalSize.GetVectorXY() ); + + mImpl->mRecalculateNaturalSize = false; + } + else + { + naturalSize = mImpl->mVisualModel->GetNaturalSize(); + } + + return naturalSize; +} + +float Controller::GetHeightForWidth( float width ) +{ + // Make sure the model is up-to-date before layouting + ProcessModifyEvents(); + + Size layoutSize; + if( width != mImpl->mControlSize.width ) + { + // Operations that can be done only once until the text changes. + const OperationsMask onlyOnceOperations = static_cast( CONVERT_TO_UTF32 | + GET_SCRIPTS | + VALIDATE_FONTS | + GET_LINE_BREAKS | + GET_WORD_BREAKS | + BIDI_INFO | + SHAPE_TEXT | + GET_GLYPH_METRICS ); + // Make sure the model is up-to-date before layouting + UpdateModel( onlyOnceOperations ); + + // Operations that need to be done if the size changes. + const OperationsMask sizeOperations = static_cast( LAYOUT | + ALIGN | + REORDER ); + + DoRelayout( Size( width, MAX_FLOAT ), + static_cast( onlyOnceOperations | + sizeOperations ), + layoutSize ); + + // Do not do again the only once operations. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending & ~onlyOnceOperations ); + + // Do the size related operations again. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | sizeOperations ); + } + else + { + layoutSize = mImpl->mVisualModel->GetActualSize(); + } + + return layoutSize.height; +} + +bool Controller::Relayout( const Size& size ) +{ + if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) + { + bool glyphsRemoved( false ); + if( 0u != mImpl->mVisualModel->GetNumberOfGlyphPositions() ) + { + mImpl->mVisualModel->SetGlyphPositions( NULL, 0u ); + glyphsRemoved = true; + } + + // Not worth to relayout if width or height is equal to zero. + return glyphsRemoved; + } + + if( size != mImpl->mControlSize ) + { + // Operations that need to be done if the size changes. + mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | + LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); + + mImpl->mControlSize = size; + } + + // Make sure the model is up-to-date before layouting + ProcessModifyEvents(); + UpdateModel( mImpl->mOperationsPending ); + + Size layoutSize; + bool updated = DoRelayout( mImpl->mControlSize, + mImpl->mOperationsPending, + layoutSize ); + + // Do not re-do any operation until something changes. + mImpl->mOperationsPending = NO_OPERATION; + + // After doing the text layout, the alignment offset to place the actor in the desired position can be calculated. + CalculateTextAlignment( size ); + + if( mImpl->mTextInput ) + { + // Move the cursor, grab handle etc. + updated = mImpl->mTextInput->ProcessInputEvents( mImpl->mControlSize, mImpl->mAlignmentOffset ) || updated; + } + + return updated; +} + +void Controller::ProcessModifyEvents() +{ + std::vector& events = mImpl->mModifyEvents; + + for( unsigned int i=0; imLogicalModel->mText.Clear(); + mImpl->mLogicalModel->mScriptRuns.Clear(); + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mLogicalModel->mLineBreakInfo.Clear(); + mImpl->mLogicalModel->mWordBreakInfo.Clear(); + mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear(); + mImpl->mLogicalModel->mCharacterDirections.Clear(); + mImpl->mLogicalModel->mBidirectionalLineInfo.Clear(); + mImpl->mLogicalModel->mLogicalToVisualMap.Clear(); + mImpl->mLogicalModel->mVisualToLogicalMap.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + // Convert text into UTF-32 + Vector& utf32Characters = mImpl->mLogicalModel->mText; + utf32Characters.Resize( text.size() ); + + // This is a bit horrible but std::string returns a (signed) char* + const uint8_t* utf8 = reinterpret_cast( text.c_str() ); + + // Transform a text array encoded in utf8 into an array encoded in utf32. + // It returns the actual number of characters. + Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() ); + utf32Characters.Resize( characterCount ); + + // Reset the cursor position + if( mImpl->mTextInput ) + { + mImpl->mTextInput->mPrimaryCursorPosition = characterCount; + // TODO - handle secondary cursor + } + + // The natural size needs to be re-calculated. + mImpl->mRecalculateNaturalSize = true; + + // Apply modifications to the model + mImpl->mOperationsPending = ALL_OPERATIONS; + UpdateModel( ALL_OPERATIONS ); + mImpl->mOperationsPending = static_cast( LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); +} + +void Controller::InsertTextEvent( const std::string& text ) +{ + DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "Unexpected InsertTextEvent" ); + + // TODO - Optimize this + mImpl->mLogicalModel->mScriptRuns.Clear(); + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mLogicalModel->mLineBreakInfo.Clear(); + mImpl->mLogicalModel->mWordBreakInfo.Clear(); + mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear(); + mImpl->mLogicalModel->mCharacterDirections.Clear(); + mImpl->mLogicalModel->mBidirectionalLineInfo.Clear(); + mImpl->mLogicalModel->mLogicalToVisualMap.Clear(); + mImpl->mLogicalModel->mVisualToLogicalMap.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + // Convert text into UTF-32 + Vector utf32Characters; + utf32Characters.Resize( text.size() ); + + // This is a bit horrible but std::string returns a (signed) char* + const uint8_t* utf8 = reinterpret_cast( text.c_str() ); + + // Transform a text array encoded in utf8 into an array encoded in utf32. + // It returns the actual number of characters. + Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() ); + utf32Characters.Resize( characterCount ); + + // Insert at current cursor position + Vector& modifyText = mImpl->mLogicalModel->mText; + CharacterIndex& cursorIndex = mImpl->mTextInput->mPrimaryCursorPosition; + + if( cursorIndex < modifyText.Count() ) + { + modifyText.Insert( modifyText.Begin() + cursorIndex, utf32Characters.Begin(), utf32Characters.End() ); + } + else + { + modifyText.Insert( modifyText.End(), utf32Characters.Begin(), utf32Characters.End() ); + } + + // Advance the cursor position + ++cursorIndex; + + // The natural size needs to be re-calculated. + mImpl->mRecalculateNaturalSize = true; + + // Apply modifications to the model; TODO - Optimize this + mImpl->mOperationsPending = ALL_OPERATIONS; + UpdateModel( ALL_OPERATIONS ); + mImpl->mOperationsPending = static_cast( LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); + + // Queue a cursor reposition event; this must wait until after DoRelayout() + mImpl->mTextInput->mUpdateCursorPosition = true; +} + +void Controller::DeleteTextEvent() +{ + DALI_ASSERT_DEBUG( NULL != mImpl->mTextInput && "Unexpected InsertTextEvent" ); + + // TODO - Optimize this + mImpl->mLogicalModel->mScriptRuns.Clear(); + mImpl->mLogicalModel->mFontRuns.Clear(); + mImpl->mLogicalModel->mLineBreakInfo.Clear(); + mImpl->mLogicalModel->mWordBreakInfo.Clear(); + mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear(); + mImpl->mLogicalModel->mCharacterDirections.Clear(); + mImpl->mLogicalModel->mBidirectionalLineInfo.Clear(); + mImpl->mLogicalModel->mLogicalToVisualMap.Clear(); + mImpl->mLogicalModel->mVisualToLogicalMap.Clear(); + mImpl->mVisualModel->mGlyphs.Clear(); + mImpl->mVisualModel->mGlyphsToCharacters.Clear(); + mImpl->mVisualModel->mCharactersToGlyph.Clear(); + mImpl->mVisualModel->mCharactersPerGlyph.Clear(); + mImpl->mVisualModel->mGlyphsPerCharacter.Clear(); + mImpl->mVisualModel->mGlyphPositions.Clear(); + mImpl->mVisualModel->mLines.Clear(); + mImpl->mVisualModel->ClearCaches(); + + // Delte at current cursor position + Vector& modifyText = mImpl->mLogicalModel->mText; + CharacterIndex& cursorIndex = mImpl->mTextInput->mPrimaryCursorPosition; + + if( cursorIndex > 0 && + cursorIndex-1 < modifyText.Count() ) + { + modifyText.Remove( modifyText.Begin() + cursorIndex - 1 ); + + // Cursor position retreat + --cursorIndex; + } + + // The natural size needs to be re-calculated. + mImpl->mRecalculateNaturalSize = true; + + // Apply modifications to the model; TODO - Optimize this + mImpl->mOperationsPending = ALL_OPERATIONS; + UpdateModel( ALL_OPERATIONS ); + mImpl->mOperationsPending = static_cast( LAYOUT | + ALIGN | + UPDATE_ACTUAL_SIZE | + REORDER ); + + // Queue a cursor reposition event; this must wait until after DoRelayout() + mImpl->mTextInput->mUpdateCursorPosition = true; +} + +void Controller::UpdateModel( OperationsMask operationsRequired ) +{ + // Calculate the operations to be done. + const OperationsMask operations = static_cast( mImpl->mOperationsPending & operationsRequired ); + + Vector& utf32Characters = mImpl->mLogicalModel->mText; + + const Length numberOfCharacters = mImpl->mLogicalModel->GetNumberOfCharacters(); + + Vector& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo; + if( GET_LINE_BREAKS & operations ) + { + // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to + // calculate the bidirectional info for each 'paragraph'. + // It's also used to layout the text (where it should be a new line) or to shape the text (text in different lines + // is not shaped together). + lineBreakInfo.Resize( numberOfCharacters, TextAbstraction::LINE_NO_BREAK ); + + SetLineBreakInfo( utf32Characters, + lineBreakInfo ); + } + + Vector& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo; + if( GET_WORD_BREAKS & operations ) + { + // Retrieves the word break info. The word break info is used to layout the text (where to wrap the text in lines). + wordBreakInfo.Resize( numberOfCharacters, TextAbstraction::WORD_NO_BREAK ); + + SetWordBreakInfo( utf32Characters, + wordBreakInfo ); + } + + const bool getScripts = GET_SCRIPTS & operations; + const bool validateFonts = VALIDATE_FONTS & operations; + + Vector& scripts = mImpl->mLogicalModel->mScriptRuns; + Vector& validFonts = mImpl->mLogicalModel->mFontRuns; + + if( getScripts || validateFonts ) + { + // Validates the fonts assigned by the application or assigns default ones. + // It makes sure all the characters are going to be rendered by the correct font. + MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get(); + + if( getScripts ) + { + // Retrieves the scripts used in the text. + multilanguageSupport.SetScripts( utf32Characters, + lineBreakInfo, + scripts ); + } + + if( validateFonts ) + { + if( 0u == validFonts.Count() ) + { + // Copy the requested font defaults received via the property system. + // These may not be valid i.e. may not contain glyphs for the necessary scripts. + GetDefaultFonts( validFonts, numberOfCharacters ); + } + + // Validates the fonts. If there is a character with no assigned font it sets a default one. + // After this call, fonts are validated. + multilanguageSupport.ValidateFonts( utf32Characters, + scripts, + validFonts ); + } + } + + Vector mirroredUtf32Characters; + bool textMirrored = false; + if( BIDI_INFO & operations ) + { + // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's + // bidirectional info. + + Length numberOfParagraphs = 0u; + + const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + for( Length index = 0u; index < numberOfCharacters; ++index ) + { + if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) ) + { + ++numberOfParagraphs; + } + } + + Vector& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo; + bidirectionalInfo.Reserve( numberOfParagraphs ); + + // Calculates the bidirectional info for the whole paragraph if it contains right to left scripts. + SetBidirectionalInfo( utf32Characters, + scripts, + lineBreakInfo, + bidirectionalInfo ); + + if( 0u != bidirectionalInfo.Count() ) + { + // This paragraph has right to left text. Some characters may need to be mirrored. + // TODO: consider if the mirrored string can be stored as well. + + textMirrored = GetMirroredText( utf32Characters, mirroredUtf32Characters ); + + // Only set the character directions if there is right to left characters. + Vector& directions = mImpl->mLogicalModel->mCharacterDirections; + directions.Resize( numberOfCharacters ); + + GetCharactersDirection( bidirectionalInfo, + directions ); + } + else + { + // There is no right to left characters. Clear the directions vector. + mImpl->mLogicalModel->mCharacterDirections.Clear(); + } + + } + + Vector& glyphs = mImpl->mVisualModel->mGlyphs; + Vector& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters; + Vector& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph; + if( SHAPE_TEXT & operations ) + { + const Vector& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters; + // Shapes the text. + ShapeText( textToShape, + lineBreakInfo, + scripts, + validFonts, + glyphs, + glyphsToCharactersMap, + charactersPerGlyph ); + + // Create the 'number of glyphs' per character and the glyph to character conversion tables. + mImpl->mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters ); + mImpl->mVisualModel->CreateCharacterToGlyphTable( numberOfCharacters ); + } + + const Length numberOfGlyphs = glyphs.Count(); + + if( GET_GLYPH_METRICS & operations ) + { + mImpl->mFontClient.GetGlyphMetrics( glyphs.Begin(), numberOfGlyphs ); + } +} + +bool Controller::DoRelayout( const Size& size, + OperationsMask operationsRequired, + Size& layoutSize ) +{ + bool viewUpdated( false ); + + // Calculate the operations to be done. + const OperationsMask operations = static_cast( mImpl->mOperationsPending & operationsRequired ); + + if( LAYOUT & operations ) + { + // Some vectors with data needed to layout and reorder may be void + // after the first time the text has been laid out. + // Fill the vectors again. + + Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs(); + + if( 0u == numberOfGlyphs ) + { + // Nothing else to do if there is no glyphs. + return true; + } + + Vector& lineBreakInfo = mImpl->mLogicalModel->mLineBreakInfo; + Vector& wordBreakInfo = mImpl->mLogicalModel->mWordBreakInfo; + Vector& characterDirection = mImpl->mLogicalModel->mCharacterDirections; + Vector& glyphs = mImpl->mVisualModel->mGlyphs; + Vector& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters; + Vector& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph; + + // Set the layout parameters. + LayoutParameters layoutParameters( size, + mImpl->mLogicalModel->mText.Begin(), + lineBreakInfo.Begin(), + wordBreakInfo.Begin(), + ( 0u != characterDirection.Count() ) ? characterDirection.Begin() : NULL, + numberOfGlyphs, + glyphs.Begin(), + glyphsToCharactersMap.Begin(), + charactersPerGlyph.Begin() ); + + // The laid-out lines. + // It's not possible to know in how many lines the text is going to be laid-out, + // but it can be resized at least with the number of 'paragraphs' to avoid + // some re-allocations. + Vector& lines = mImpl->mVisualModel->mLines; + + // Delete any previous laid out lines before setting the new ones. + lines.Clear(); + + // The capacity of the bidirectional paragraph info is the number of paragraphs. + lines.Reserve( mImpl->mLogicalModel->mBidirectionalParagraphInfo.Capacity() ); + + // Resize the vector of positions to have the same size than the vector of glyphs. + Vector& glyphPositions = mImpl->mVisualModel->mGlyphPositions; + glyphPositions.Resize( numberOfGlyphs ); + + // Update the visual model. + viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters, + glyphPositions, + lines, + layoutSize ); + + if( viewUpdated ) + { + // Reorder the lines + if( REORDER & operations ) + { + Vector& bidirectionalInfo = mImpl->mLogicalModel->mBidirectionalParagraphInfo; + + // Check first if there are paragraphs with bidirectional info. + if( 0u != bidirectionalInfo.Count() ) + { + // Get the lines + const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines(); + + // Reorder the lines. + Vector lineBidirectionalInfoRuns; + lineBidirectionalInfoRuns.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters. + ReorderLines( bidirectionalInfo, + lines, + lineBidirectionalInfoRuns ); + + // Set the bidirectional info into the model. + const Length numberOfBidirectionalInfoRuns = lineBidirectionalInfoRuns.Count(); + mImpl->mLogicalModel->SetVisualToLogicalMap( lineBidirectionalInfoRuns.Begin(), + numberOfBidirectionalInfoRuns ); + + // Set the bidirectional info per line into the layout parameters. + layoutParameters.lineBidirectionalInfoRunsBuffer = lineBidirectionalInfoRuns.Begin(); + layoutParameters.numberOfBidirectionalInfoRuns = numberOfBidirectionalInfoRuns; + + // Get the character to glyph conversion table and set into the layout. + layoutParameters.charactersToGlyphsBuffer = mImpl->mVisualModel->mCharactersToGlyph.Begin(); + + // Get the glyphs per character table and set into the layout. + layoutParameters.glyphsPerCharacterBuffer = mImpl->mVisualModel->mGlyphsPerCharacter.Begin(); + + // Re-layout the text. Reorder those lines with right to left characters. + mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters, + glyphPositions ); + + // Free the allocated memory used to store the conversion table in the bidirectional line info run. + for( Vector::Iterator it = lineBidirectionalInfoRuns.Begin(), + endIt = lineBidirectionalInfoRuns.End(); + it != endIt; + ++it ) + { + BidirectionalLineInfoRun& bidiLineInfo = *it; + + free( bidiLineInfo.visualToLogicalMap ); + } + } + } // REORDER + + if( ALIGN & operations ) + { + mImpl->mLayoutEngine.Align( layoutParameters, + layoutSize, + lines, + glyphPositions ); + } + + // Sets the actual size. + if( UPDATE_ACTUAL_SIZE & operations ) + { + mImpl->mVisualModel->SetActualSize( layoutSize ); + } + } // view updated + } + else + { + layoutSize = mImpl->mVisualModel->GetActualSize(); + } + + return viewUpdated; +} + +void Controller::CalculateTextAlignment( const Size& size ) +{ + // Get the direction of the first character. + const CharacterDirection firstParagraphDirection = mImpl->mLogicalModel->GetCharacterDirection( 0u ); + + const Size& actualSize = mImpl->mVisualModel->GetActualSize(); + + // If the first paragraph is right to left swap ALIGN_BEGIN and ALIGN_END; + LayoutEngine::HorizontalAlignment horizontalAlignment = mImpl->mLayoutEngine.GetHorizontalAlignment(); + if( firstParagraphDirection && + ( LayoutEngine::HORIZONTAL_ALIGN_CENTER != horizontalAlignment ) ) + { + if( LayoutEngine::HORIZONTAL_ALIGN_BEGIN == horizontalAlignment ) + { + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_END; + } + else + { + horizontalAlignment = LayoutEngine::HORIZONTAL_ALIGN_BEGIN; + } + } + + switch( horizontalAlignment ) + { + case LayoutEngine::HORIZONTAL_ALIGN_BEGIN: + { + mImpl->mAlignmentOffset.x = 0.f; + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_CENTER: + { + const int intOffset = static_cast( 0.5f * ( size.width - actualSize.width ) ); // try to avoid pixel alignment. + mImpl->mAlignmentOffset.x = static_cast( intOffset ); + break; + } + case LayoutEngine::HORIZONTAL_ALIGN_END: + { + mImpl->mAlignmentOffset.x = size.width - actualSize.width; + break; + } + } + + const LayoutEngine::VerticalAlignment verticalAlignment = mImpl->mLayoutEngine.GetVerticalAlignment(); + switch( verticalAlignment ) + { + case LayoutEngine::VERTICAL_ALIGN_TOP: + { + mImpl->mAlignmentOffset.y = 0.f; + break; + } + case LayoutEngine::VERTICAL_ALIGN_CENTER: + { + const int intOffset = static_cast( 0.5f * ( size.height - actualSize.height ) ); // try to avoid pixel alignment. + mImpl->mAlignmentOffset.y = static_cast( intOffset ); + break; + } + case LayoutEngine::VERTICAL_ALIGN_BOTTOM: + { + mImpl->mAlignmentOffset.y = size.height - actualSize.height; + break; + } + } +} + +View& Controller::GetView() +{ + return mImpl->mView; +} + +LayoutEngine& Controller::GetLayoutEngine() +{ + return mImpl->mLayoutEngine; +} + +void Controller::RequestRelayout() +{ + mImpl->mControlInterface.RequestTextRelayout(); +} + +void Controller::KeyboardFocusGainEvent() +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusGainEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::KEYBOARD_FOCUS_GAIN_EVENT ); + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +void Controller::KeyboardFocusLostEvent() +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyboardFocusLostEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::KEYBOARD_FOCUS_LOST_EVENT ); + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected KeyEvent" ); + + if( mImpl->mTextInput && + keyEvent.state == KeyEvent::Down ) + { + int keyCode = keyEvent.keyCode; + const std::string& keyString = keyEvent.keyPressed; + + // Pre-process to separate modifying events from non-modifying input events. + if( Dali::DALI_KEY_ESCAPE == keyCode ) + { + // Escape key is a special case which causes focus loss + KeyboardFocusLostEvent(); + } + else if( Dali::DALI_KEY_CURSOR_LEFT == keyCode || + Dali::DALI_KEY_CURSOR_RIGHT == keyCode || + Dali::DALI_KEY_CURSOR_UP == keyCode || + Dali::DALI_KEY_CURSOR_DOWN == keyCode ) + { + TextInput::Event event( TextInput::CURSOR_KEY_EVENT ); + event.p1.mInt = keyCode; + mImpl->mTextInput->mEventQueue.push_back( event ); + } + else if( Dali::DALI_KEY_BACKSPACE == keyCode ) + { + // Queue a delete event + ModifyEvent event; + event.type = DELETE_TEXT; + mImpl->mModifyEvents.push_back( event ); + } + else if( !keyString.empty() ) + { + // Queue an insert event + ModifyEvent event; + event.type = INSERT_TEXT; + event.text = keyString; + mImpl->mModifyEvents.push_back( event ); + } + + mImpl->mTextInput->ChangeState( TextInput::EDITING ); // todo Confirm this is the best place to change the state of + + RequestRelayout(); + } + + return false; +} + +void Controller::TapEvent( unsigned int tapCount, float x, float y ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected TapEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::TAP_EVENT ); + event.p1.mUint = tapCount; + event.p2.mFloat = x; + event.p3.mFloat = y; + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +void Controller::PanEvent( Gesture::State state, const Vector2& displacement ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected PanEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::PAN_EVENT ); + event.p1.mInt = state; + event.p2.mFloat = displacement.x; + event.p3.mFloat = displacement.y; + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +void Controller::GrabHandleEvent( GrabHandleState state, float x, float y ) +{ + DALI_ASSERT_DEBUG( mImpl->mTextInput && "Unexpected GrabHandleEvent" ); + + if( mImpl->mTextInput ) + { + TextInput::Event event( TextInput::GRAB_HANDLE_EVENT ); + event.p1.mUint = state; + event.p2.mFloat = x; + event.p3.mFloat = y; + mImpl->mTextInput->mEventQueue.push_back( event ); + + RequestRelayout(); + } +} + +Controller::~Controller() +{ + delete mImpl; +} + +Controller::Controller( ControlInterface& controlInterface ) +: mImpl( NULL ) +{ + mImpl = new Controller::Impl( controlInterface ); +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h new file mode 100644 index 0000000..a5dd91b --- /dev/null +++ b/dali-toolkit/internal/text/text-controller.h @@ -0,0 +1,463 @@ +#ifndef __DALI_TOOLKIT_TEXT_CONTROLLER_H__ +#define __DALI_TOOLKIT_TEXT_CONTROLLER_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 +#include +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +class Controller; +class LayoutEngine; + +typedef IntrusivePtr ControllerPtr; +typedef Dali::Toolkit::Text::ControlInterface ControlInterface; + +/** + * @brief A Text Controller is used by UI Controls which display text. + * + * It manipulates the Logical & Visual text models on behalf of the UI Controls. + * It provides a view of the text that can be used by rendering back-ends. + * + * For selectable/editable UI controls, the controller handles input events from the UI control + * and decorations (grab handles etc) via an observer interface. + */ +class Controller : public RefObject, public Decorator::Observer +{ +private: + + /** + * @brief Text related operations to be done in the relayout process. + */ + enum OperationsMask + { + NO_OPERATION = 0x0000, + CONVERT_TO_UTF32 = 0x0001, + GET_SCRIPTS = 0x0002, + VALIDATE_FONTS = 0x0004, + GET_LINE_BREAKS = 0x0008, + GET_WORD_BREAKS = 0x0010, + BIDI_INFO = 0x0020, + SHAPE_TEXT = 0x0040, + GET_GLYPH_METRICS = 0x0080, + LAYOUT = 0x0100, + UPDATE_ACTUAL_SIZE = 0x0200, + REORDER = 0x0400, + ALIGN = 0x0800, + ALL_OPERATIONS = 0xFFFF + }; + +public: + + /** + * @brief Create a new instance of a Controller. + * + * @param[in] controlInterface An interface used to request a text relayout. + * @return A pointer to a new Controller. + */ + static ControllerPtr New( ControlInterface& controlInterface ); + + /** + * @brief Replaces any text previously set. + * + * @note This will be converted into UTF-32 when stored in the text model. + * @param[in] text A string of UTF-8 characters. + */ + void SetText( const std::string& text ); + + /** + * @brief Retrieve any text previously set. + * + * @return A string of UTF-8 characters. + */ + void GetText( std::string& text ) const; + + /** + * @brief Replaces any placeholder text previously set. + * + * @param[in] text A string of UTF-8 characters. + */ + void SetPlaceholderText( const std::string& text ); + + /** + * @brief Retrieve any placeholder text previously set. + * + * @return A string of UTF-8 characters. + */ + void GetPlaceholderText( std::string& text ) const; + + /** + * @brief Set the default font family. + * + * @param[in] defaultFontFamily The default font family. + */ + void SetDefaultFontFamily( const std::string& defaultFontFamily ); + + /** + * @brief Retrieve the default font family. + * + * @return The default font family. + */ + const std::string& GetDefaultFontFamily() const; + + /** + * @brief Set the default font style. + * + * @param[in] defaultFontStyle The default font style. + */ + void SetDefaultFontStyle( const std::string& defaultFontStyle ); + + /** + * @brief Retrieve the default font style. + * + * @return The default font style. + */ + const std::string& GetDefaultFontStyle() const; + + /** + * @brief Set the default point size. + * + * @param[in] defaultFontStyle The default point size. + */ + void SetDefaultPointSize( float pointSize ); + + /** + * @brief Retrieve the default point size. + * + * @return The default point size. + */ + float GetDefaultPointSize() const; + + /** + * @brief Retrieve the default fonts. + * + * @param[out] fonts The default font family, style and point sizes. + * @param[in] numberOfCharacters The number of characters in the logical model. + */ + void GetDefaultFonts( Dali::Vector& fonts, Length numberOfCharacters ) const; + + /** + * @brief Set the text color + * + * @param textColor The text color + */ + void SetTextColor( const Vector4& textColor ); + + /** + * @brief Retrieve the text color + * + * @return The text color + */ + const Vector4& GetTextColor() const; + + /** + * @brief Set the shadow offset. + * + * @param[in] shadowOffset The shadow offset, 0,0 indicates no shadow. + */ + void SetShadowOffset( const Vector2& shadowOffset ); + + /** + * @brief Retrieve the shadow offset. + * + * @return The shadow offset. + */ + const Vector2& GetShadowOffset() const; + + /** + * @brief Set the shadow color. + * + * @param[in] shadowColor The shadow color. + */ + void SetShadowColor( const Vector4& shadowColor ); + + /** + * @brief Retrieve the shadow color. + * + * @return The shadow color. + */ + const Vector4& GetShadowColor() const; + + /** + * @brief Set the underline color. + * + * @param[in] color color of underline. + */ + void SetUnderlineColor( const Vector4& color ); + + /** + * @brief Retrieve the underline color. + * + * @return The underline color. + */ + const Vector4& GetUnderlineColor() const; + + /** + * @brief Set the underline enabled flag. + * + * @param[in] enabled The underline enabled flag. + */ + void SetUnderlineEnabled( bool enabled ); + + /** + * @brief Returns whether the text is underlined or not. + * + * @return The underline state. + */ + bool IsUnderlineEnabled() const; + + /** + * @brief Set the override used for underline height, 0 indicates height will be supplied by font metrics + * + * @param[in] height The height in pixels of the underline + */ + void SetUnderlineHeight( float height ); + + /** + * @brief Retrieves the override height of an underline, 0 indicates height is supplied by font metrics + * + * @return The height of the underline, or 0 if height is not overrided. + */ + float GetUnderlineHeight() const; + + /** + * @brief Called to enable text input. + * + * @note Only selectable or editable controls should calls this. + * @param[in] decorator Used to create cursor, selection handle decorations etc. + */ + void EnableTextInput( DecoratorPtr decorator ); + + /** + * @brief Called to enable/disable cursor blink. + * + * @note Only editable controls should calls this. + * @param[in] enabled Whether the cursor should blink or not. + */ + void SetEnableCursorBlink( bool enable ); + + /** + * @brief Query whether cursor blink is enabled. + * + * @return Whether the cursor should blink or not. + */ + bool GetEnableCursorBlink() const; + + /** + * @brief Query the current scroll position; the UI control is responsible for moving actors to this position. + * + * @return The scroll position. + */ + const Vector2& GetScrollPosition() const; + + /** + * @brief Query the alignment offset. + * + * @return The alignmnet offset. + */ + const Vector2& GetAlignmentOffset() const; + + /** + * @copydoc Control::GetNaturalSize() + */ + Vector3 GetNaturalSize(); + + /** + * @copydoc Control::GetHeightForWidth() + */ + float GetHeightForWidth( float width ); + + /** + * @brief Triggers a relayout which updates View (if necessary). + * + * @note UI Controls are expected to minimize calls to this method e.g. call once after size negotiation. + * @param[in] size A the size of a bounding box to layout text within. + * @return True if the text model or decorations were updated. + */ + bool Relayout( const Size& size ); + + /** + * @brief Process queued events which modify the model. + */ + void ProcessModifyEvents(); + + /** + * @brief Used to process an event queued from SetText() + * + * @param[in] newText The new text to store in the logical model. + */ + void ReplaceTextEvent( const std::string& newText ); + + /** + * @brief Used to process an event queued from key events etc. + * + * @param[in] text The text to insert into the logical model. + */ + void InsertTextEvent( const std::string& text ); + + /** + * @brief Used to process an event queued from backspace key etc. + */ + void DeleteTextEvent(); + + /** + * @brief Update the model following text replace/insert etc. + * + * @param[in] operationsRequired The layout operations which need to be done. + */ + void UpdateModel( OperationsMask operationsRequired ); + + /** + * @brief Lays-out the text. + * + * GetNaturalSize(), GetHeightForWidth() and Relayout() calls this method. + * + * @param[in] size A the size of a bounding box to layout text within. + * @param[in] operations The layout operations which need to be done. + * @param[out] layoutSize The size of the laid-out text. + */ + bool DoRelayout( const Size& size, + OperationsMask operations, + Size& layoutSize ); + + /** + * @brief Calulates the alignment of the whole text inside the bounding box. + * + * @param[in] size The size of the bounding box. + */ + void CalculateTextAlignment( const Size& size ); + + /** + * @brief Return the layout engine. + * + * @return A reference to the layout engine. + */ + LayoutEngine& GetLayoutEngine(); + + /** + * @brief Return a view of the text. + * + * @return A reference to the view. + */ + View& GetView(); + + // Text-input Event Queuing + + /** + * @brief Caller by editable UI controls when keyboard focus is gained. + */ + void KeyboardFocusGainEvent(); + + /** + * @brief Caller by editable UI controls when focus is lost. + */ + void KeyboardFocusLostEvent(); + + /** + * @brief Caller by editable UI controls when key events are received. + * + * @param[in] event The key event. + */ + bool KeyEvent( const Dali::KeyEvent& event ); + + /** + * @brief Caller by editable UI controls when a tap gesture occurs. + * @param[in] tapCount The number of taps. + * @param[in] x The x position relative to the top-left of the parent control. + * @param[in] y The y position relative to the top-left of the parent control. + */ + void TapEvent( unsigned int tapCount, float x, float y ); + + /** + * @brief Caller by editable UI controls when a pan gesture occurs. + * + * @param[in] state The state of the gesture. + * @param[in] displacement This distance panned since the last pan gesture. + */ + void PanEvent( Gesture::State state, const Vector2& displacement ); + + /** + * @copydoc Dali::Toolkit::Text::Decorator::Observer::GrabHandleEvent() + */ + virtual void GrabHandleEvent( GrabHandleState state, float x, float y ); + +protected: + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~Controller(); + +private: + + /** + * @brief Request a relayout using the ControlInterface. + */ + void RequestRelayout(); + + /** + * @brief Private constructor. + */ + Controller( ControlInterface& controlInterface ); + + // Undefined + Controller( const Controller& handle ); + + // Undefined + Controller& operator=( const Controller& handle ); + +private: + + struct Impl; + Impl* mImpl; + + // Avoid allocating this when the user does not specify a font + struct FontDefaults; + + // Avoid allocating this for non-editable controls + struct TextInput; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_CONTROLLER_H__ diff --git a/dali-toolkit/internal/text/text-definitions.h b/dali-toolkit/internal/text/text-definitions.h new file mode 100644 index 0000000..17bca2d --- /dev/null +++ b/dali-toolkit/internal/text/text-definitions.h @@ -0,0 +1,63 @@ +#ifndef __DALI_TEXT_ABSTRACTION_TEXT_TYPE_DEFINITIONS_H__ +#define __DALI_TEXT_ABSTRACTION_TEXT_TYPE_DEFINITIONS_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 +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +typedef TextAbstraction::FontId FontId; ///< The unique identifier for a font face (generated by FontClient). +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. +typedef TextAbstraction::GlyphIndex GlyphIndex; ///< Uniquely identifies a glyph within a particular font. +typedef TextAbstraction::Character Character; ///< A UTF-32 representation of a character. +typedef TextAbstraction::GlyphInfo GlyphInfo; ///< The information describing a glyph (font ID, index, metrics). +typedef TextAbstraction::CharacterIndex CharacterIndex; ///< An index into an array of characters. +typedef TextAbstraction::Length Length; ///< The length of an array. +typedef TextAbstraction::BidiInfoIndex BidiInfoIndex; ///< Index to the bidirectional info for a paragraph. +typedef TextAbstraction::Script Script; ///< The character's script. +typedef TextAbstraction::LineBreakInfo LineBreakInfo; ///< Line break info (must break, allow break, no break). Possible values are: @e LINE_MUST_BREAK, @e LINE_ALLOW_BREAK and @e LINE_NO_BREAK (in the TextAbstraction namespace). +typedef TextAbstraction::WordBreakInfo WordBreakInfo; ///< Word break info (break, no break). Possible values are: @e WORD_BREAK and @e WORD_NO_BREAK (in the TextAbstraction namespace). +typedef TextAbstraction::CharacterDirection CharacterDirection; ///< The character's direction: @e false is left to right, @e true is right to left. + +typedef uint32_t GlyphIndex; ///< An index into an array of glyphs. +typedef uint32_t ScriptRunIndex; ///< An index into an array of script runs. +typedef uint32_t FontRunIndex; ///< An index into an array of font runs. +typedef uint32_t BidirectionalRunIndex; ///< An index into an array of font runs. +typedef uint32_t LineIndex; ///< An index into an array of lines. + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TEXT_ABSTRACTION_TEXT_TYPE_DEFINITIONS_H__ diff --git a/dali-toolkit/internal/text/text-io.cpp b/dali-toolkit/internal/text/text-io.cpp new file mode 100644 index 0000000..3bc1761 --- /dev/null +++ b/dali-toolkit/internal/text/text-io.cpp @@ -0,0 +1,115 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +std::ostream& operator<< (std::ostream& o, const Vector& text) +{ + o << std::hex; + + for( unsigned int i=0; i& scriptRun) +{ + for( unsigned int i=0; i9: LATIN" for a ten character run staring from beginning of the model + o << scriptRun[i].characterRun.characterIndex << "->" << (scriptRun[i].characterRun.characterIndex + scriptRun[i].characterRun.numberOfCharacters ) << ": "; + o << TextAbstraction::ScriptName[scriptRun[i].script]; + + if( i+1 < scriptRun.Count() ) + { + o << ", "; + } + } + + return o << std::dec; +} + +std::ostream& operator<< (std::ostream& o, const Vector& fontRun) +{ + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + + for( unsigned int i=0; i9: ID:1 TizenSansKorean style:Regular size:10.0" for a ten character run staring from beginning of the model + o << fontRun[i].characterRun.characterIndex << "->" << (fontRun[i].characterRun.characterIndex + fontRun[i].characterRun.numberOfCharacters ) << ": "; + + 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); + + if( i+1 < fontRun.Count() ) + { + o << ", "; + } + } + + return o << std::dec; +} + +std::ostream& operator<< (std::ostream& o, const Vector& lineRuns) +{ + for( unsigned int i=0; i9 Characters: 0->9 (10)" for a ten character run staring from beginning of the model + o << "Line " << i << " Glyphs: " << lineRuns[i].glyphIndex << "->" << (lineRuns[i].glyphIndex + lineRuns[i].numberOfGlyphs ); + o << " Characters: " << lineRuns[i].characterRun.characterIndex << "->" << (lineRuns[i].characterRun.characterIndex + lineRuns[i].characterRun.numberOfCharacters ); + o << " Width: " << lineRuns[i].width; + o << " Ascender: " << lineRuns[i].ascender; + o << " Descender: " << lineRuns[i].descender; + + if( i+1 < lineRuns.Count() ) + { + o << ", "; + } + } + + return o << std::dec; +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-io.h b/dali-toolkit/internal/text/text-io.h new file mode 100644 index 0000000..25620e0 --- /dev/null +++ b/dali-toolkit/internal/text/text-io.h @@ -0,0 +1,82 @@ +#ifndef __DALI_TEXT_ABSTRACTION_TEXT_IO_H__ +#define __DALI_TEXT_ABSTRACTION_TEXT_IO_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 +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief Print a vector of characters. + * + * @param [in] o The output stream operator. + * @param [in] text The text to print. + * @return The output stream operator. + */ +std::ostream& operator<< (std::ostream& o, const Vector& text); + +/** + * @brief Print a vector of script runs. + * + * @param [in] o The output stream operator. + * @param [in] scriptRuns The script runs to print. + * @return The output stream operator. + */ +std::ostream& operator<< (std::ostream& o, const Vector& scriptRuns); + +/** + * @brief Print a vector of font runs. + * + * @param [in] o The output stream operator. + * @param [in] fontRuns The font runs to print. + * @return The output stream operator. + */ +std::ostream& operator<< (std::ostream& o, const Vector& fontRuns); + +/** + * @brief Print a vector of line runs. + * + * @param [in] o The output stream operator. + * @param [in] lineRuns The line runs to print. + * @return The output stream operator. + */ +std::ostream& operator<< (std::ostream& o, const Vector& lineRuns); + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TEXT_ABSTRACTION_TEXT_IO_H__ diff --git a/dali-toolkit/internal/text/text-view-interface.cpp b/dali-toolkit/internal/text/text-view-interface.cpp new file mode 100644 index 0000000..54d1589 --- /dev/null +++ b/dali-toolkit/internal/text/text-view-interface.cpp @@ -0,0 +1,42 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +ViewInterface::ViewInterface() +{ +} + +ViewInterface::~ViewInterface() +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-view-interface.h b/dali-toolkit/internal/text/text-view-interface.h new file mode 100644 index 0000000..68d5e97 --- /dev/null +++ b/dali-toolkit/internal/text/text-view-interface.h @@ -0,0 +1,141 @@ +#ifndef __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__ +#define __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_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 + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +struct Vector2; + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief Abstract interface to provide the information necessary displaying text. + * + * This includes: + * - The font & glyph IDs needed to get bitmaps etc. from TextAbstraction + * - The visual position of each glyph within the layout + * - A window into the text layout e.g. which page of a document to view + */ +class ViewInterface +{ +public: + + /** + * @brief Constructor. + */ + ViewInterface(); + + /** + * @brief Virtual destructor + */ + virtual ~ViewInterface(); + + /** + * Retrieves the number of glyphs. + * + * @return The number of glyphs. + */ + virtual Length GetNumberOfGlyphs() const = 0; + + /** + * @brief Retrieves glyphs in the given buffer. + * + * The size of the @p glyphs buffer needs to be big enough to copy the @p numberOfGlyphs. + * @param[out] glyphs Pointer to a buffer where the glyphs are copied. + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs Number of glyphs to be copied. + */ + virtual void GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const = 0; + + /** + * @brief Retrieves the glyph positions. + * + * @pre The size of the @p positions buffer needs to be big enough to copy the @p numberOfGlyphs positions. + * @param[out] glyphPositions Pointer to a buffer where the glyph positions are copied. + * @param[in] glyphIndex Index to the first glyph position. + * @param[in] numberOfGlyphs The number of positions to be copied. + */ + virtual void GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const = 0; + + /** + * @brief Retrieves the text color + * + * @return The text color + */ + virtual const Vector4& GetTextColor() const = 0; + + /** + * @brief Retrieves the shadow offset, 0 indicates no shadow. + * + * @return The shadow offset. + */ + virtual const Vector2& GetShadowOffset() const = 0; + + /** + * @brief Retrieves the shadow color. + * + * @return The shadow color. + */ + virtual const Vector4& GetShadowColor() const = 0; + + /** + * @brief Retrieves the underline color. + * + * @return The underline color. + */ + virtual const Vector4& GetUnderlineColor() const = 0; + + /** + * @brief Returns whether underline is enabled or not. + * + * @return The underline state. + */ + virtual bool IsUnderlineEnabled() const = 0; + + /** + * @brief Retrieves the underline height override + * + * @return Returns the override height for an underline, 0 indicates that adaptor will determine the height + */ + virtual float GetUnderlineHeight() const = 0; + +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_VIEW_INTERFACE_H__ diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp new file mode 100644 index 0000000..61073fe --- /dev/null +++ b/dali-toolkit/internal/text/text-view.cpp @@ -0,0 +1,155 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +struct View::Impl +{ + VisualModelPtr mVisualModel; +}; + +View::View() +: mImpl( NULL ) +{ + mImpl = new View::Impl(); +} + +View::~View() +{ + delete mImpl; +} + +void View::SetVisualModel( VisualModelPtr visualModel ) +{ + mImpl->mVisualModel = visualModel; +} + +const Vector4& View::GetTextColor() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetTextColor(); + } + return Vector4::ZERO; +} + +const Vector2& View::GetShadowOffset() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetShadowOffset(); + } + return Vector2::ZERO; +} + +const Vector4& View::GetShadowColor() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetShadowColor(); + } + return Vector4::ZERO; +} + +const Vector4& View::GetUnderlineColor() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetUnderlineColor(); + } + return Vector4::ZERO; +} + +bool View::IsUnderlineEnabled() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.IsUnderlineEnabled(); + } + return false; +} + +float View::GetUnderlineHeight() const +{ + if ( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + return model.GetUnderlineHeight(); + } + return 0.0f; +} + +Length View::GetNumberOfGlyphs() const +{ + if( mImpl->mVisualModel ) + { + VisualModel& model = *mImpl->mVisualModel; + + Length glyphCount = model.GetNumberOfGlyphs(); + Length positionCount = model.GetNumberOfGlyphPositions(); + + DALI_ASSERT_DEBUG( positionCount <= glyphCount && "Invalid glyph positions in Model" ); + + return (positionCount < glyphCount) ? positionCount : glyphCount; + } + + return 0; +} + +void View::GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + if( mImpl->mVisualModel ) + { + mImpl->mVisualModel->GetGlyphs( glyphs, glyphIndex, numberOfGlyphs ); + } +} + +void View::GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + if( mImpl->mVisualModel ) + { + mImpl->mVisualModel->GetGlyphPositions( glyphPositions, glyphIndex, numberOfGlyphs ); + } +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/text-view.h b/dali-toolkit/internal/text/text-view.h new file mode 100644 index 0000000..e611c3c --- /dev/null +++ b/dali-toolkit/internal/text/text-view.h @@ -0,0 +1,128 @@ +#ifndef __DALI_TOOLKIT_TEXT_VIEW_H__ +#define __DALI_TOOLKIT_TEXT_VIEW_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. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +struct Vector2; + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief View provides an interface between the Text layout engine and rendering back-end. + */ +class View : public ViewInterface +{ +public: + + /** + * @brief Create a new instance of a View. + */ + View(); + + /** + * @brief Virtual destructor. + */ + virtual ~View(); + + /** + * @brief Set the visual model. + * + * @param[in] visualModel The visual model used by the View. + */ + void SetVisualModel( VisualModelPtr visualModel ); + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetNumberOfGlyphs() + */ + virtual Length GetNumberOfGlyphs() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetGlyphs() + */ + virtual void GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetGlyphPositions() + */ + virtual void GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetTextColor() + */ + virtual const Vector4& GetTextColor() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetShadowOffset() + */ + virtual const Vector2& GetShadowOffset() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetShadowColor() + */ + virtual const Vector4& GetShadowColor() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetUnderlineColor() + */ + virtual const Vector4& GetUnderlineColor() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::IsUnderlineEnabled() + */ + virtual bool IsUnderlineEnabled() const; + + /** + * @copydoc Dali::Toolkit::Text::ViewInterface::GetUnderlineHeight() + */ + virtual float GetUnderlineHeight() const; + +private: + + // Undefined + View( const View& handle ); + + // Undefined + View& operator=( const View& handle ); + +private: + + struct Impl; + Impl* mImpl; +}; +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_VIEW_H__ diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp new file mode 100644 index 0000000..922f309 --- /dev/null +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -0,0 +1,513 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +VisualModelPtr VisualModel::New() +{ + return VisualModelPtr( new VisualModel() ); +} + +void VisualModel::SetGlyphs( const GlyphInfo* glyphs, + const CharacterIndex* characterIndices, + const Length* charactersPerGlyph, + Length numberOfGlyphs ) +{ + if( 0u == numberOfGlyphs ) + { + mGlyphs.Clear(); + mGlyphsToCharacters.Clear(); + mCharactersToGlyph.Clear(); + mCharactersPerGlyph.Clear(); + mGlyphsPerCharacter.Clear(); + } + else + { + if( NULL != glyphs ) + { + mGlyphs.Resize( numberOfGlyphs ); + memcpy( mGlyphs.Begin(), glyphs, numberOfGlyphs * sizeof( GlyphInfo ) ); + } + + if( NULL != characterIndices ) + { + mGlyphsToCharacters.Resize( numberOfGlyphs ); + memcpy( mGlyphsToCharacters.Begin(), characterIndices, numberOfGlyphs * sizeof( CharacterIndex ) ); + } + + if( NULL != charactersPerGlyph ) + { + mCharactersPerGlyph.Resize( numberOfGlyphs ); + memcpy( mCharactersPerGlyph.Begin(), charactersPerGlyph, numberOfGlyphs * sizeof( Length ) ); + + // Build the glyphs per character table. + CreateGlyphsPerCharacterTable(); + + // Build the characters to glyph conversion table. + CreateCharacterToGlyphTable(); + } + } +} + +void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters ) +{ + // 1) Reserve some space for the characters to avoid reallocations. + if( 0u == numberOfCharacters ) + { + // If no number of characters is given, just set something sensible to avoid reallocations. + numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f ); + } + mCharactersToGlyph.Reserve( numberOfCharacters ); + + DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u || + ( 0u == numberOfCharacters ) ); + + const Length* const glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin(); + + // 2) Traverse the glyphs and set the glyph indices per character. + + // Index to the glyph. + GlyphIndex glyphIndex = 0u; + CharacterIndex characterIndex = 0u; + for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(), + endIt = mCharactersPerGlyph.End(); + it != endIt; + ++it ) + { + const Length numberOfCharactersPerGlyph = *it; + + Length numberOfGlyphs = 0u; + // Set the glyph indices. + for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex ) + { + mCharactersToGlyph.PushBack( glyphIndex ); + numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex ); + } + glyphIndex += numberOfGlyphs; + } +} + +void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters ) +{ + // 1) Reserve some space for the characters to avoid reallocations. + if( 0u == numberOfCharacters ) + { + // If no number of characters is given, just set something sensible to avoid reallocations. + numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f ); + } + mGlyphsPerCharacter.Reserve( numberOfCharacters ); + + // 2) Traverse the glyphs and set the number of glyphs per character. + + // The number of 'characters per glyph' equal to zero. + Length zeroCharactersPerGlyph = 0u; + + for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(), + endIt = mCharactersPerGlyph.End(); + it != endIt; + ++it ) + { + const Length numberOfCharactersPerGlyph = *it; + + // Set the glyphs per character. + if( 0u == numberOfCharactersPerGlyph ) + { + ++zeroCharactersPerGlyph; + } + else + { + const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u ); + for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex ) + { + mGlyphsPerCharacter.PushBack( 0u ); + } + + mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph ); + + zeroCharactersPerGlyph = 0u; + } + } +} + +Length VisualModel::GetNumberOfGlyphs() const +{ + return mGlyphs.Count(); +} + +void VisualModel::GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) ); +} + +const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const +{ + return mGlyphs[glyphIndex]; +} + +void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const GlyphInfo* const glyphs, + const Length* const numberOfCharacters, + Length numberOfGlyphsToInsert ) +{ +} + +CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const +{ + return mGlyphsToCharacters[glyphIndex]; +} + +Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const +{ + return mCharactersPerGlyph[glyphIndex]; +} + +GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const +{ + return mCharactersToGlyph[characterIndex]; +} + +void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( characterToGlyphMap, mCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) ); +} + +void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphToCharacter, mGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) ); +} + +void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( charactersPerGlyph, mCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) ); +} + +void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter, + CharacterIndex characterIndex, + Length numberOfCharacters ) const +{ + memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) ); +} + +void VisualModel::SetGlyphPositions( const Vector2* glyphPositions, + Length numberOfGlyphs ) +{ + if( 0u == numberOfGlyphs ) + { + mGlyphPositions.Clear(); + } + else + { + mGlyphPositions.Resize( numberOfGlyphs ); + memcpy( mGlyphPositions.Begin(), glyphPositions, numberOfGlyphs * sizeof( Vector2 ) ); + } +} + +Length VisualModel::GetNumberOfGlyphPositions() const +{ + return mGlyphPositions.Count(); +} + +void VisualModel::GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) ); +} + +const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const +{ + return *( mGlyphPositions.Begin() + glyphIndex ); +} + +void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const Vector2* const positions, + Length numberOfGlyphsToInsert ) +{ +} + +void VisualModel::SetLines( const LineRun* const lines, + Length numberOfLines ) +{ + if( 0u == numberOfLines ) + { + mLines.Clear(); + } + else + { + mLines.Resize( numberOfLines ); + memcpy( mLines.Begin(), lines, numberOfLines * sizeof( LineRun ) ); + } +} + +Length VisualModel::GetNumberOfLines() const +{ + return mLines.Count(); +} + +void VisualModel::GetLines( LineRun* lines, + LineIndex lineIndex, + Length numberOfLines ) const +{ + memcpy( lines, mLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) ); +} + +void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex, + Length numberOfGlyphs, + LineIndex& firstLine, + Length& numberOfLines ) const +{ + // Initialize the number of lines and the first line. + firstLine = 0u; + numberOfLines = 0u; + bool firstLineFound = false; + + const GlyphIndex lastGlyphIndex = glyphIndex + numberOfGlyphs; + + // Traverse the lines and count those lines within the range of glyphs. + for( Vector::ConstIterator it = mLines.Begin(), + endIt = mLines.End(); + it != endIt; + ++it ) + { + const LineRun& line = *it; + + if( ( line.glyphIndex + line.numberOfGlyphs > glyphIndex ) && + ( lastGlyphIndex > line.glyphIndex ) ) + { + firstLineFound = true; + ++numberOfLines; + } + else if( lastGlyphIndex <= line.glyphIndex ) + { + // nothing else to do. + break; + } + + if( !firstLineFound ) + { + ++firstLine; + } + } +} + +void VisualModel::GetLinesOfGlyphRange( LineRun* lines, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const +{ + LineIndex firstLine = 0u; + Length numberOfLines = 0u; + + GetNumberOfLines( glyphIndex, + numberOfGlyphs, + firstLine, + numberOfLines ); + + memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) ); +} + +LineIndex VisualModel::GetLineOfGlyph( GlyphIndex glyphIndex ) +{ + const CharacterIndex characterIndex = *( mGlyphsToCharacters.Begin() + glyphIndex ); + + return GetLineOfCharacter( characterIndex ); +} + +LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex ) +{ + // 1) Check first in the cached line. + + const LineRun& lineRun = *( mLines.Begin() + mCachedLineIndex ); + + if( ( lineRun.characterRun.characterIndex <= characterIndex ) && + ( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) ) + { + return mCachedLineIndex; + } + + // 2) Is not in the cached line. Check in the other lines. + + LineIndex index = characterIndex < lineRun.characterRun.characterIndex ? 0u : mCachedLineIndex + 1u; + + for( Vector::ConstIterator it = mLines.Begin() + index, + endIt = mLines.End(); + it != endIt; + ++it, ++index ) + { + const LineRun& lineRun = *it; + + if( characterIndex < lineRun.characterRun.characterIndex + lineRun.characterRun.numberOfCharacters ) + { + mCachedLineIndex = index; + break; + } + } + + return index; +} + +void VisualModel::ReplaceLines( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const LineRun* const lines, + Length numberOfGlyphsToInsert ) +{ +} + +void VisualModel::SetNaturalSize( const Vector2& size ) +{ + mNaturalSize = size; +} + +const Vector2& VisualModel::GetNaturalSize() const +{ + return mNaturalSize; +} + +void VisualModel::SetActualSize( const Vector2& size ) +{ + mActualSize = size; +} + +const Vector2& VisualModel::GetActualSize() const +{ + return mActualSize; +} + +void VisualModel::SetTextColor( const Vector4& textColor ) +{ + mTextColor = textColor; + + if ( !mUnderlineColorSet ) + { + mUnderlineColor = textColor; + } +} + +void VisualModel::SetShadowOffset( const Vector2& shadowOffset ) +{ + mShadowOffset = shadowOffset; +} + +void VisualModel::SetShadowColor( const Vector4& shadowColor ) +{ + mShadowColor = shadowColor; +} + +void VisualModel::SetUnderlineColor( const Vector4& color ) +{ + mUnderlineColor = color; + mUnderlineColorSet = true; +} + +void VisualModel::SetUnderlineEnabled( bool enabled ) +{ + mUnderlineEnabled = enabled; +} + +void VisualModel::SetUnderlineHeight( float height ) +{ + mUnderlineHeight = height; +} + +const Vector4& VisualModel::GetTextColor() const +{ + return mTextColor; +} + +const Vector2& VisualModel::GetShadowOffset() const +{ + return mShadowOffset; +} + +const Vector4& VisualModel::GetShadowColor() const +{ + return mShadowColor; +} + +const Vector4& VisualModel::GetUnderlineColor() const +{ + return mUnderlineColor; +} + +bool VisualModel::IsUnderlineEnabled() const +{ + return mUnderlineEnabled; +} + +float VisualModel::GetUnderlineHeight() const +{ + return mUnderlineHeight; +} + +void VisualModel::ClearCaches() +{ + mCachedLineIndex = 0u; +} + +VisualModel::~VisualModel() +{ +} + +VisualModel::VisualModel() +: mGlyphs(), + mGlyphsToCharacters(), + mCharactersToGlyph(), + mCharactersPerGlyph(), + mGlyphsPerCharacter(), + mGlyphPositions(), + mLines(), + mTextColor(), + mShadowColor(), + mUnderlineColor(), + mShadowOffset(), + mUnderlineHeight( 0.0f ), + mNaturalSize(), + mActualSize(), + mCachedLineIndex( 0u ), + mUnderlineEnabled( false ), + mUnderlineColorSet( false ) +{ +} + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h new file mode 100644 index 0000000..fb9f7bc --- /dev/null +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -0,0 +1,553 @@ +#ifndef __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__ +#define __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_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 +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +struct Vector2; + +namespace Toolkit +{ + +namespace Text +{ + +struct LineRun; +class VisualModel; +typedef IntrusivePtr VisualModelPtr; + +/** + * @brief A visual text model contains layout specific information. + * + * This includes: + * - A series of glyphs in visual order i.e. after the bidirectional reordering. + * - The position of each glyph within a 2D bounding box. + */ +class VisualModel : public RefObject +{ +public: + + /** + * @brief Create a new instance of a VisualModel. + * + * @return A pointer to a new VisualModel. + */ + static VisualModelPtr New(); + + // Glyph interface. + + /** + * @brief Replaces any glyphs previously set. + * + * @note If the number of glyphs is zero, all buffers are cleared. + * @note If one pointer is NULL and the number of glyphs is not zero, the buffer is not touched. + * + * @param[in] glyphs An array of glyphs in the visual order. + * @param[in] characterIndices An array containing the first character in the logical model that each glyph relates to. + * @param[in] charactersPerGlyph An array containing the number of characters per glyph. + * @param[in] numberOfGlyphs The number of glyphs. + */ + void SetGlyphs( const GlyphInfo* glyphs, + const CharacterIndex* characterIndices, + const Length* charactersPerGlyph, + Length numberOfGlyphs ); + + /** + * @brief Creates the character to glyph conversion table. + * + * @pre The glyphs per character table needs to be created first. + * + * @param[in] numberOfCharacters The number of characters. + */ + void CreateCharacterToGlyphTable( Length numberOfCharacters = 0u ); + + /** + * @brief Creates an array containing the number of glyphs per character. + * + * @param[in] numberOfCharacters The number of characters. + */ + void CreateGlyphsPerCharacterTable( Length numberOfCharacters = 0u ); + + /** + * @brief Retrieves the number of glyphs. + * + * @return The number of glyphs. + */ + Length GetNumberOfGlyphs() const; + + /** + * @brief Retrieves glyphs in the given buffer. + * + * The size of the @p glyphs buffer needs to be big enough to copy the @p numberOfGlyphs. + * @param[out] glyphs Pointer to a buffer where the glyphs are copied. + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs Number of glyphs to be copied. + */ + void GetGlyphs( GlyphInfo* glyphs, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieves a glyph. + * + * @param[in] glyphIndex Index to a glyph. + * + * @return A glyph. + */ + const GlyphInfo& GetGlyphInfo( GlyphIndex glyphIndex ) const; + + /** + * @brief Replaces glyphs. + * + * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert. + * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove. + * + * @param[in] glyphIndex Where to replace the glyphs. + * @param[in] numberOfGlyphsToRemove The number of glyphs to be removed. + * @param[in] glyphs Pointer to a buffer with the new glyphs. + * @param[in] numberOfCharacters Pointer to a buffer with the number of characters per glyph. + * @param[in] numberOfGlyphsToInsert The number of new glyphs in the buffer. + */ + void ReplaceGlyphs( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const GlyphInfo* const glyphs, + const Length* const numberOfCharacters, + Length numberOfGlyphsToInsert ); + + // Character <--> Glyph conversion + + /** + * @brief Retrieves the first character in the logical model which a glyph represents. + * + * @note After shaping several characters may be represented by the same glyph. + * Alternatively several glyphs may be required to display a character. + * @param[in] glyphIndex The glyph index. + * @return The character index. + */ + CharacterIndex GetCharacterIndex( GlyphIndex glyphIndex ) const; + + /** + * @brief Query the number of characters the glyph represents. + * + * @param[in] glyphIndex The glyph index. + * @return The number of characters represented by the glyph. + */ + Length GetCharactersPerGlyph( GlyphIndex glyphIndex ) const; + + /** + * @brief Retrieves the first glyph in the visual model which represents a given character. + * + * @note After shaping several characters may be represented by the same glyph. + * Alternatively several glyphs may be required to display a character. + * @param[in] characterIndex The character index. + * @return The glyph index. + */ + GlyphIndex GetGlyphIndex( CharacterIndex characterIndex ) const; + + /** + * @brief Retrieves the whole or part of the character to glyph conversion map. + * + * The size of the buffer needs to be big enough to copy the @p numberOfCharacters. + * + * @param[out] characterToGlyphMap Pointer to a buffer where the conversion map is copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + /** + * @brief Retrieves the whole or part of the glyph to character conversion map. + * + * The size of the buffer needs to be big enough to copy the @p numberOfGlyphs. + * + * @param[out] glyphToCharacter Pointer to a buffer where the conversion map is copied. + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs The number of glyphs. + */ + void GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieves for each glyph the number of characters the glyph represents. + * + * @param[out] charactersPerGlyph Pointer to a buffer where the number of characters for each glyph are copied. + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs The number of glyphs. + */ + void GetCharactersPerGlyphMap( Length* charactersPerGlyph, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieves for each character the number of glyphs the character is shaped. + * + * @param[out] glyphsPerCharacter Pointer to a buffer where the number of glyphs for each character are copied. + * @param[in] characterIndex Index to the first character. + * @param[in] numberOfCharacters The number of characters. + */ + void GetGlyphsPerCharacterMap( Length* glyphsPerCharacter, + CharacterIndex characterIndex, + Length numberOfCharacters ) const; + + // Position interface + + /** + * @brief Replaces any glyph positions previously set. + * + * @note If the number of glyphs is zero the position buffer is cleared. + * + * @param[in] glyphPositions An array of visual positions for each glyph. + * @param[in] numberOfGlyphs The number of positions. + */ + void SetGlyphPositions( const Vector2* glyphPositions, + Length numberOfGlyphs ); + + /** + * @brief Retrieves the number of glyph positions set. + * + * @note This may be less than the number of glyphs in the model. + * @return The number of glyphs. + */ + Length GetNumberOfGlyphPositions() const; + + /** + * @brief Retrieves the glyph positions. + * + * @pre The size of the @p positions buffer needs to be big enough to copy the @p numberOfGlyphs positions. + * @param[out] glyphPositions Pointer to a buffer where the glyph positions are copied. + * @param[in] glyphIndex Index to the first glyph position. + * @param[in] numberOfGlyphs The number of positions to be copied. + */ + void GetGlyphPositions( Vector2* glyphPositions, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieve the glyph's position of the given glyph. + * + * @param[in] glyphIndex Index to the glyph. + * + * @return The glyph's position. + */ + const Vector2& GetGlyphPosition( GlyphIndex glyphIndex ) const; + + /** + * @brief Replaces glyph's positions. + * + * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert. + * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove. + * + * @param[in] glyphIndex Where to replace the glyph's positions. + * @param[in] numberOfGlyphsToRemove The number of glyph's positions to be removed. + * @param[in] positions Pointer to a buffer with the new glyph's positions. + * @param[in] numberOfGlyphsToInsert The number of new glyph's positions in the buffer. + */ + void ReplaceGlyphPositions( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const Vector2* const positions, + Length numberOfGlyphsToInsert ); + + // Line interface. + + /** + * @brief Sets the lines. + * + * Replaces any lines previously set. + * + * Every line is an item run containing the index to the first glyph of the line and the number of glyphs. + * + * @note If the number of lines is zero or the pointer is NULL, the lines buffer is cleared. + * + * @param[in] lines Pointer to a buffer containing all the line runs. + * @param[in] numberOfLines The number of lines in the buffer. + */ + void SetLines( const LineRun* const lines, + Length numberOfLines ); + + /** + * @brief Retrieves the number of lines of the whole text. + * + * @return The number of lines. + */ + Length GetNumberOfLines() const; + + /** + * @brief Retrieves lines. + * + * The size of the @p lines buffer needs to be big enough to copy the @p numberOfLines. + * + * @param[out] lines Pointer to a buffer where the lines are copied. + * @param[in] lineIndex Index to the first line. + * @param[in] numberOfLines Number of lines to be copied. + */ + void GetLines( LineRun* lines, + LineIndex lineIndex, + Length numberOfLines ) const; + + /** + * @brief Retrieves the number of lines and the index to the first line where the given range of glyphs is laid out. + * + * @param[in] glyphIndex Index to the first glyph. + * @param[in] numberOfGlyphs The number of glyph. + * @param[out] firstLine Index to the line containing the glyph index. + * @param[out] numberOfLines The number of lines. + */ + void GetNumberOfLines( GlyphIndex glyphIndex, + Length numberOfGlyphs, + LineIndex& firstLine, + Length& numberOfLines ) const; + /** + * @brief Retrieves the lines where the given range of glyphs is laid out. + * + * The size of the @p lines buffer needs to be big enough to copy the @p numberOfLines. + * + * @param[out] lines Pointer to a buffer where the lines are copied. + * @param[in] glyphIndex Index to the first glyphs of the range. + * @param[in] numberOfGlyphs Number of glyphs in the range. + */ + void GetLinesOfGlyphRange( LineRun* lines, + GlyphIndex glyphIndex, + Length numberOfGlyphs ) const; + + /** + * @brief Retrieves the line index where the glyph is laid-out. + * + * @param[in] glyphIndex The glyph's index. + * + * @return The line index. + */ + LineIndex GetLineOfGlyph( GlyphIndex glyphIndex ); + + /** + * @brief Retrieves the line index where the character is laid-out. + * + * @param[in] characterIndex The character's index. + * + * @return The line index. + */ + LineIndex GetLineOfCharacter( CharacterIndex characterIndex ); + + /** + * @brief Replaces lines for the given range of glyphs. + * + * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert. + * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove. + * + * @param[in] glyphIndex Index of the first glyph where to replace the line info. + * @param[in] numberOfGlyphsToRemove The number of glyphs to be the line info removed. + * @param[in] lines Pointer to a buffer with the lines. + * @param[in] numberOfGlyphsToInsert The number of characters to be the line info inserted. + */ + void ReplaceLines( GlyphIndex glyphIndex, + Length numberOfGlyphsToRemove, + const LineRun* const lines, + Length numberOfGlyphsToInsert ); + + // Size interface + + /** + * @brief Sets the natural size. + * + * @param[in] size The text's natural size. + */ + void SetNaturalSize( const Vector2& size ); + + /** + * @brief Retrieves the natural size. + * + * @return The text's natural size. + */ + const Vector2& GetNaturalSize() const; + + /** + * @brief Sets the text's actual size after it has been laid out. + * + * @param[in] size The text's size. + */ + void SetActualSize( const Vector2& size ); + + /** + * @brief Retrieves the text's actual size after it has been laid out. + * + * @return The text's size. + */ + const Vector2& GetActualSize() const; + + /** + * @brief Set the text's color + * + * @param[in] textColor The text's color + */ + void SetTextColor( const Vector4& textColor ); + + /** + * @brief Retrieve the text's color + * + * @return The text's color + */ + const Vector4& GetTextColor() const; + + /** + * @brief Sets the text's shadow offset. + * + * @param[in] shadowOffset The shadow offset, 0,0 indicates no shadow. + */ + void SetShadowOffset( const Vector2& shadowOffset ); + + /** + * @brief Retrieves the text's shadow offset. + * + * @return The text's shadow offset, 0,0 indicates no shadow. + */ + const Vector2& GetShadowOffset() const; + + /** + * @brief Sets the text's shadow color. + * + * @param[in] shadowColor The shadow color. + */ + void SetShadowColor( const Vector4& shadowColor ); + + /** + * @brief Retrieves the text's shadow color. + * + * @return The text's shadow color. + */ + const Vector4& GetShadowColor() const; + + /** + * @brief Sets the text's underline color. + * + * @param[in] color The text's underline color. + */ + void SetUnderlineColor( const Vector4& color ); + + /** + * @brief Retrieves the text's underline color. + * + * @return The text's underline color. + */ + const Vector4& GetUnderlineColor() const; + + /** + * @brief Sets the text underline flag. + * + * @param[in] enabled true if underlined. + */ + void SetUnderlineEnabled( bool enabled ); + + /** + * @brief Returns whether the text is underlined or not. + * + * @return underline state. + */ + bool IsUnderlineEnabled() const; + + /** + * @brief Clear the caches. + */ + void ClearCaches(); + + /** + * @brief Set the override used for underline height, 0 indicates height will be come from font metrics + * + * @param[in] height The height in pixels of the underline + */ + void SetUnderlineHeight( float height ); + + /** + * @brief Retrieves the underline height override + * + * @return Returns the override height for an underline, 0 indicates that font metrics will determine the height + */ + float GetUnderlineHeight() const; + +protected: + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~VisualModel(); + +private: + + /** + * @brief Private constructor. + */ + VisualModel(); + + // Undefined + VisualModel( const VisualModel& handle ); + + // Undefined + VisualModel& operator=( const VisualModel& handle ); + +public: + + Vector mGlyphs; ///< For each glyph, the font's id, glyph's index within the font and glyph's metrics. + Vector mGlyphsToCharacters; ///< For each glyph, the index of the first character. + Vector mCharactersToGlyph; ///< For each character, the index of the first glyph. + Vector mCharactersPerGlyph; ///< For each glyph, the number of characters that form the glyph. + Vector mGlyphsPerCharacter; ///< For each character, the number of glyphs that are shaped. + Vector mGlyphPositions; ///< For each glyph, the position. + Vector mLines; ///< The laid out lines. + + Vector4 mTextColor; ///< The text color + Vector4 mShadowColor; ///< Color of drop shadow + Vector4 mUnderlineColor; ///< Color of underline + Vector2 mShadowOffset; ///< Offset for drop shadow, 0 indicates no shadow + float mUnderlineHeight; ///< Fixed height for underline to override font metrics. + + + +private: + + Size mNaturalSize; ///< Size of the text with no line wrapping. + Size mActualSize; ///< Size of the laid-out text considering the layout properties set. + + // Caches to increase performance in some consecutive operations. + LineIndex mCachedLineIndex; ///< Used to increase performance in consecutive calls to GetLineOfGlyph() or GetLineOfCharacter() with consecutive glyphs or characters. + +public: + + bool mUnderlineEnabled:1; ///< Underline enabled flag + bool mUnderlineColorSet:1; ///< Has the underline color been explicitly set? + +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_VISUAL_MODEL_IMPL_H__ diff --git a/dali-toolkit/internal/transition-effects/cube-transition-cross-effect-impl.cpp b/dali-toolkit/internal/transition-effects/cube-transition-cross-effect-impl.cpp index 975889d..5a0188a 100644 --- a/dali-toolkit/internal/transition-effects/cube-transition-cross-effect-impl.cpp +++ b/dali-toolkit/internal/transition-effects/cube-transition-cross-effect-impl.cpp @@ -127,11 +127,11 @@ void CubeTransitionCrossEffect::SetupAnimation(unsigned int actorIndex, float an mTiles[mContainerIndex][actorIndex].TranslateBy( resetTranslation ); mTiles[mContainerIndex][actorIndex].SetOrientation( Radian( angle), axis ); } - mAnimation.RotateTo( mBoxes[actorIndex], Radian( -angle ), axis, AlphaFunctions::EaseInOutSine ); + mAnimation.AnimateTo( Property( mBoxes[actorIndex], Actor::Property::ORIENTATION ), Quaternion( Radian( -angle ), axis ), AlphaFunctions::EaseInOutSine ); Vector3 position(mBoxes[actorIndex].GetCurrentPosition()); - mAnimation.MoveTo(mBoxes[actorIndex], position*mDisplacementRatio+Vector3(0.f,0.f,mCubeDisplacement), AlphaFunctions::Bounce); - mAnimation.ColorTo( mTiles[mContainerIndex^1][actorIndex], HALF_BRIGHTNESS, AlphaFunctions::EaseOut ); - mAnimation.ColorTo( mTiles[mContainerIndex][actorIndex], FULL_BRIGHTNESS, AlphaFunctions::EaseIn ); + mAnimation.AnimateTo( Property( mBoxes[actorIndex], Actor::Property::POSITION ), position * mDisplacementRatio + Vector3( 0.f, 0.f, mCubeDisplacement ), AlphaFunctions::Bounce ); + mAnimation.AnimateTo( Property( mTiles[mContainerIndex^1][actorIndex], Actor::Property::COLOR ), HALF_BRIGHTNESS, AlphaFunctions::EaseOut ); + mAnimation.AnimateTo( Property( mTiles[mContainerIndex][actorIndex], Actor::Property::COLOR ), FULL_BRIGHTNESS, AlphaFunctions::EaseIn ); } } // namespace Internal diff --git a/dali-toolkit/internal/transition-effects/cube-transition-effect-impl.cpp b/dali-toolkit/internal/transition-effects/cube-transition-effect-impl.cpp index 2872ffa..888322a 100644 --- a/dali-toolkit/internal/transition-effects/cube-transition-effect-impl.cpp +++ b/dali-toolkit/internal/transition-effects/cube-transition-effect-impl.cpp @@ -19,6 +19,7 @@ #include "cube-transition-effect-impl.h" // EXTERNAL INCLUDES +#include // for strcmp #include #include #include @@ -116,10 +117,10 @@ void CubeTransitionEffect::Initialize() // helper actor to create a off-screen image using shader effect mEmptyImage = ImageActor::New( placeHolder ); + mEmptyImage.SetRelayoutEnabled( false ); mEmptyImage.SetSize(Stage::GetCurrent().GetSize()); mEmptyImage.SetParentOrigin( ParentOrigin::CENTER ); mEmptyImage.SetAnchorPoint( AnchorPoint::CENTER ); - mEmptyImage.SetRelayoutEnabled( false ); mFullImageCreator = FullAreaImageCreator::New(); mEmptyImage.SetShaderEffect( mFullImageCreator ); Stage::GetCurrent().Add(mEmptyImage); @@ -140,9 +141,9 @@ void CubeTransitionEffect::Initialize() ImageActor CubeTransitionEffect::CreateTile( Image image, const Vector4& color ) { ImageActor tile = ImageActor::New( image ); + tile.SetRelayoutEnabled( false ); tile.SetParentOrigin( ParentOrigin::CENTER ); tile.SetAnchorPoint( AnchorPoint::CENTER ); - tile.SetRelayoutEnabled( false ); tile.SetSize( mTileSize ); tile.SetColorMode( Dali::USE_OWN_COLOR ); tile.SetColor( color ); diff --git a/dali-toolkit/internal/transition-effects/cube-transition-fold-effect-impl.cpp b/dali-toolkit/internal/transition-effects/cube-transition-fold-effect-impl.cpp index abffa6a..37a3a06 100644 --- a/dali-toolkit/internal/transition-effects/cube-transition-fold-effect-impl.cpp +++ b/dali-toolkit/internal/transition-effects/cube-transition-fold-effect-impl.cpp @@ -125,11 +125,11 @@ void CubeTransitionFoldEffect::SetupAnimation(unsigned int actorIndex, float ang sideTile.TranslateBy( resetTranslation ); sideTile.SetOrientation( Radian( angle), Vector3::YAXIS ); } - mAnimation.RotateTo( currentCube, Radian( -angle ), Vector3::YAXIS, AlphaFunctions::Linear ); + mAnimation.AnimateTo( Property( currentCube, Actor::Property::ORIENTATION ), Quaternion( Radian( -angle ), Vector3::YAXIS ), AlphaFunctions::Linear ); Vector3 position(currentCube.GetCurrentPosition()); - mAnimation.MoveTo(currentCube, Vector3( position.x*mDisplacementRatio, position.y, position.z ), AlphaFunctions::Bounce); - mAnimation.ColorTo( frontTile, HALF_BRIGHTNESS, AlphaFunctions::EaseOut ); - mAnimation.ColorTo( sideTile, FULL_BRIGHTNESS, AlphaFunctions::EaseIn ); + mAnimation.AnimateTo( Property( currentCube, Actor::Property::POSITION ), Vector3( position.x*mDisplacementRatio, position.y, position.z ), AlphaFunctions::Bounce ); + mAnimation.AnimateTo( Property( frontTile, Actor::Property::COLOR ), HALF_BRIGHTNESS, AlphaFunctions::EaseOut ); + mAnimation.AnimateTo( Property( sideTile, Actor::Property::COLOR ), FULL_BRIGHTNESS, AlphaFunctions::EaseIn ); } } // namespace Internal diff --git a/dali-toolkit/internal/transition-effects/cube-transition-wave-effect-impl.cpp b/dali-toolkit/internal/transition-effects/cube-transition-wave-effect-impl.cpp index 1f8ca0f..1b0063d 100644 --- a/dali-toolkit/internal/transition-effects/cube-transition-wave-effect-impl.cpp +++ b/dali-toolkit/internal/transition-effects/cube-transition-wave-effect-impl.cpp @@ -97,14 +97,14 @@ void CubeTransitionWaveEffect::OnStartTransition( Vector2 panPosition, Vector2 p // the delay value is within 0.f ~ 2.f*thirdAnimationDuration float delay = thirdAnimationDuration * CalculateDelay(x*mTileSize.width,y*mTileSize.height); - mAnimation.RotateTo( mBoxes[idx], Degree( -angle ), Vector3::YAXIS, - AlphaFunctions::EaseOutSine, delay, thirdAnimationDuration ); - mAnimation.MoveBy( mBoxes[idx], Vector3(0.f,0.f,-mCubeDisplacement), - AlphaFunctions::Bounce, delay, thirdAnimationDuration ); - mAnimation.ColorTo( mTiles[anotherIndex][idx], HALF_BRIGHTNESS, - AlphaFunctions::EaseOut, delay, thirdAnimationDuration ); - mAnimation.ColorTo( mTiles[mContainerIndex][idx], FULL_BRIGHTNESS, - AlphaFunctions::EaseIn, delay, thirdAnimationDuration ); + mAnimation.AnimateTo( Property( mBoxes[idx], Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( -angle ) ), Vector3::YAXIS ), + AlphaFunctions::EaseOutSine, TimePeriod( delay, thirdAnimationDuration ) ); + mAnimation.AnimateBy( Property( mBoxes[idx], Actor::Property::POSITION ), Vector3( 0.f, 0.f, -mCubeDisplacement ), + AlphaFunctions::Bounce, TimePeriod( delay, thirdAnimationDuration ) ); + mAnimation.AnimateTo( Property( mTiles[anotherIndex][idx], Actor::Property::COLOR ), HALF_BRIGHTNESS, + AlphaFunctions::EaseOut, TimePeriod( delay, thirdAnimationDuration ) ); + mAnimation.AnimateTo( Property( mTiles[mContainerIndex][idx], Actor::Property::COLOR ), FULL_BRIGHTNESS, + AlphaFunctions::EaseIn, TimePeriod( delay, thirdAnimationDuration ) ); } } diff --git a/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.cpp b/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.cpp new file mode 100644 index 0000000..62389fa --- /dev/null +++ b/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2014 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + + +namespace Dali +{ + +namespace Toolkit +{ + +BubbleEmitter::BubbleEmitter() +{ +} + +BubbleEmitter::~BubbleEmitter() +{ +} + +BubbleEmitter::BubbleEmitter( Internal::BubbleEmitter& implementation ) +: Control( implementation ) +{ +} + +BubbleEmitter::BubbleEmitter(Dali::Internal::CustomActor* internal) +: Control( internal ) +{ + VerifyCustomActorPointer( internal ); +} + +BubbleEmitter BubbleEmitter::New( const Vector2& winSize, + Image shapeImage, + unsigned int maximumNumberOfBubble, + const Vector2& bubbleSizeRange ) +{ + return Internal::BubbleEmitter::New( winSize, shapeImage, maximumNumberOfBubble, bubbleSizeRange ); +} + +BubbleEmitter::BubbleEmitter( const BubbleEmitter& handle ) +: Control( handle ) +{ +} + +BubbleEmitter& BubbleEmitter::operator=( const BubbleEmitter& rhs ) +{ + if( &rhs != this ) + { + Control::operator=(rhs); + } + return *this; +} + +BubbleEmitter BubbleEmitter::DownCast( BaseHandle handle ) +{ + return Control::DownCast( handle ); +} + +Actor BubbleEmitter::GetRootActor() +{ + return GetImpl(*this).GetRootActor(); +} + +void BubbleEmitter::SetBackground( Image bgImage, const Vector3& hsvDelta ) +{ + GetImpl(*this).SetBackground( bgImage, hsvDelta ); +} + +void BubbleEmitter::SetShapeImage( Image shapeImage ) +{ + GetImpl(*this).SetShapeImage( shapeImage ); +} + +void BubbleEmitter::SetBubbleScale( float scale ) +{ + GetImpl(*this).SetBubbleScale( scale ); +} + +void BubbleEmitter::SetBubbleDensity( unsigned int density ) +{ + GetImpl(*this).SetBubbleDensity( density ); +} + +void BubbleEmitter::SetBlendMode( bool enable ) +{ + GetImpl(*this).SetBlendMode( enable ); +} + +void BubbleEmitter::EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ) +{ + GetImpl(*this).EmitBubble( animation, emitPosition, direction, displacement ); +} + +void BubbleEmitter::StartExplosion( float duration, float multiple ) +{ + GetImpl(*this).StartExplosion( duration, multiple ); +} + +void BubbleEmitter::Restore() +{ + GetImpl(*this).Restore(); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.h b/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.h new file mode 100644 index 0000000..5648280 --- /dev/null +++ b/dali-toolkit/public-api/controls/bubble-effect/bubble-emitter.h @@ -0,0 +1,194 @@ +#ifndef __DALI_TOOLKIT_BUBBLE_EMMITER_H__ +#define __DALI_TOOLKIT_BUBBLE_EMMITER_H__ + +/* + * Copyright (c) 2014 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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal DALI_INTERNAL +{ + /** + * @brief BubbleEmitter implementation class. + */ + class BubbleEmitter; +} + +/** + * @brief BubbleEmitter is used to display lots of moving bubbles on the stage. + * + * This is done by applying BubbleEffect to multiple specifically created meshActors. + */ +class DALI_IMPORT_API BubbleEmitter : public Control +{ +public: + + /** + * @brief Create an empty BubbleEmitter handle. + */ + BubbleEmitter(); + + /** + * @brief Virtual destructor. + */ + ~BubbleEmitter(); + + /** + * @brief Create an initialized BubbleEmitter. + * + * @param[in] winSize The size of the bubble moving area, usually the same size as the background image actor. + * @param[in] shapeImage The alpha channnel of this texture defines the bubble shape. + * @param[in] maximumNumberOfBubble The maximum number of bubble needed. + * @param[in] bubbleSizeRange The size range of the bubbles; x component is the low bound, and y component is the up bound. + * @return The initialized BubbleEmitter object. + */ + static BubbleEmitter New( const Vector2& winSize, + Image shapeImage, + unsigned int maximumNumberOfBubble, + const Vector2& bubbleSizeRange ); + + + /** + * @brief Copy constructor. + * + * Creates another handle that points to the same real object + * @param[in] handle The handle to copy + */ + BubbleEmitter( const BubbleEmitter& handle ); + + /** + * @brief Assignment operator. + * + * Changes this handle to point to another real object + * @param[in] rhs The object to point at + * @return A reference to this + */ + BubbleEmitter& operator=( const BubbleEmitter& rhs ); + + /** + * @brief Downcast an Object handle to SuperBlurView. + * + * If handle points to a BubbleEmitter, the downcast produces valid handle. + * If not, the returned handle is left uninitialized. + * @param[in] handle Handle to an object + * @return handle to a BubbleEmitter or an uninitialized handle + */ + static BubbleEmitter DownCast( BaseHandle handle ); + + /** + * @brief Return the root actor of all bubbles, should then be added to stage. + * + * @return The bubble root actor. + */ + Actor GetRootActor(); + + /** + * @brief Set Background image. + * + * The bubbles pick color from this image with HSV values adjusted. + * @param[in] bgImage The background image which provide color to bubbles. + * @param[in] hsvDelta The hsv channel difference used to adjust the background image color. + * If set these vector as Vector3::Zero, original colors are used. + */ + void SetBackground( Image bgImage, const Vector3& hsvDelta ); + + /** + * @brief Set bubble shape. + * + * The bubble mesh is a rectangular patch, but its displayed shape is decided by the alpha channel of the shape image. + * @param[in] shapeImage The image whose alpha channel defines the bubble shape. + */ + void SetShapeImage( Image shapeImage ); + + /** + * @brief Set the scale factor applied to all the bubbles. + * + * @param [in] scale The scale factor applied on bubbles. + */ + void SetBubbleScale( float scale ); + + /** + * @brief Set the density of the bubble. + * + * Ideally every bubble's moving track is controlled by different uniforms in BubbleEffect shaders. + * To increase the density, 'density' number of bubbles are sharing one group of uniforms, but with random offsets between these bubbles. + * The available density is one to nine. The default density is five. + * By set the density bigger than one, instead of emit one bubble each time, a 'density' number of bubbles are emitted. + * @param[in] density The density of the bubble. + */ + void SetBubbleDensity( unsigned int density ); + + /** + * @brief Enable different blending mode for rendering. + * + * @param[in] enable If false, the default blending function for RenderableActor is used. + */ + void SetBlendMode( bool enable ); + + /** + * @brief Add a bubble movement to the animation. + * + * @param[in] animation The animation reference. + * By passing the animation into BubbleEmitter, the animation's duration and how many bubbles contained within this animation are freely decided in App. + * @param[in] emitPosition The start position of the bubble movement. + * @param[in] direction The direction used to constrain the bubble to move in an adjacent direction around it. + * @param[in] displacement The displacement used to bound the moving distance of the bubble. + */ + void EmitBubble( Animation& animation, const Vector2& emitPosition, const Vector2& direction, const Vector2& displacement ); + + /** + * @brief Start an animation to enlarge every activated bubble's size and moving speed. + * + * @param[in] duration The duration of the animation + * @param[in] multiple The bubble size and moving speed will be increased gradually to multiple speed during the animation. + */ + void StartExplosion( float duration, float multiple ); + + /** + * @brief Reset all the parameters controlling the bubbles after animation. + */ + void Restore(); + +public: // Not intended for developer use + + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The Control implementation. + */ + DALI_INTERNAL BubbleEmitter(Internal::BubbleEmitter& implementation); + + /** + * @brief Allows the creation of this Control from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor. + */ + explicit DALI_INTERNAL BubbleEmitter(Dali::Internal::CustomActor* internal); +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif /* __DALI_TOOLKIT_BUBBLE_EMMITER_H__ */ diff --git a/dali-toolkit/public-api/controls/buttons/push-button.cpp b/dali-toolkit/public-api/controls/buttons/push-button.cpp index d2ae939..d9e395e 100644 --- a/dali-toolkit/public-api/controls/buttons/push-button.cpp +++ b/dali-toolkit/public-api/controls/buttons/push-button.cpp @@ -76,7 +76,9 @@ PushButton PushButton::DownCast( BaseHandle handle ) void PushButton::SetButtonImage( Image image ) { - Dali::Toolkit::GetImplementation( *this ).SetButtonImage( ImageActor::New( image ) ); + Actor imageActor = ImageActor::New( image ); + imageActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + Dali::Toolkit::GetImplementation( *this ).SetButtonImage( imageActor ); } void PushButton::SetButtonImage( Actor image ) @@ -91,7 +93,9 @@ Actor PushButton::GetButtonImage() const void PushButton::SetBackgroundImage( Image image ) { - Dali::Toolkit::GetImplementation( *this ).SetBackgroundImage( ImageActor::New( image ) ); + Actor imageActor = ImageActor::New( image ); + imageActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + Dali::Toolkit::GetImplementation( *this ).SetBackgroundImage( imageActor ); } void PushButton::SetBackgroundImage( Actor image ) @@ -106,7 +110,9 @@ Actor PushButton::GetBackgroundImage() const void PushButton::SetSelectedImage( Image image ) { - Dali::Toolkit::GetImplementation( *this ).SetSelectedImage( ImageActor::New( image ) ); + Actor imageActor = ImageActor::New( image ); + imageActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + Dali::Toolkit::GetImplementation( *this ).SetSelectedImage( imageActor ); } void PushButton::SetSelectedImage( Actor image ) @@ -119,9 +125,26 @@ Actor PushButton::GetSelectedImage() const return Dali::Toolkit::GetImplementation( *this ).GetSelectedImage(); } +void PushButton::SetSelectedBackgroundImage( Image image ) +{ + Dali::Toolkit::GetImplementation( *this ).SetSelectedBackgroundImage( ImageActor::New( image ) ); +} + +void PushButton::SetSelectedBackgroundImage( Actor image ) +{ + Dali::Toolkit::GetImplementation( *this ).SetSelectedBackgroundImage( image ); +} + +Actor PushButton::GetSelectedBackgroundImage() const +{ + return Dali::Toolkit::GetImplementation( *this ).GetSelectedBackgroundImage(); +} + void PushButton::SetDisabledBackgroundImage( Image image ) { - Dali::Toolkit::GetImplementation( *this ).SetDisabledBackgroundImage( ImageActor::New( image ) ); + Actor imageActor = ImageActor::New( image ); + imageActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + Dali::Toolkit::GetImplementation( *this ).SetDisabledBackgroundImage( imageActor ); } void PushButton::SetDisabledBackgroundImage( Actor image ) @@ -136,7 +159,9 @@ Actor PushButton::GetDisabledBackgroundImage() const void PushButton::SetDisabledImage( Image image ) { - Dali::Toolkit::GetImplementation( *this ).SetDisabledImage( ImageActor::New( image ) ); + Actor imageActor = ImageActor::New( image ); + imageActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + Dali::Toolkit::GetImplementation( *this ).SetDisabledImage( imageActor ); } void PushButton::SetDisabledImage( Actor image ) diff --git a/dali-toolkit/public-api/controls/buttons/push-button.h b/dali-toolkit/public-api/controls/buttons/push-button.h index dfc3409..0b4fa5f 100644 --- a/dali-toolkit/public-api/controls/buttons/push-button.h +++ b/dali-toolkit/public-api/controls/buttons/push-button.h @@ -129,7 +129,12 @@ public: void SetButtonImage( Image image ); /** - * @copydoc SetButtonImage( Image image ) + * @brief SetButtonImage + * + * @param[in] image The Actor to be used as the button image. + * + * The natural size of the button would be the size of this Actor + * if it's larger than the background and label */ void SetButtonImage( Actor image ); @@ -148,7 +153,12 @@ public: void SetBackgroundImage( Image image ); /** - * @copydoc SetBackgroundImage( Image image ) + * @brief SetBackgroundImage + * + * @param[in] image The Actor to be used as the background image. + * + * The natural size of the button would be the size of this Actor + * if it's larger than the button and label */ void SetBackgroundImage( Actor image ); @@ -179,6 +189,25 @@ public: Actor GetSelectedImage() const; /** + * @brief Sets the selected background image. + * + * @param[in] image The selected background image. + */ + void SetSelectedBackgroundImage( Image image ); + + /** + * @copydoc SetSelectedBackgroundImage( Image image ) + */ + void SetSelectedBackgroundImage( Actor image ); + + /** + * @brief Gets the selected background image. + * + * @return An actor with the selected background image. + */ + Actor GetSelectedBackgroundImage() const; + + /** * @brief Sets the disabled background image. * * @param[in] image The disabled background image. diff --git a/dali-toolkit/public-api/controls/cluster/cluster-style.cpp b/dali-toolkit/public-api/controls/cluster/cluster-style.cpp index 6ef28a6..0e2d988 100644 --- a/dali-toolkit/public-api/controls/cluster/cluster-style.cpp +++ b/dali-toolkit/public-api/controls/cluster/cluster-style.cpp @@ -18,6 +18,9 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index 3aa01ef..d65c16b 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -19,11 +19,14 @@ #include // EXTERNAL INCLUDES +#include // for strcmp +#include #include #include -#include +#include #include #include +#include #include #include #include @@ -92,6 +95,36 @@ struct Background } }; +/** + * Creates a white coloured Mesh. + */ +Mesh CreateMesh() +{ + Vector3 white( Color::WHITE ); + + MeshData meshData; + + // Create vertices with a white color (actual color is set by actor color) + MeshData::VertexContainer vertices(4); + vertices[ 0 ] = MeshData::Vertex( Vector3( -0.5f, -0.5f, 0.0f ), Vector2::ZERO, white ); + vertices[ 1 ] = MeshData::Vertex( Vector3( 0.5f, -0.5f, 0.0f ), Vector2::ZERO, white ); + vertices[ 2 ] = MeshData::Vertex( Vector3( -0.5f, 0.5f, 0.0f ), Vector2::ZERO, white ); + vertices[ 3 ] = MeshData::Vertex( Vector3( 0.5f, 0.5f, 0.0f ), Vector2::ZERO, white ); + + // Specify all the faces + MeshData::FaceIndices faces; + faces.reserve( 6 ); // 2 triangles in Quad + faces.push_back( 0 ); faces.push_back( 3 ); faces.push_back( 1 ); + faces.push_back( 0 ); faces.push_back( 2 ); faces.push_back( 3 ); + + // Create the mesh data from the vertices and faces + meshData.SetMaterial( Material::New( "ControlMaterial" ) ); + meshData.SetVertices( vertices ); + meshData.SetFaceIndices( faces ); + meshData.SetHasColor( true ); + + return Mesh::New( meshData ); +} /** * Sets all the required properties for the background actor. @@ -106,8 +139,13 @@ void SetupBackgroundActor( Actor actor, Property::Index constrainingIndex, const actor.SetPositionInheritanceMode( USE_PARENT_POSITION_PLUS_LOCAL_POSITION ); actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); actor.SetZ( BACKGROUND_ACTOR_Z_POSITION ); - actor.SetRelayoutEnabled( true ); - actor.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); + actor.SetRelayoutEnabled( false ); + + Constraint constraint = Constraint::New( actor, + constrainingIndex, + EqualToConstraint() ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.Apply(); } } // unnamed namespace @@ -132,6 +170,7 @@ public: // Construction & Destruction Impl(Control& controlImpl) : mControlImpl( controlImpl ), + mStyleName(""), mBackground( NULL ), mStartingPinchScale( NULL ), mKeyEventSignal(), @@ -210,6 +249,12 @@ public: switch ( index ) { + case Toolkit::Control::Property::STYLE_NAME: + { + controlImpl.SetStyleName( value.Get< std::string >() ); + break; + } + case Toolkit::Control::Property::BACKGROUND_COLOR: { controlImpl.SetBackgroundColor( value.Get< Vector4 >() ); @@ -270,6 +315,12 @@ public: switch ( index ) { + case Toolkit::Control::Property::STYLE_NAME: + { + value = controlImpl.GetStyleName(); + break; + } + case Toolkit::Control::Property::BACKGROUND_COLOR: { value = controlImpl.GetBackgroundColor(); @@ -311,6 +362,7 @@ public: // Data Control& mControlImpl; + std::string mStyleName; Background* mBackground; ///< Only create the background if we use it Vector3* mStartingPinchScale; ///< The scale when a pinch gesture starts, TODO: consider removing this Toolkit::Control::KeyEventSignalType mKeyEventSignal; @@ -333,12 +385,14 @@ public: static PropertyRegistration PROPERTY_1; static PropertyRegistration PROPERTY_2; static PropertyRegistration PROPERTY_3; + static PropertyRegistration PROPERTY_4; }; // Properties registered without macro to use specific member variables. -PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "background-color", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); -PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "background-image", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); -PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "key-input-focus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +PropertyRegistration Control::Impl::PROPERTY_1( typeRegistration, "style-name", Toolkit::Control::Property::STYLE_NAME, Property::STRING, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +PropertyRegistration Control::Impl::PROPERTY_2( typeRegistration, "background-color", Toolkit::Control::Property::BACKGROUND_COLOR, Property::VECTOR4, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +PropertyRegistration Control::Impl::PROPERTY_3( typeRegistration, "background-image", Toolkit::Control::Property::BACKGROUND_IMAGE, Property::MAP, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); +PropertyRegistration Control::Impl::PROPERTY_4( typeRegistration, "key-input-focus", Toolkit::Control::Property::KEY_INPUT_FOCUS, Property::BOOLEAN, &Control::Impl::SetProperty, &Control::Impl::GetProperty ); Toolkit::Control Control::New() { @@ -366,13 +420,13 @@ Vector3 Control::GetNaturalSize() return mImpl->mNaturalSize; } -float Control::CalculateChildSize( const Dali::Actor& child, Dimension dimension ) +float Control::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) { // Could be overridden in derived classes. return CalculateChildSizeBase( child, dimension ); } -bool Control::RelayoutDependentOnChildren( Dimension dimension ) +bool Control::RelayoutDependentOnChildren( Dimension::Type dimension ) { return RelayoutDependentOnChildrenBase( dimension ); } @@ -455,6 +509,23 @@ LongPressGestureDetector Control::GetLongPressGestureDetector() const return mImpl->mLongPressGestureDetector; } +void Control::SetStyleName( const std::string& styleName ) +{ + if( styleName != mImpl->mStyleName ) + { + mImpl->mStyleName = styleName; + + // Apply new style + Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); + GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); + } +} + +const std::string& Control::GetStyleName() const +{ + return mImpl->mStyleName; +} + void Control::SetBackgroundColor( const Vector4& color ) { Background& background( mImpl->GetBackground() ); @@ -464,6 +535,17 @@ void Control::SetBackgroundColor( const Vector4& color ) // Just set the actor color background.actor.SetColor( color ); } + else + { + // Create Mesh Actor + MeshActor meshActor = MeshActor::New( CreateMesh() ); + + SetupBackgroundActor( meshActor, Actor::Property::SCALE, color ); + + // Set the background actor before adding so that we do not inform deriving classes + background.actor = meshActor; + Self().Add( meshActor ); + } background.color = color; } @@ -683,7 +765,7 @@ void Control::Initialize() Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get(); // Register for style changes - styleManager.StyleChangeSignal().Connect( this, &Control::DoStyleChange ); + styleManager.StyleChangeSignal().Connect( this, &Control::OnStyleChange ); // SetTheme GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); @@ -761,13 +843,13 @@ void Control::OnActivated() { } -void Control::OnThemeChange( Toolkit::StyleManager styleManager ) -{ - GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); -} - -void Control::OnFontChange( bool defaultFontChange, bool defaultFontSizeChange ) +void Control::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) { + // By default the control is only interested in theme (not font) changes + if( change.themeChange ) + { + GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); + } } void Control::OnPinch(const PinchGesture& pinch) @@ -818,11 +900,11 @@ void Control::OnControlSizeSet( const Vector3& size ) { } -void Control::OnCalculateRelayoutSize( Dimension dimension ) +void Control::OnCalculateRelayoutSize( Dimension::Type dimension ) { } -void Control::OnLayoutNegotiated( float size, Dimension dimension ) +void Control::OnLayoutNegotiated( float size, Dimension::Type dimension ) { } @@ -834,7 +916,7 @@ void Control::OnRelayout( const Vector2& size, RelayoutContainer& container ) } } -void Control::OnSetResizePolicy( ResizePolicy policy, Dimension dimension ) +void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) { } @@ -937,18 +1019,6 @@ void Control::SignalDisconnected( SlotObserver* slotObserver, CallbackBase* call mImpl->SignalDisconnected( slotObserver, callback ); } -void Control::DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change ) -{ - if( change.themeChange ) - { - OnThemeChange( styleManager ); - } - else if( change.defaultFontChange || change.defaultFontSizeChange ) - { - OnFontChange( change.defaultFontChange, change.defaultFontSizeChange ); - } -} - } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/public-api/controls/control-impl.h b/dali-toolkit/public-api/controls/control-impl.h index 2583450..5c29c39 100644 --- a/dali-toolkit/public-api/controls/control-impl.h +++ b/dali-toolkit/public-api/controls/control-impl.h @@ -170,6 +170,16 @@ public: // Background /** + * @copydoc Dali::Toolkit::Control::SetStyleName + */ + void SetStyleName( const std::string& styleName ); + + /** + * @copydoc Dali::Toolkit::Control::GetStyleName + */ + const std::string& GetStyleName() const; + + /** * @copydoc Dali::Toolkit::Control::SetBackgroundColor */ void SetBackgroundColor( const Vector4& color ); @@ -374,7 +384,7 @@ protected: /** * @copydoc Dali::CustomActorImpl::RelayoutDependentOnChildren() */ - virtual bool RelayoutDependentOnChildren( Dimension dimension = ALL_DIMENSIONS ); + virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); private: @@ -395,21 +405,12 @@ private: virtual void OnActivated(); /** - * @brief This method should be overridden by deriving classes when - * they wish to be notified when the style manager changes the theme. + * @brief This method should be overridden by deriving classes requiring notifications when the style changes. * * @param[in] styleManager The StyleManager object. + * @param[in] change Information denoting what has changed. */ - virtual void OnThemeChange( Toolkit::StyleManager styleManager ); - - /** - * @brief This method should be overridden by deriving classes when - * they wish to be notified when the style changes the default font. - * - * @param[in] defaultFontChange Information denoting whether the default font has changed. - * @param[in] defaultFontSizeChange Information denoting whether the default font size has changed. - */ - virtual void OnFontChange( bool defaultFontChange, bool defaultFontSizeChange ); + virtual void OnStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); /** * @brief Called whenever a pinch gesture is detected on this control. @@ -549,12 +550,12 @@ private: /** * @copydoc Dali::CustomActorImpl::OnCalculateRelayoutSize() */ - virtual void OnCalculateRelayoutSize( Dimension dimension ); + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ); /** * @copydoc Dali::CustomActorImpl::OnLayoutNegotiated() */ - virtual void OnLayoutNegotiated( float size, Dimension dimension ); + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ); /** * @copydoc Dali::CustomActorImpl::OnRelayout() @@ -564,12 +565,12 @@ private: /** * @copydoc Dali::CustomActorImpl::OnSetResizePolicy() */ - virtual void OnSetResizePolicy( ResizePolicy policy, Dimension dimension ); + virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ); /** * @copydoc Dali::CustomActorImpl::CalculateChildSize() */ - virtual float CalculateChildSize( const Dali::Actor& child, Dimension dimension ); + virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ); // From CustomActorImpl, derived classes should NOT override these. @@ -646,16 +647,6 @@ private: */ virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback ); - // Style - - /** - * @brief This method is the callback for the StyleChangeSignal from StyleManager - * - * @param[in] styleManager The StyleManager Object - * @param[in] change Information denoting what has changed. - */ - DALI_INTERNAL void DoStyleChange( Toolkit::StyleManager styleManager, StyleChange change ); - private: // Undefined diff --git a/dali-toolkit/public-api/controls/control.cpp b/dali-toolkit/public-api/controls/control.cpp index a66f2ae..4ceae4f 100644 --- a/dali-toolkit/public-api/controls/control.cpp +++ b/dali-toolkit/public-api/controls/control.cpp @@ -104,6 +104,16 @@ LongPressGestureDetector Control::GetLongPressGestureDetector() const return GetImplementation().GetLongPressGestureDetector(); } +void Control::SetStyleName( const std::string& styleName ) +{ + GetImplementation().SetStyleName( styleName ); +} + +const std::string& Control::GetStyleName() const +{ + return GetImplementation().GetStyleName(); +} + void Control::SetBackgroundColor( const Vector4& color ) { GetImplementation().SetBackgroundColor( color ); diff --git a/dali-toolkit/public-api/controls/control.h b/dali-toolkit/public-api/controls/control.h index 1e6f8d9..b4373c7 100644 --- a/dali-toolkit/public-api/controls/control.h +++ b/dali-toolkit/public-api/controls/control.h @@ -82,7 +82,8 @@ public: { enum { - BACKGROUND_COLOR = PROPERTY_START_INDEX, ///< name "background-color", @see SetBackgroundColor, type Vector4 + STYLE_NAME = PROPERTY_START_INDEX, ///< name "style-name", @see SetStyleName, type std::string + BACKGROUND_COLOR, ///< name "background-color", @see SetBackgroundColor, type Vector4 BACKGROUND_IMAGE, ///< name "background-image", @see SetBackgroundImage, type Map KEY_INPUT_FOCUS, ///< name "key-input-focus", @see SetKeyInputFocus, type bool }; @@ -245,6 +246,22 @@ public: // Background /** + * @brief Sets the name of the style to be applied to the control. + * + * @param[in] styleName A string matching a style described in a stylesheet. + */ + void SetStyleName( const std::string& styleName ); + + /** + * @brief Retrieves the name of the style to be applied to the control (if any). + * + * @return A string matching a style or an empty string. + */ + const std::string& GetStyleName() const; + + // Background + + /** * @brief Sets the background color of the control. * * @param[in] color The required background color of the control diff --git a/dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp b/dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp index 1474151..5a6ae0e 100644 --- a/dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp +++ b/dali-toolkit/public-api/controls/default-controls/solid-color-actor.cpp @@ -83,7 +83,6 @@ ImageActor CreateSolidColorActor( const Vector4& color, bool border, const Vecto imageData.Update(); image = ImageActor::New( imageData ); - image.SetAnchorPoint( AnchorPoint::CENTER ); image.SetParentOrigin( ParentOrigin::CENTER ); if( border ) diff --git a/dali-toolkit/public-api/controls/navigation-frame/navigation-bar-style.h b/dali-toolkit/public-api/controls/navigation-frame/navigation-bar-style.h index 9df024c..4a06591 100644 --- a/dali-toolkit/public-api/controls/navigation-frame/navigation-bar-style.h +++ b/dali-toolkit/public-api/controls/navigation-frame/navigation-bar-style.h @@ -105,8 +105,6 @@ namespace Toolkit * Constructor */ NaviTitleBarStyle( Actor background, - TextStyle titleTextStyle, - TextStyle subtitleTextStyle, int referenceWidth, int height, int titleHeightWithoutSubtitle, @@ -120,7 +118,6 @@ namespace Toolkit int buttonBottomMargin, int gapBetweenButtons ) : BasicNaviBarStyle( background, referenceWidth, height), - titleTextStyle( titleTextStyle ), subtitleTextStyle( subtitleTextStyle ), titleHeightWithoutSubtitle( titleHeightWithoutSubtitle ), titleHeightWithSubtitle( titleHeightWithSubtitle ), subtitleHeight( subtitleHeight ), titleLeftMargin( titleLeftMargin ), titleBottomMargin( titleBottomMargin ), @@ -130,8 +127,6 @@ namespace Toolkit { } - TextStyle titleTextStyle; ///< the text style of the tile text - TextStyle subtitleTextStyle; ///< the text style of the subtitle text int titleHeightWithoutSubtitle; ///< the height of the title when no subtitle exists int titleHeightWithSubtitle; ///< the height of the title when there is subtitle below int subtitleHeight; ///< the height of the subtitle diff --git a/dali-toolkit/public-api/controls/popup/popup.cpp b/dali-toolkit/public-api/controls/popup/popup.cpp index df8e42d..b557f01 100644 --- a/dali-toolkit/public-api/controls/popup/popup.cpp +++ b/dali-toolkit/public-api/controls/popup/popup.cpp @@ -87,12 +87,7 @@ void Popup::SetTitle( const std::string& text ) GetImpl(*this).SetTitle( text ); } -void Popup::SetTitle( TextView titleActor ) -{ - GetImpl(*this).SetTitle( titleActor ); -} - -TextView Popup::GetTitle() const +std::string Popup::GetTitle() const { return GetImpl(*this).GetTitle(); } diff --git a/dali-toolkit/public-api/controls/popup/popup.h b/dali-toolkit/public-api/controls/popup/popup.h index fc14389..1ab708b 100644 --- a/dali-toolkit/public-api/controls/popup/popup.h +++ b/dali-toolkit/public-api/controls/popup/popup.h @@ -20,7 +20,6 @@ // INTERNAL INCLUDES #include -#include namespace Dali { @@ -167,18 +166,11 @@ public: void SetTitle( const std::string& text ); /** - * @brief Sets a title for this Popup. - * - * @param[in] titleActor The TextView to appear as the heading for this Popup - */ - void SetTitle( TextView titleActor ); - - /** * @brief Gets the text (TextView) for this Popup. * - * @return The TextView representing this popup is returned. + * @return The text to appear as the heading for this Popup */ - TextView GetTitle() const; + std::string GetTitle() const; /** * @brief Adds a button to this Popup. diff --git a/dali-toolkit/public-api/controls/scrollable/item-view/depth-layout.cpp b/dali-toolkit/public-api/controls/scrollable/item-view/depth-layout.cpp index cce79c0..7b4e3f6 100644 --- a/dali-toolkit/public-api/controls/scrollable/item-view/depth-layout.cpp +++ b/dali-toolkit/public-api/controls/scrollable/item-view/depth-layout.cpp @@ -235,62 +235,62 @@ struct DepthPositionConstraint270 struct DepthRotationConstraint0 { - DepthRotationConstraint0(float angleRadians) + DepthRotationConstraint0(Radian angleRadians) : mTiltAngle(angleRadians) { } Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize) { - return Quaternion(0.0f, Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS); + return Quaternion( Radian( 0.0f ), Vector3::ZAXIS ) * Quaternion( mTiltAngle, Vector3::XAXIS ); } - float mTiltAngle; + Radian mTiltAngle; }; struct DepthRotationConstraint90 { - DepthRotationConstraint90(float angleRadians) + DepthRotationConstraint90(Radian angleRadians) : mTiltAngle(angleRadians) { } Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize) { - return Quaternion(1.5f * Math::PI, Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS); + return Quaternion( Radian( 1.5f * Math::PI ), Vector3::ZAXIS) * Quaternion( mTiltAngle, Vector3::XAXIS ); } - float mTiltAngle; + Radian mTiltAngle; }; struct DepthRotationConstraint180 { - DepthRotationConstraint180(float angleRadians) + DepthRotationConstraint180(Radian angleRadians) : mTiltAngle(angleRadians) { } Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize) { - return Quaternion(-Math::PI, Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS); + return Quaternion( Radian( -Math::PI ), Vector3::ZAXIS) * Quaternion( mTiltAngle, Vector3::XAXIS ); } - float mTiltAngle; + Radian mTiltAngle; }; struct DepthRotationConstraint270 { - DepthRotationConstraint270(float angleRadians) + DepthRotationConstraint270(Radian angleRadians) : mTiltAngle(angleRadians) { } Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize) { - return Quaternion(0.5f * Math::PI, Vector3::ZAXIS) * Quaternion(mTiltAngle, Vector3::XAXIS); + return Quaternion( Radian( 0.5f * Math::PI ), Vector3::ZAXIS) * Quaternion( mTiltAngle, Vector3::XAXIS ); } - float mTiltAngle; + Radian mTiltAngle; }; struct DepthColorConstraint @@ -450,12 +450,12 @@ float DepthLayout::GetRowSpacing() const void DepthLayout::SetTiltAngle(Degree angle) { - mImpl->mTiltAngle = Degree( Clamp(angle, -45.0f, 45.0f) ); + mImpl->mTiltAngle = Degree( Clamp( angle, -45.0f, 45.0f ) ); } Degree DepthLayout::GetTiltAngle() const { - return mImpl->mTiltAngle; + return Degree( mImpl->mTiltAngle ); } void DepthLayout::SetItemSizeFunction(ItemSizeFunction function) @@ -485,7 +485,7 @@ void DepthLayout::SetItemTiltAngle(Degree angle) Degree DepthLayout::GetItemTiltAngle() const { - return mImpl->mItemTiltAngle; + return Degree( mImpl->mItemTiltAngle ); } void DepthLayout::SetColumnPositionFunction(ColumnPositionFunction function) @@ -575,7 +575,7 @@ void DepthLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 { if(animation) { - animation.Resize(actor, size); + animation.AnimateTo( Property( actor, Actor::Property::SIZE ), size ); } } @@ -673,19 +673,19 @@ Degree DepthLayout::GetScrollDirection() const if (mOrientation == ControlOrientation::Up) { - scrollDirection = 180.0f; + scrollDirection = Degree( 180.0f ); } else if (mOrientation == ControlOrientation::Left) { - scrollDirection = 270.0f; + scrollDirection = Degree( 270.0f ); } else if (mOrientation == ControlOrientation::Down) { - scrollDirection = 0.0f; + scrollDirection = Degree( 0.0f ); } else // mOrientation == ControlOrientation::Right { - scrollDirection = 90.0f; + scrollDirection = Degree( 90.0f ); } return scrollDirection; diff --git a/dali-toolkit/public-api/controls/scrollable/item-view/grid-layout.cpp b/dali-toolkit/public-api/controls/scrollable/item-view/grid-layout.cpp index efb16e2..35d5ab6 100644 --- a/dali-toolkit/public-api/controls/scrollable/item-view/grid-layout.cpp +++ b/dali-toolkit/public-api/controls/scrollable/item-view/grid-layout.cpp @@ -193,7 +193,7 @@ struct GridRotationConstraint0 { Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize) { - return Quaternion(0.0f, Vector3::ZAXIS); + return Quaternion( Radian( 0.0f ), Vector3::ZAXIS); } }; @@ -201,7 +201,7 @@ struct GridRotationConstraint90 { Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize) { - return Quaternion(1.5f * Math::PI, Vector3::ZAXIS); + return Quaternion( Radian( 1.5f * Math::PI ), Vector3::ZAXIS); } }; @@ -209,7 +209,7 @@ struct GridRotationConstraint180 { Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize) { - return Quaternion(Math::PI, Vector3::ZAXIS); + return Quaternion( Radian( Math::PI ), Vector3::ZAXIS); } }; @@ -217,7 +217,7 @@ struct GridRotationConstraint270 { Quaternion operator()(const Quaternion& current, const float& layoutPosition, const float& scrollSpeed, const Vector3& layoutSize) { - return Quaternion(0.5f * Math::PI, Vector3::ZAXIS); + return Quaternion( Radian( 0.5f * Math::PI ), Vector3::ZAXIS); } }; @@ -624,8 +624,8 @@ void GridLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 s // Do a nonlinear size animation to shrink the actor first when the actor size changes, // so that we can avoid the actors overlapping during orientation change. - animation.Resize( actor, shrink, AlphaFunctions::EaseOut, 0.0f, durationSeconds * 0.5f ); - animation.Resize( actor, size, AlphaFunctions::EaseIn, 0.0f, durationSeconds ); + animation.AnimateTo( Property( actor, Actor::Property::SIZE ), shrink, AlphaFunctions::EaseOut, TimePeriod( 0.0f, durationSeconds * 0.5f ) ); + animation.AnimateTo( Property( actor, Actor::Property::SIZE ), size, AlphaFunctions::EaseIn, TimePeriod( 0.0f, durationSeconds ) ); } } @@ -692,19 +692,19 @@ Degree GridLayout::GetScrollDirection() const if (mOrientation == ControlOrientation::Up) { - scrollDirection = 0.0f; + scrollDirection = Degree( 0.0f ); } else if (mOrientation == ControlOrientation::Left) { - scrollDirection = 90.0f; + scrollDirection = Degree( 90.0f ); } else if (mOrientation == ControlOrientation::Down) { - scrollDirection = 180.0f; + scrollDirection = Degree( 180.0f ); } else // mOrientation == ControlOrientation::Right { - scrollDirection = 270.0f; + scrollDirection = Degree( 270.0f ); } return scrollDirection; diff --git a/dali-toolkit/public-api/controls/scrollable/item-view/item-layout.cpp b/dali-toolkit/public-api/controls/scrollable/item-view/item-layout.cpp index 54809c3..918b9bb 100644 --- a/dali-toolkit/public-api/controls/scrollable/item-view/item-layout.cpp +++ b/dali-toolkit/public-api/controls/scrollable/item-view/item-layout.cpp @@ -19,7 +19,7 @@ #include // EXTERNAL INCLUDES -#include +#include #include #include @@ -29,82 +29,96 @@ namespace { - // Functors which wrap constraint functions with stored item IDs - struct WrappedQuaternionConstraint +// Lerps between current and target using the progress +template< typename Type > +void Lerp( Type& current, const Type& target, float progress ) +{ + current += ((target - current) * progress); +} + +// Functors which wrap constraint functions with stored item IDs +struct WrappedQuaternionConstraint +{ + WrappedQuaternionConstraint( Dali::Toolkit::ItemLayout::QuaternionFunction wrapMe, unsigned int itemId ) + :mWrapMe(wrapMe), + mItemId(itemId) { - WrappedQuaternionConstraint(Dali::Toolkit::ItemLayout::QuaternionFunction wrapMe, unsigned int itemId) - :mWrapMe(wrapMe), - mItemId(itemId) - { - } + } - Dali::Quaternion operator()(const Dali::Quaternion& current, const Dali::PropertyInput& layoutPosition, const Dali::PropertyInput& scrollSpeed, const Dali::PropertyInput& layoutSize) - { - float offsetLayoutPosition = layoutPosition.GetFloat() + static_cast(mItemId); + void operator()( Dali::Quaternion& current, const Dali::PropertyInputContainer& inputs ) + { + float offsetLayoutPosition = inputs[0]->GetFloat() + static_cast(mItemId); + float weight = inputs[3]->GetFloat(); - return mWrapMe(current, offsetLayoutPosition, scrollSpeed.GetFloat(), layoutSize.GetVector3()); - } + current = Dali::Quaternion::Slerp( current, mWrapMe( current, offsetLayoutPosition, inputs[1]->GetFloat(), inputs[2]->GetVector3() ), weight ); + } - Dali::Toolkit::ItemLayout::QuaternionFunction mWrapMe; - unsigned int mItemId; - }; + Dali::Toolkit::ItemLayout::QuaternionFunction mWrapMe; + unsigned int mItemId; +}; - struct WrappedVector3Constraint +struct WrappedVector3Constraint +{ + WrappedVector3Constraint( Dali::Toolkit::ItemLayout::Vector3Function wrapMe, unsigned int itemId ) + : mWrapMe(wrapMe), + mItemId(itemId) { - WrappedVector3Constraint(Dali::Toolkit::ItemLayout::Vector3Function wrapMe, unsigned int itemId) - : mWrapMe(wrapMe), - mItemId(itemId) - { - } + } - Dali::Vector3 operator()(const Dali::Vector3& current, const Dali::PropertyInput& layoutPosition, const Dali::PropertyInput& scrollSpeed, const Dali::PropertyInput& layoutSize) - { - float offsetLayoutPosition = layoutPosition.GetFloat() + static_cast(mItemId); + void operator()( Dali::Vector3& current, const Dali::PropertyInputContainer& inputs ) + { + float offsetLayoutPosition = inputs[0]->GetFloat() + static_cast(mItemId); + float weight = inputs[3]->GetFloat(); - return mWrapMe(current, offsetLayoutPosition, scrollSpeed.GetFloat(), layoutSize.GetVector3()); - } + Lerp( current, mWrapMe( current, offsetLayoutPosition, inputs[1]->GetFloat(), inputs[2]->GetVector3() ), weight ); + } - Dali::Toolkit::ItemLayout::Vector3Function mWrapMe; - unsigned int mItemId; - }; + Dali::Toolkit::ItemLayout::Vector3Function mWrapMe; + unsigned int mItemId; +}; - struct WrappedVector4Constraint +struct WrappedVector4Constraint +{ + WrappedVector4Constraint( Dali::Toolkit::ItemLayout::Vector4Function wrapMe, unsigned int itemId ) + : mWrapMe(wrapMe), + mItemId(itemId) { - WrappedVector4Constraint(Dali::Toolkit::ItemLayout::Vector4Function wrapMe, unsigned int itemId) - : mWrapMe(wrapMe), - mItemId(itemId) - { - } + } - Dali::Vector4 operator()(const Dali::Vector4& current, const Dali::PropertyInput& layoutPosition, const Dali::PropertyInput& scrollSpeed, const Dali::PropertyInput& layoutSize) - { - float offsetLayoutPosition = layoutPosition.GetFloat() + static_cast(mItemId); + void operator()( Dali::Vector4& current, const Dali::PropertyInputContainer& inputs ) + { + float offsetLayoutPosition = inputs[0]->GetFloat() + static_cast(mItemId); + float weight = inputs[3]->GetFloat(); - return mWrapMe(current, offsetLayoutPosition, scrollSpeed.GetFloat(), layoutSize.GetVector3()); - } + Lerp( current, mWrapMe( current, offsetLayoutPosition, inputs[1]->GetFloat(), inputs[2]->GetVector3() ), weight ); + } - Dali::Toolkit::ItemLayout::Vector4Function mWrapMe; - unsigned int mItemId; - }; + Dali::Toolkit::ItemLayout::Vector4Function mWrapMe; + unsigned int mItemId; +}; - struct WrappedBoolConstraint +struct WrappedBoolConstraint +{ + WrappedBoolConstraint( Dali::Toolkit::ItemLayout::BoolFunction wrapMe, unsigned int itemId ) + : mWrapMe(wrapMe), + mItemId(itemId) { - WrappedBoolConstraint(Dali::Toolkit::ItemLayout::BoolFunction wrapMe, unsigned int itemId) - : mWrapMe(wrapMe), - mItemId(itemId) - { - } + } - bool operator()(const bool& current, const Dali::PropertyInput& layoutPosition, const Dali::PropertyInput& scrollSpeed, const Dali::PropertyInput& layoutSize) - { - float offsetLayoutPosition = layoutPosition.GetFloat() + static_cast(mItemId); + void operator()( bool& current, const Dali::PropertyInputContainer& inputs ) + { + float weight = inputs[3]->GetFloat(); - return mWrapMe(current, offsetLayoutPosition, scrollSpeed.GetFloat(), layoutSize.GetVector3()); + if ( weight >= 1.0f ) + { + float offsetLayoutPosition = inputs[0]->GetFloat() + static_cast(mItemId); + current = mWrapMe( current, offsetLayoutPosition, inputs[1]->GetFloat(), inputs[2]->GetVector3() ); } + } - Dali::Toolkit::ItemLayout::BoolFunction mWrapMe; - unsigned int mItemId; - }; + Dali::Toolkit::ItemLayout::BoolFunction mWrapMe; + unsigned int mItemId; +}; } //Unnamed namespace @@ -115,8 +129,9 @@ namespace Toolkit { ItemLayout::ItemLayout() -: mOrientation(ControlOrientation::Up), - mAlphaFunction(Dali::Constraint::DEFAULT_ALPHA_FUNCTION) +: mOrientation( ControlOrientation::Up ), + mAlphaFunction( AlphaFunctions::Linear ), + mWeightObject() { } @@ -196,18 +211,22 @@ void ItemLayout::ApplyConstraints( Actor& actor, const int itemId, const float d Property::Index scrollSpeedProperty = itemView.GetPropertyIndex("item-view-scroll-speed"); Property::Index scrollPositionProperty = scrollPositionObject.GetPropertyIndex("scroll-position"); + // We want to animate the layout in so use a weight object to do this + if ( !mWeightObject ) + { + mWeightObject = WeightObject::New(); + } + ItemLayout::Vector3Function positionConstraint; if (GetPositionConstraint(itemId, positionConstraint)) { WrappedVector3Constraint wrapped(positionConstraint, itemId); - Constraint constraint = Constraint::New( Actor::Property::POSITION, - Source( scrollPositionObject, scrollPositionProperty ), - ParentSource( scrollSpeedProperty ), - ParentSource( Actor::Property::SIZE ), - wrapped ); - constraint.SetApplyTime(durationSeconds); - constraint.SetAlphaFunction(mAlphaFunction); - actor.ApplyConstraint(constraint); + Constraint constraint = Constraint::New( actor, Actor::Property::POSITION, wrapped ); + constraint.AddSource( Source( scrollPositionObject, scrollPositionProperty ) ); + constraint.AddSource( ParentSource( scrollSpeedProperty ) ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source( mWeightObject, WeightObject::WEIGHT ) ); + constraint.Apply(); } ItemLayout::QuaternionFunction rotationConstraint; @@ -215,15 +234,12 @@ void ItemLayout::ApplyConstraints( Actor& actor, const int itemId, const float d { WrappedQuaternionConstraint wrapped(rotationConstraint, itemId); - Constraint constraint = Constraint::New( Actor::Property::ORIENTATION, - Source( scrollPositionObject, scrollPositionProperty ), - ParentSource( scrollSpeedProperty ), - ParentSource( Actor::Property::SIZE ), - wrapped ); - constraint.SetApplyTime(durationSeconds); - constraint.SetAlphaFunction(mAlphaFunction); - - actor.ApplyConstraint(constraint); + Constraint constraint = Constraint::New( actor, Actor::Property::ORIENTATION, wrapped ); + constraint.AddSource( Source( scrollPositionObject, scrollPositionProperty ) ); + constraint.AddSource( ParentSource( scrollSpeedProperty ) ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source( mWeightObject, WeightObject::WEIGHT ) ); + constraint.Apply(); } ItemLayout::Vector3Function scaleConstraint; @@ -231,15 +247,12 @@ void ItemLayout::ApplyConstraints( Actor& actor, const int itemId, const float d { WrappedVector3Constraint wrapped(scaleConstraint, itemId); - Constraint constraint = Constraint::New( Actor::Property::SCALE, - Source( scrollPositionObject, scrollPositionProperty ), - ParentSource( scrollSpeedProperty ), - ParentSource( Actor::Property::SIZE ), - wrapped ); - constraint.SetApplyTime(durationSeconds); - constraint.SetAlphaFunction(mAlphaFunction); - - actor.ApplyConstraint(constraint); + Constraint constraint = Constraint::New( actor, Actor::Property::SCALE, wrapped ); + constraint.AddSource( Source( scrollPositionObject, scrollPositionProperty ) ); + constraint.AddSource( ParentSource( scrollSpeedProperty ) ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source( mWeightObject, WeightObject::WEIGHT ) ); + constraint.Apply(); } ItemLayout::Vector4Function colorConstraint; @@ -247,17 +260,13 @@ void ItemLayout::ApplyConstraints( Actor& actor, const int itemId, const float d { WrappedVector4Constraint wrapped(colorConstraint, itemId); - Constraint constraint = Constraint::New( Actor::Property::COLOR, - Source( scrollPositionObject, scrollPositionProperty ), - ParentSource( scrollSpeedProperty ), - ParentSource( Actor::Property::SIZE ), - wrapped ); - - constraint.SetApplyTime(durationSeconds); - constraint.SetAlphaFunction(mAlphaFunction); + Constraint constraint = Constraint::New( actor, Actor::Property::COLOR, wrapped ); + constraint.AddSource( Source( scrollPositionObject, scrollPositionProperty ) ); + constraint.AddSource( ParentSource( scrollSpeedProperty ) ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source( mWeightObject, WeightObject::WEIGHT ) ); constraint.SetRemoveAction(Dali::Constraint::Discard); - - actor.ApplyConstraint(constraint); + constraint.Apply(); } ItemLayout::BoolFunction visibilityConstraint; @@ -265,20 +274,25 @@ void ItemLayout::ApplyConstraints( Actor& actor, const int itemId, const float d { WrappedBoolConstraint wrapped(visibilityConstraint, itemId); - Constraint constraint = Constraint::New( Actor::Property::VISIBLE, - Source( scrollPositionObject, scrollPositionProperty ), - ParentSource( scrollSpeedProperty ), - ParentSource( Actor::Property::SIZE ), - wrapped ); - - constraint.SetApplyTime(durationSeconds); - constraint.SetAlphaFunction(mAlphaFunction); + Constraint constraint = Constraint::New( actor, Actor::Property::VISIBLE, wrapped ); + constraint.AddSource( Source( scrollPositionObject, scrollPositionProperty ) ); + constraint.AddSource( ParentSource( scrollSpeedProperty ) ); + constraint.AddSource( ParentSource( Actor::Property::SIZE ) ); + constraint.AddSource( Source( mWeightObject, WeightObject::WEIGHT ) ); // Release visibility constraints the same time as the color constraint constraint.SetRemoveAction(Dali::Constraint::Discard); - actor.ApplyConstraint(constraint); + constraint.Apply(); } + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add( 0.0f, 0.0f ); + keyFrames.Add( 1.0f, 1.0f ); + + Animation applyAnimation = Dali::Animation::New( durationSeconds ); + applyAnimation.AnimateBetween( Property( mWeightObject, WeightObject::WEIGHT ), keyFrames, mAlphaFunction, durationSeconds ); + applyAnimation.Play(); } } diff --git a/dali-toolkit/public-api/controls/scrollable/item-view/item-layout.h b/dali-toolkit/public-api/controls/scrollable/item-view/item-layout.h index 92659ed..ee9ca7d 100644 --- a/dali-toolkit/public-api/controls/scrollable/item-view/item-layout.h +++ b/dali-toolkit/public-api/controls/scrollable/item-view/item-layout.h @@ -19,6 +19,7 @@ */ // EXTERNAL INCLUDES +#include #include #include @@ -412,7 +413,8 @@ protected: protected: ControlOrientation::Type mOrientation; ///< the orientation of the layout. - AlphaFunction mAlphaFunction; /// 0.5f) ? 2.0f*(1.0f - progress) : progress*2.0f; float darkness(1.0f); @@ -489,7 +488,7 @@ void SpiralLayout::GetResizeAnimation(Animation& animation, Actor actor, Vector3 { if(animation) { - animation.Resize(actor, size); + animation.AnimateTo( Property( actor, Actor::Property::SIZE ), size ); } } @@ -568,19 +567,19 @@ Degree SpiralLayout::GetScrollDirection() const if (mOrientation == ControlOrientation::Up) { - scrollDirection = 0.0f - 45.0f; // Allow swiping horizontally & vertically + scrollDirection = Degree( -45.0f ); // Allow swiping horizontally & vertically } else if (mOrientation == ControlOrientation::Left) { - scrollDirection = 90.0f - 45.0f; + scrollDirection = Degree( 45.0f ); } else if (mOrientation == ControlOrientation::Down) { - scrollDirection = 180.0f - 45.0f; + scrollDirection = Degree( 180.0f - 45.0f ); } else // mOrientation == ControlOrientation::Right { - scrollDirection = 270.0f - 45.0f; + scrollDirection = Degree( 270.0f - 45.0f ); } return scrollDirection; diff --git a/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.cpp b/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.cpp index 48b21f1..995bfc2 100644 --- a/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.cpp +++ b/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.cpp @@ -30,31 +30,23 @@ namespace Dali namespace Toolkit { -Vector3 MoveActorConstraint(const Vector3& current, - const PropertyInput& scrollPositionProperty) +void MoveActorConstraint( Vector3& current, const PropertyInputContainer& inputs ) { - return current + scrollPositionProperty.GetVector3(); + current += inputs[0]->GetVector3(); } -Vector3 WrapActorConstraint(const Vector3& current, - const PropertyInput& actorScaleProperty, - const PropertyInput& actorAnchorPointProperty, - const PropertyInput& actorSizeProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& scrollWrap) +void WrapActorConstraint( Vector3& position, const PropertyInputContainer& inputs ) { - Vector3 position = current; - bool wrap = scrollWrap.GetBoolean(); + bool wrap = inputs[5]->GetBoolean(); if(wrap) { - const Vector3& min = scrollPositionMin.GetVector3(); - const Vector3& max = scrollPositionMax.GetVector3(); + const Vector3& min = inputs[3]->GetVector3(); + const Vector3& max = inputs[4]->GetVector3(); - const Vector3& anchor = actorAnchorPointProperty.GetVector3(); - const Vector3 scale = actorScaleProperty.GetVector3(); - const Vector3 size = actorSizeProperty.GetVector3(); + const Vector3& anchor = inputs[1]->GetVector3(); + const Vector3 scale = inputs[0]->GetVector3(); + const Vector3 size = inputs[2]->GetVector3(); if(fabsf(min.x - max.x) > Math::MACHINE_EPSILON_1) { @@ -70,8 +62,6 @@ Vector3 WrapActorConstraint(const Vector3& current, position.y = WrapInDomain(position.y + offsetY, min.y, max.y) - offsetY; } } - - return position; } } // namespace Toolkit diff --git a/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h b/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h index 9faba35..dcb8e34 100644 --- a/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h +++ b/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view-constraints.h @@ -19,8 +19,7 @@ */ // EXTERNAL INCLUDES - -// INTERNAL INCLUDES +#include namespace Dali { @@ -44,21 +43,14 @@ namespace Toolkit * * Moves an Actor in accordance to scroll position. */ -DALI_IMPORT_API Vector3 MoveActorConstraint(const Vector3& current, - const PropertyInput& scrollPositionProperty); +DALI_IMPORT_API void MoveActorConstraint( Vector3& current, const PropertyInputContainer& inputs ); /** * Wrap Actor constraint. * * Wraps an Actors position in accordance to min/max bounds of domain. */ -DALI_IMPORT_API Vector3 WrapActorConstraint(const Vector3& current, - const PropertyInput& actorScaleProperty, - const PropertyInput& actorAnchorPointProperty, - const PropertyInput& actorSizeProperty, - const PropertyInput& scrollPositionMin, - const PropertyInput& scrollPositionMax, - const PropertyInput& scrollWrap); +DALI_IMPORT_API void WrapActorConstraint( Vector3& position, const PropertyInputContainer& inputs ); } // namespace Toolkit diff --git a/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.cpp b/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.cpp index 9e8a9c7..be7a991 100644 --- a/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.cpp +++ b/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.cpp @@ -283,18 +283,6 @@ unsigned int FixedRuler::GetTotalPages() const // ScrollView /////////////////////////////////////////////////////////////////////////////////////////////////// -const std::string ScrollView::SCROLL_TIME_PROPERTY_NAME( "scroll-time" ); -const std::string ScrollView::SCROLL_POSITION_PROPERTY_NAME( "scroll-position" ); -const std::string ScrollView::SCROLL_PRE_POSITION_PROPERTY_NAME( "scroll-pre-position" ); -const std::string ScrollView::SCROLL_OVERSHOOT_X_PROPERTY_NAME( "scroll-overshoot-x" ); -const std::string ScrollView::SCROLL_OVERSHOOT_Y_PROPERTY_NAME( "scroll-overshoot-y" ); -const std::string ScrollView::SCROLL_FINAL_PROPERTY_NAME( "scroll-final" ); -const std::string ScrollView::SCROLL_WRAP_PROPERTY_NAME( "scroll-wrap" ); -const std::string ScrollView::SCROLL_PANNING_PROPERTY_NAME( "scroll-panning" ); -const std::string ScrollView::SCROLL_SCROLLING_PROPERTY_NAME( "scroll-scrolling" ); -const std::string ScrollView::SCROLL_POSITION_DELTA_PROPERTY_NAME( "scroll-position-delta" ); -const std::string ScrollView::SCROLL_START_PAGE_POSITION_PROPERTY_NAME( "scroll-start-page-position" ); - const float ScrollView::DEFAULT_SLOW_SNAP_ANIMATION_DURATION(0.5f); const float ScrollView::DEFAULT_FAST_SNAP_ANIMATION_DURATION(0.25f); const float ScrollView::DEFAULT_SNAP_OVERSHOOT_DURATION(0.5f); diff --git a/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h b/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h index 6cf6331..3ba77ed 100644 --- a/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h +++ b/dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h @@ -409,20 +409,6 @@ class DALI_IMPORT_API ScrollView : public Scrollable { public: - // Custom properties - - static const std::string SCROLL_TIME_PROPERTY_NAME; ///< Property, name "scroll-time", type float - static const std::string SCROLL_POSITION_PROPERTY_NAME; ///< Property, name "scroll-position", type Vector3 - static const std::string SCROLL_PRE_POSITION_PROPERTY_NAME; ///< Property, name "scroll-pre-position", type Vector3 - static const std::string SCROLL_OVERSHOOT_X_PROPERTY_NAME; ///< Property, name "scroll-overshoot-x", type float - static const std::string SCROLL_OVERSHOOT_Y_PROPERTY_NAME; ///< Property, name "scroll-overshoot-y", type float - static const std::string SCROLL_FINAL_PROPERTY_NAME; ///< Property, name "scroll-final", type Vector3 - static const std::string SCROLL_WRAP_PROPERTY_NAME; ///< Property, name "scroll-wrap", type bool - static const std::string SCROLL_PANNING_PROPERTY_NAME; ///< Property, name "scroll-panning", type bool - static const std::string SCROLL_SCROLLING_PROPERTY_NAME; ///< Property, name "scroll-scrolling", type bool - static const std::string SCROLL_POSITION_DELTA_PROPERTY_NAME; ///< Property, name "scroll-position-delta" type Vector3 - static const std::string SCROLL_START_PAGE_POSITION_PROPERTY_NAME; ///< Property, name "scroll-start-page-position" type Vector3 - // Default settings static const float DEFAULT_SLOW_SNAP_ANIMATION_DURATION; ///< Default Drag-Release animation time. @@ -457,6 +443,36 @@ public: float duration; ///< Duration of snap animation. }; + /** + * @brief The start and end property ranges for this control. + */ + enum PropertyRange + { + ANIMATABLE_PROPERTY_START_INDEX = Toolkit::Scrollable::ANIMATABLE_PROPERTY_END_INDEX + 1, + ANIMATABLE_PROPERTY_END_INDEX = ANIMATABLE_PROPERTY_START_INDEX + 1000 ///< Reserve animatable property indices + }; + + /** + * @brief An enumeration of properties belonging to the ScrollView class. + */ + struct Property + { + enum + { + SCROLL_POSITION = ANIMATABLE_PROPERTY_START_INDEX, ///< Property, name "scroll-position", type Vector3 + SCROLL_PRE_POSITION, ///< Property, name "scroll-pre-position", type Vector3 + OVERSHOOT_X, ///< Property, name "overshoot-x", type float + OVERSHOOT_Y, ///< Property, name "overshoot-y", type float + SCROLL_FINAL, ///< Property, name "scroll-final", type Vector3 + WRAP, ///< Property, name "wrap", type bool + PANNING, ///< Property, name "panning", type bool + SCROLLING, ///< Property, name "scrolling", type bool + SCROLL_DOMAIN_OFFSET, ///< Property, name "scroll-domain-offset" type Vector3 + SCROLL_POSITION_DELTA, ///< Property, name "scroll-position-delta" type Vector3 + START_PAGE_POSITION ///< Property, name "start-page-position" type Vector3 + }; + }; + typedef Signal< void ( const SnapEvent& ) > SnapStartedSignalType; ///< SnapStarted signal type /** diff --git a/dali-toolkit/public-api/controls/scrollable/scrollable.cpp b/dali-toolkit/public-api/controls/scrollable/scrollable.cpp index 1ce8314..ff955ff 100644 --- a/dali-toolkit/public-api/controls/scrollable/scrollable.cpp +++ b/dali-toolkit/public-api/controls/scrollable/scrollable.cpp @@ -26,11 +26,6 @@ namespace Dali namespace Toolkit { -const std::string Scrollable::SCROLL_RELATIVE_POSITION_PROPERTY_NAME( "scroll-relative-position" ); -const std::string Scrollable::SCROLL_POSITION_MIN_PROPERTY_NAME( "scroll-position-min" ); -const std::string Scrollable::SCROLL_POSITION_MAX_PROPERTY_NAME( "scroll-position-max" ); -const std::string Scrollable::SCROLL_DIRECTION_PROPERTY_NAME( "scroll-direction" ); - Scrollable::Scrollable() { } diff --git a/dali-toolkit/public-api/controls/scrollable/scrollable.h b/dali-toolkit/public-api/controls/scrollable/scrollable.h index 0b315f3..62f6100 100644 --- a/dali-toolkit/public-api/controls/scrollable/scrollable.h +++ b/dali-toolkit/public-api/controls/scrollable/scrollable.h @@ -59,20 +59,16 @@ public: OvershootIndicator, }; - // Custom properties - - static const std::string SCROLL_RELATIVE_POSITION_PROPERTY_NAME; ///< Property, name "scroll-relative-position", type Vector3 - static const std::string SCROLL_POSITION_MIN_PROPERTY_NAME; ///< Property, name "scroll-position-min", type Vector3 - static const std::string SCROLL_POSITION_MAX_PROPERTY_NAME; ///< Property, name "scroll-position-max", type Vector3 - static const std::string SCROLL_DIRECTION_PROPERTY_NAME; ///< Property, name "scroll-direction", type Vector2 - /** * @brief The start and end property ranges for this control. */ enum PropertyRange { PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, - PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices + PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000, ///< Reserve property indices + + ANIMATABLE_PROPERTY_START_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX, + ANIMATABLE_PROPERTY_END_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1000 ///< Reserve animatable property indices }; /** @@ -82,8 +78,17 @@ public: { enum { + // Event side properties OVERSHOOT_EFFECT_COLOR = PROPERTY_START_INDEX, ///< Property, name "overshoot-effect-color", @see SetOvershootEffectColor(), type Vector4 OVERSHOOT_ANIMATION_SPEED, ///< Property, name "overshoot-animation-speed", @see SetOvershootAnimationSpeed(), type float + + // Animatable properties + SCROLL_RELATIVE_POSITION = ANIMATABLE_PROPERTY_START_INDEX, ///< Property, name "scroll-relative-position", type Vector3 + SCROLL_POSITION_MIN, ///< Property, name "scroll-position-min", type Vector3 + SCROLL_POSITION_MAX, ///< Property, name "scroll-position-max", type Vector3 + SCROLL_DIRECTION, ///< Property, name "scroll-direction", type Vector2 + CAN_SCROLL_VERTICAL, ///< Property, name "can-scroll-vertical", type bool + CAN_SCROLL_HORIZONTAL ///< Property, name "can-scroll-horizontal", type bool }; }; diff --git a/dali-toolkit/public-api/controls/text-controls/text-field.cpp b/dali-toolkit/public-api/controls/text-controls/text-field.cpp new file mode 100644 index 0000000..7935752 --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-field.cpp @@ -0,0 +1,75 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +TextField TextField::New() +{ + return Internal::TextField::New(); +} + +TextField::TextField() +{ +} + +TextField::TextField( const TextField& handle ) +: Control( handle ) +{ +} + +TextField& TextField::operator=( const TextField& handle ) +{ + if( &handle != this ) + { + Control::operator=( handle ); + } + return *this; +} + +TextField::~TextField() +{ +} + +TextField TextField::DownCast( BaseHandle handle ) +{ + return Control::DownCast(handle); +} + +TextField::TextField( Internal::TextField& implementation ) +: Control(implementation) +{ +} + +TextField::TextField( Dali::Internal::CustomActor* internal ) +: Control( internal ) +{ + VerifyCustomActorPointer( internal ); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-controls/text-field.h b/dali-toolkit/public-api/controls/text-controls/text-field.h new file mode 100644 index 0000000..3736a2f --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-field.h @@ -0,0 +1,153 @@ +#ifndef __DALI_TOOLKIT_TEXT_FIELD_H__ +#define __DALI_TOOLKIT_TEXT_FIELD_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal DALI_INTERNAL +{ +class TextField; +} + +/** + * @brief A control which provides a single-line editable text field. + */ +class DALI_IMPORT_API TextField : public Control +{ +public: + + /** + * @brief The start and end property ranges for this control. + */ + enum PropertyRange + { + PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, + PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices + }; + + /** + * @brief An enumeration of properties belonging to the TextLabel class. + */ + struct Property + { + enum + { + RENDERING_BACKEND = PROPERTY_START_INDEX, ///< name "rendering-backend", The type or rendering e.g. bitmap-based, type INT + PLACEHOLDER_TEXT, ///< name "placeholder-text", The text to display when the TextField is empty, type STRING + 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 + POINT_SIZE, ///< name "point-size", The size of font in points, type FLOAT + EXCEED_POLICY, ///< name "exceed-policy" Specifies how the text is truncated when it does not fit, type INT + PRIMARY_CURSOR_COLOR, ///< name "primary-cursor-color", The color to apply to the primary cursor, type VECTOR4 + SECONDARY_CURSOR_COLOR, ///< name "secondary-cursor-color", The color to apply to the secondary cursor, type VECTOR4 + ENABLE_CURSOR_BLINK, ///< name "enable-cursor-blink", Whether the cursor should blink or not, type BOOLEAN + CURSOR_BLINK_INTERVAL, ///< name "cursor-blink-interval", The time interval between cursor on/off states, type FLOAT + CURSOR_BLINK_DURATION, ///< name "cursor-blink-duration", The cursor will stop blinking after this duration (if non-zero), type FLOAT + GRAB_HANDLE_IMAGE, ///< name "grab-handle-image", The image to display for grab handle, type STRING + DECORATION_BOUNDING_BOX, ///< name "decoration-bounding-box", The decorations (handles etc) will positioned within this area on-screen, type RECTANGLE + HORIZONTAL_ALIGNMENT, ///< name "horizontal-alignment", The line horizontal alignment, type STRING, values "BEGIN", "CENTER", "END" + VERTICAL_ALIGNMENT ///< name "vertical-alignment", The line vertical alignment, type STRING, values "TOP", "CENTER", "BOTTOM" + }; + }; + + /** + * @brief Specifies how the text is truncated when it does not fit + * + * The default value is \e EXCEED_POLICY_CLIP. + */ + enum ExceedPolicy + { + EXCEED_POLICY_ORIGINAL, ///< The text will be display at original size, and may exceed the TextField boundary. + EXCEED_POLICY_CLIP ///< The end of text will be clipped to fit within the TextField. + }; + + /** + * Create the TextField control. + * @return A handle to the TextField control. + */ + static TextField New(); + + /** + * @brief Creates an empty handle. + */ + TextField(); + + /** + * @brief Copy constructor. + * + * @param[in] handle The handle to copy from. + */ + TextField( const TextField& handle ); + + /** + * @brief Assignment operator. + * + * @param[in] handle The handle to copy from. + * @return A reference to this. + */ + TextField& operator=( const TextField& handle ); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~TextField(); + + /** + * @brief Downcast a handle to TextField. + * + * If the BaseHandle points is a TextField the downcast returns a valid handle. + * If not the returned handle is left empty. + * + * @param[in] handle Handle to an object + * @return handle to a TextField or an empty handle + */ + static TextField DownCast( BaseHandle handle ); + +public: // Not intended for application developers + + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The Control implementation. + */ + DALI_INTERNAL TextField( Internal::TextField& implementation ); + + /** + * @brief Allows the creation of this Control from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor. + */ + explicit DALI_INTERNAL TextField( Dali::Internal::CustomActor* internal ); +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_FIELD_H__ diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.cpp b/dali-toolkit/public-api/controls/text-controls/text-label.cpp new file mode 100644 index 0000000..7a61615 --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-label.cpp @@ -0,0 +1,83 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +TextLabel TextLabel::New() +{ + return Internal::TextLabel::New(); +} + +TextLabel TextLabel::New( const std::string& text ) +{ + TextLabel label = Internal::TextLabel::New(); + label.SetProperty( TextLabel::Property::TEXT, text ); + + return label; +} + +TextLabel::TextLabel() +{ +} + +TextLabel::TextLabel( const TextLabel& handle ) +: Control( handle ) +{ +} + +TextLabel& TextLabel::operator=( const TextLabel& handle ) +{ + if( &handle != this ) + { + Control::operator=( handle ); + } + return *this; +} + +TextLabel::~TextLabel() +{ +} + +TextLabel TextLabel::DownCast( BaseHandle handle ) +{ + return Control::DownCast(handle); +} + +TextLabel::TextLabel( Internal::TextLabel& implementation ) +: Control(implementation) +{ +} + +TextLabel::TextLabel( Dali::Internal::CustomActor* internal ) +: Control( internal ) +{ + VerifyCustomActorPointer( internal ); +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.h b/dali-toolkit/public-api/controls/text-controls/text-label.h new file mode 100644 index 0000000..b11bd13 --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-label.h @@ -0,0 +1,151 @@ +#ifndef __DALI_TOOLKIT_TEXT_LABEL_H__ +#define __DALI_TOOLKIT_TEXT_LABEL_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal DALI_INTERNAL +{ +class TextLabel; +} + +/** + * @brief A control which renders a short text string. + * + * Text labels are lightweight, non-editable and do not respond to user input. + */ +class DALI_IMPORT_API TextLabel : public Control +{ +public: + + /** + * @brief The start and end property ranges for this control. + */ + enum PropertyRange + { + PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, + PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices + }; + + /** + * @brief An enumeration of properties belonging to the TextLabel class. + */ + struct Property + { + enum + { + 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 + 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" + VERTICAL_ALIGNMENT, ///< name "vertical-alignment", The line vertical alignment, type STRING, values "TOP", "CENTER", "BOTTOM" + TEXT_COLOR, ///< name "text-color", The text color, type VECTOR4 + SHADOW_OFFSET, ///< name "shadow-offset", The drop shadow offset 0 indicates no shadow, type VECTOR2 + SHADOW_COLOR, ///< name "shadow-color", The color of a drop shadow, type VECTOR4 + UNDERLINE_ENABLED, ///< name "underline-enabled", The underline enabled flag, type BOOLEAN + UNDERLINE_COLOR, ///< name "underline-color", The color of the underline, type VECTOR4 + UNDERLINE_HEIGHT ///< name "underline-height", Overrides the underline height from font metrics, type FLOAT + }; + }; + + /** + * @brief Create the TextLabel control. + * + * @return A handle to the TextLabel control. + */ + static TextLabel New(); + + /** + * @brief Create the TextLabel control. + * + * @param[in] text The text to display. + * @return A handle to the TextLabel control. + */ + static TextLabel New( const std::string& text ); + + /** + * @brief Creates an empty handle. + */ + TextLabel(); + + /** + * @brief Copy constructor. + * + * @param[in] handle The handle to copy from. + */ + TextLabel( const TextLabel& handle ); + + /** + * @brief Assignment operator. + * + * @param[in] handle The handle to copy from. + * @return A reference to this. + */ + TextLabel& operator=( const TextLabel& handle ); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~TextLabel(); + + /** + * @brief Downcast a handle to TextLabel. + * + * If the BaseHandle points is a TextLabel the downcast returns a valid handle. + * If not the returned handle is left empty. + * + * @param[in] handle Handle to an object + * @return handle to a TextLabel or an empty handle + */ + static TextLabel DownCast( BaseHandle handle ); + +public: // Not intended for application developers + + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The Control implementation. + */ + DALI_INTERNAL TextLabel( Internal::TextLabel& implementation ); + + /** + * @brief Allows the creation of this Control from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor. + */ + explicit DALI_INTERNAL TextLabel( Dali::Internal::CustomActor* internal ); +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_TEXT_LABEL_H__ diff --git a/dali-toolkit/public-api/controls/text-controls/text-selection-popup.cpp b/dali-toolkit/public-api/controls/text-controls/text-selection-popup.cpp new file mode 100644 index 0000000..4c55375 --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-selection-popup.cpp @@ -0,0 +1,78 @@ +/* + * 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. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +using namespace Dali; + +namespace Dali +{ + +namespace Toolkit +{ + +TextSelectionPopup TextSelectionPopup::New() +{ + return Internal::TextSelectionPopup::New(); +} + +TextSelectionPopup::TextSelectionPopup() +{ +} + +TextSelectionPopup::TextSelectionPopup( const TextSelectionPopup& handle ) +: Control( handle ) +{ +} + +TextSelectionPopup& TextSelectionPopup::operator=( const TextSelectionPopup& handle ) +{ + if( &handle != this ) + { + Control::operator=( handle ); + } + return *this; +} + +TextSelectionPopup::~TextSelectionPopup() +{ +} + +TextSelectionPopup TextSelectionPopup::DownCast( BaseHandle handle ) +{ + return Control::DownCast(handle); +} + +TextSelectionPopup::TextSelectionPopup( Internal::TextSelectionPopup& implementation ) +: Control(implementation) +{ +} + +TextSelectionPopup::TextSelectionPopup( Dali::Internal::CustomActor* internal ) +: Control( internal ) +{ + VerifyCustomActorPointer( internal ); +} + + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-controls/text-selection-popup.h b/dali-toolkit/public-api/controls/text-controls/text-selection-popup.h new file mode 100644 index 0000000..2243f2d --- /dev/null +++ b/dali-toolkit/public-api/controls/text-controls/text-selection-popup.h @@ -0,0 +1,143 @@ +#ifndef __DALI_TOOLKIT_TEXT_SELECTION_POPUP_H__ +#define __DALI_TOOLKIT_TEXT_SELECTION_POPUP_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. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal DALI_INTERNAL +{ +class TextSelectionPopup; +} + +/** + * @brief A control which provides a Popup with a number of buttons + * + * The style of the pop can be set through style sheets, this includes the images for the buttons + * A Show and Hide API is provided. + * + * If the buttons exceed the size constraints of the popup then it will offer scrolling. + * + * + */ +class DALI_IMPORT_API TextSelectionPopup : public Control +{ +public: + + /** + * @brief The start and end property ranges for this control. + */ + enum PropertyRange + { + PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, + PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices + }; + + /** + * @brief An enumeration of properties belonging to the TextLabel class. + */ + struct Property + { + enum + { + + POPUP_MAX_SIZE, ///< name "popup-max-size", The max size the Popup can be, type VECTOR2 + POPUP_BACKGROUND_IMAGE, ///< name "popup-background-image", The image to display for popup background type STRING + POPUP_CLIPBOARD_BUTTON_ICON_IMAGE, ///< name "popup-clipboard-button-image", The image to use as the popup clipboard icon, type STRING + POPUP_CUT_BUTTON_ICON_IMAGE, ///< name "popup-cut-button-image", The image to use as the popup cut icon, type STRING + POPUP_COPY_BUTTON_ICON_IMAGE, ///< name "popup-copy-button-image", The image to use as the popup copy icon, type STRING + POPUP_PASTE_BUTTON_ICON_IMAGE, ///< name "popup-paste-button-image", The image to use as the popup paste icon, type STRING + POPUP_SELECT_BUTTON_ICON_IMAGE, ///< name "popup-select-button-image", The image to use as the popup select icon, type STRING + POPUP_SELECT_ALL_BUTTON_ICON_IMAGE, ///< name "popup-select-all-button-image", The image to use as the popup select all icon, type STRING + }; + }; + + /** + * Create the TextSelectionPopup control. + * @return A handle to the TextSelectionPopup control. + */ + static TextSelectionPopup New(); + + /** + * @brief Creates an empty handle. + */ + TextSelectionPopup(); + + /** + * @brief Copy constructor. + * + * @param[in] handle The handle to copy from. + */ + TextSelectionPopup( const TextSelectionPopup& handle ); + + /** + * @brief Assignment operator. + * + * @param[in] handle The handle to copy from. + * @return A reference to this. + */ + TextSelectionPopup& operator=( const TextSelectionPopup& handle ); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~TextSelectionPopup(); + + /** + * @brief Downcast a handle to TextSelectionPopup. + * + * If the BaseHandle points is a TextSelectionPopup the downcast returns a valid handle. + * If not the returned handle is left empty. + * + * @param[in] handle Handle to an object + * @return handle to a TextSelectionPopup or an empty handle + */ + static TextSelectionPopup DownCast( BaseHandle handle ); + +public: // Not intended for application developers + + /** + * @brief Creates a handle using the Toolkit::Internal implementation. + * + * @param[in] implementation The Control implementation. + */ + DALI_INTERNAL TextSelectionPopup( Internal::TextSelectionPopup& implementation ); + + /** + * @brief Allows the creation of this Control from an Internal::CustomActor pointer. + * + * @param[in] internal A pointer to the internal CustomActor. + */ + explicit DALI_INTERNAL TextSelectionPopup( Dali::Internal::CustomActor* internal ); + +}; // Class TextSelectionPopup + +} // namespace Toolkit + +} // namepsace Dali + +#endif // __DALI_TOOLKIT_TEXT_SELECTION_POPUP_H__ diff --git a/dali-toolkit/public-api/controls/text-input/text-input.cpp b/dali-toolkit/public-api/controls/text-input/text-input.cpp deleted file mode 100644 index f38b516..0000000 --- a/dali-toolkit/public-api/controls/text-input/text-input.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// CLASS HEADER -#include - -// EXTERNAL INCLUDES -#include -#include -#include -#include - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -TextInput::TextInput() -{ -} - -TextInput::TextInput(Internal::TextInput& implementation) -: Control(implementation) -{ -} - -TextInput::TextInput( const TextInput& textInput ) -: Control( textInput ) -{ -} - -TextInput& TextInput::operator=( const TextInput& textInput ) -{ - if( &textInput != this ) - { - Control::operator=( textInput ); - } - - return *this; -} - -TextInput TextInput::New() -{ - return Internal::TextInput::New(); -} - -TextInput TextInput::DownCast( BaseHandle actor ) -{ - return Control::DownCast(actor); -} - -TextInput::~TextInput() -{ -} - -std::string TextInput::GetText() const -{ - return GetImpl(*this).GetText(); -} - -std::string TextInput::GetMarkupText() const -{ - return GetImpl(*this).GetMarkupText(); -} - -void TextInput::SetMaxCharacterLength(std::size_t maxChars) -{ - GetImpl(*this).SetMaxCharacterLength(maxChars); -} - -void TextInput::SetNumberOfLinesLimit(std::size_t maxLines) -{ - GetImpl(*this).SetNumberOfLinesLimit( maxLines ); -} - -std::size_t TextInput::GetNumberOfLinesLimit() const -{ - return GetImpl(*this).GetNumberOfLinesLimit(); -} - -std::size_t TextInput::GetNumberOfCharacters() const -{ - return GetImpl(*this).GetNumberOfCharacters(); -} - -void TextInput::SetPlaceholderText( const std::string& placeHolderText ) -{ - GetImpl(*this).SetPlaceholderText( placeHolderText ); -} - -std::string TextInput::GetPlaceholderText() -{ - return GetImpl(*this).GetPlaceholderText(); -} - -void TextInput::SetInitialText(const std::string& initialText) -{ - GetImpl(*this).SetInitialText(initialText); -} - -void TextInput::SetEditable(bool editMode) -{ - GetImpl(*this).SetEditable(editMode, false); -} - -void TextInput::SetEditable(bool editMode, const Vector2& touchPoint) -{ - GetImpl(*this).SetEditable(editMode, true, touchPoint); -} - -bool TextInput::IsEditable() const -{ - return GetImpl(*this).IsEditable(); -} - -void TextInput::SetEditOnTouch( bool editOnTouch ) -{ - GetImpl(*this).SetEditOnTouch( editOnTouch ); -} - -bool TextInput::IsEditOnTouch() const -{ - return GetImpl(*this).IsEditOnTouch(); -} - -void TextInput::SetTextSelectable( bool textSelectable ) -{ - GetImpl(*this).SetTextSelectable( textSelectable ); -} - -bool TextInput::IsTextSelectable() const -{ - return GetImpl(*this).IsTextSelectable(); -} - -bool TextInput::IsTextSelected() const -{ - return GetImpl(*this).IsTextSelected(); -} - -void TextInput::SelectText(std::size_t start, std::size_t end) -{ - GetImpl(*this).SelectText( start, end ); -} - -void TextInput::DeSelectText() -{ - GetImpl(*this).DeSelectText(); -} - -void TextInput::SetGrabHandleImage( Image image ) -{ - GetImpl(*this).SetGrabHandleImage(image); -} - -void TextInput::SetCursorImage(Dali::Image image, const Vector4& border ) -{ - GetImpl(*this).SetCursorImage(image, border ); -} - -Vector3 TextInput::GetSelectionHandleSize() -{ - return GetImpl(*this).GetSelectionHandleSize(); -} - -void TextInput::SetRTLCursorImage(Dali::Image image, const Vector4& border ) -{ - GetImpl(*this).SetRTLCursorImage(image, border ); -} - -void TextInput::EnableGrabHandle(bool toggle) -{ - GetImpl(*this).EnableGrabHandle( toggle ); -} - -bool TextInput::IsGrabHandleEnabled() -{ - return GetImpl(*this).IsGrabHandleEnabled(); -} - -void TextInput::SetBoundingRectangle( const Rect& boundingOriginAndSize ) -{ - GetImpl(*this).SetBoundingRectangle( boundingOriginAndSize ); -} - -const Rect TextInput::GetBoundingRectangle() const -{ - return GetImpl(*this).GetBoundingRectangle(); -} - -void TextInput::SetActiveStyle( const TextStyle& style, const TextStyle::Mask mask ) -{ - GetImpl(*this).SetActiveStyle(style,mask); -} - -void TextInput::ApplyStyle( const TextStyle& style, const TextStyle::Mask mask ) -{ - GetImpl(*this).ApplyStyle( style, mask ); -} - -void TextInput::ApplyStyleToAll( const TextStyle& style, const TextStyle::Mask mask ) -{ - GetImpl(*this).ApplyStyleToAll( style, mask ); -} - -TextStyle TextInput::GetStyleAtCursor() const -{ - return GetImpl(*this).GetStyleAtCursor(); -} - -void TextInput::SetTextAlignment( Toolkit::Alignment::Type align ) -{ - GetImpl(*this).SetTextAlignment(align); -} - -void TextInput::SetTextLineJustification( Toolkit::TextView::LineJustification justification ) -{ - GetImpl(*this).SetTextLineJustification(justification); -} - -void TextInput::SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ) -{ - GetImpl(*this).SetFadeBoundary( fadeBoundary ); -} - -const Toolkit::TextView::FadeBoundary& TextInput::GetFadeBoundary() const -{ - return GetImpl(*this).GetFadeBoundary(); -} - -Alignment::Type TextInput::GetTextAlignment() const -{ - return GetImpl(*this).GetTextAlignment(); -} - -void TextInput::SetMultilinePolicy( TextView::MultilinePolicy policy ) -{ - GetImpl(*this).SetMultilinePolicy(policy); -} - -TextView::MultilinePolicy TextInput::GetMultilinePolicy() const -{ - return GetImpl(*this).GetMultilinePolicy(); -} - -void TextInput::SetWidthExceedPolicy( TextView::ExceedPolicy policy ) -{ - GetImpl(*this).SetWidthExceedPolicy(policy); -} - -TextView::ExceedPolicy TextInput::GetWidthExceedPolicy() const -{ - return GetImpl(*this).GetWidthExceedPolicy(); -} - -void TextInput::SetHeightExceedPolicy( TextView::ExceedPolicy policy ) -{ - GetImpl(*this).SetHeightExceedPolicy(policy); -} - -TextView::ExceedPolicy TextInput::GetHeightExceedPolicy() const -{ - return GetImpl(*this).GetHeightExceedPolicy(); -} - -void TextInput::SetExceedEnabled( bool enable ) -{ - GetImpl(*this).SetExceedEnabled( enable ); -} - -bool TextInput::GetExceedEnabled() const -{ - return GetImpl(*this).GetExceedEnabled(); -} - -void TextInput::SetSortModifier( float depthOffset ) -{ - GetImpl( *this ).SetSortModifier( depthOffset ); -} - -void TextInput::SetSnapshotModeEnabled( bool enable ) -{ - GetImpl( *this ).SetSnapshotModeEnabled( enable ); -} - -bool TextInput::IsSnapshotModeEnabled() const -{ - return GetImpl( *this ).IsSnapshotModeEnabled(); -} - -void TextInput::SetScrollEnabled( bool enable ) -{ - GetImpl( *this ).SetScrollEnabled( enable ); -} - -bool TextInput::IsScrollEnabled() const -{ - return GetImpl( *this ).IsScrollEnabled(); -} - -void TextInput::SetScrollPosition( const Vector2& position ) -{ - GetImpl( *this ).SetScrollPosition( position ); -} - -Vector2 TextInput::GetScrollPosition() const -{ - return GetImpl( *this ).GetScrollPosition(); -} - -TextInput::InputSignalType& TextInput::InputStartedSignal() -{ - return GetImpl(*this).InputStartedSignal(); -} - -TextInput::InputSignalType& TextInput::InputFinishedSignal() -{ - return GetImpl(*this).InputFinishedSignal(); -} - -TextInput::InputSignalType& TextInput::CutAndPasteToolBarDisplayedSignal() -{ - return GetImpl(*this).CutAndPasteToolBarDisplayedSignal(); -} - -TextInput::StyleChangedSignalType& TextInput::StyleChangedSignal() -{ - return GetImpl(*this).StyleChangedSignal(); -} - -TextInput::TextModifiedSignalType& TextInput::TextModifiedSignal() -{ - return GetImpl(*this).TextModifiedSignal(); -} - -TextInput::MaxInputCharactersReachedSignalType& TextInput::MaxInputCharactersReachedSignal() -{ - return GetImpl(*this).MaxInputCharactersReachedSignal(); -} - -TextInput::InputTextExceedBoundariesSignalType& TextInput::InputTextExceedBoundariesSignal() -{ - return GetImpl(*this).InputTextExceedBoundariesSignal(); -} - -void TextInput::SetMarkupProcessingEnabled( bool enable ) -{ - return GetImpl( *this ).SetMarkupProcessingEnabled( enable ); -} - -bool TextInput::IsMarkupProcessingEnabled() const -{ - return GetImpl( *this ).IsMarkupProcessingEnabled(); -} - - -TextInput::TextInput( Dali::Internal::CustomActor* internal ) -: Control( internal ) -{ - VerifyCustomActorPointer(internal); -} - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-input/text-input.h b/dali-toolkit/public-api/controls/text-input/text-input.h deleted file mode 100644 index 0598988..0000000 --- a/dali-toolkit/public-api/controls/text-input/text-input.h +++ /dev/null @@ -1,654 +0,0 @@ -#ifndef __DALI_TOOLKIT_TEXT_INPUT_H__ -#define __DALI_TOOLKIT_TEXT_INPUT_H__ - -/* - * Copyright (c) 2014 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. - * - */ - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal DALI_INTERNAL -{ -class TextInput; -} - -/** - * @brief TextInput Actor takes input one character at a time and displays it as a string within an input box. - * Characters can be removed from the end of the string until it is empty. A maximum length of displayed string - * can be set. - */ -class DALI_IMPORT_API TextInput : public Control -{ - -public: - - /** - * @brief The start and end property ranges for this control. - */ - enum PropertyRange - { - PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, - PROPERTY_END_INDEX = PROPERTY_START_INDEX + 512 ///< Reserve property indices - }; - - /** - * @brief An enumeration of properties belonging to the TextInput class. - */ - struct Property - { - enum - { - HIGHLIGHT_COLOR = PROPERTY_START_INDEX, // Property, name "highlight-color", type Vector4 - CUT_AND_PASTE_COLOR, // Property, name "cut-and-paste-bg-color", type Vector4 - CUT_AND_PASTE_PRESSED_COLOR, // Property, name "cut-and-paste-pressed-color", type Vector4 - CUT_AND_PASTE_BORDER_COLOR, // Property, name "cut-and-paste-border-color", type Vector4 - CUT_AND_PASTE_ICON_COLOR, // Property, name "cut-and-paste-icon-color", type Vector4 - CUT_AND_PASTE_ICON_PRESSED_COLOR, // Property, name "cut-and-paste-icon-pressed-color", type Vector4 - CUT_AND_PASTE_TEXT_COLOR, // Property, name "cut-and-paste-text-color", type Vector4 - CUT_AND_PASTE_TEXT_PRESSED_COLOR, // Property, name "cut-and-paste-text-pressed-color", type Vector4 - CUT_BUTTON_POSITION_PRIORITY, // Property, name "cut-button-position-priority", type unsigned int - COPY_BUTTON_POSITION_PRIORITY, // Property, name "copy-button-position-priority", type unsigned int - PASTE_BUTTON_POSITION_PRIORITY, // Property, name "paste-button-position-priority", type unsigned int - SELECT_BUTTON_POSITION_PRIORITY, // Property, name "select-button-position-priority", type unsigned int - SELECT_ALL_BUTTON_POSITION_PRIORITY, // Property, name "select-all-button-position-priority", type unsigned int - CLIPBOARD_BUTTON_POSITION_PRIORITY, // Property, name "clipboard-button-position-priority", type unsigned int - POP_UP_OFFSET_FROM_TEXT, // Property, name "popup-offset-from-text", type Vector4 - CURSOR_COLOR, // Property, name "cursor-color", type Vector4 - }; - }; - -public: - - /** - * @brief Create an uninitialized TextInput; this can be initialized with TextView::New(). - * - * Calling member functions with an uninitialized Dali::Object is not allowed. - */ - TextInput(); - - /** - * @brief Copy constructor. - * - * @param handle to be copied - */ - TextInput( const TextInput& handle ); - - /** - * @brief Assignment operator. - * - * @param handle to object we want to point to - * @return handle to the TextInput - */ - TextInput& operator=( const TextInput& handle ); - - /** - * @brief Create an initialised TextInput. - * - * @return A handle to a newly allocated Dali resource. - */ - static TextInput New(); - - /** - * @brief Downcast an Object handle to TextInput. - * - * If handle points to a TextInput the downcast produces valid - * handle. If not the returned handle is left uninitialized. - * - * @param[in] handle Handle to an object - * @return handle to a TextInput or an uninitialized handle - */ - static TextInput DownCast( BaseHandle handle ); - - /** - * @brief Destructor - * - * This is non-virtual since derived Handle types must not contain data or virtual methods. - */ - ~TextInput(); - - /** - * @brief Get the inputed text currently being displayed. - * - * @return string, the currently displayed string. - */ - std::string GetText() const; - - /** - * @brief Get the inputed text currently being displayed together with mark-up tags. - * - * @return string, the currently displayed string with mark-up. - */ - std::string GetMarkupText() const; - - /** - * @brief Set the maximum number of characters for the Text Input. - * - * @param [in] maxChars the max number of characters - */ - void SetMaxCharacterLength(std::size_t maxChars); - - /** - * @brief Limits the number of lines of text Text Input will display. - * - * @param [in] maxLines the max number of lines to display, must be greater than 0. - * Currently the only valid limit is 1. Which turns TextInput into Single line mode. Any number higher than 1 results in no limit. - */ - void SetNumberOfLinesLimit(std::size_t maxLines); - - /** - * @brief Returns the limit of lines Text Input is allowed to display. - * - * @return max line number limit - */ - std::size_t GetNumberOfLinesLimit() const; - - /** - * @brief Returns the number of characters TextInput is displaying. - * - * @return number of characters - */ - std::size_t GetNumberOfCharacters() const; - - /** - * @brief Sets a place holder text to be displayed when the text-input is empty. - * - * If not set or set to an empty string then no place holder will be shown. - * @param [in] placeHolderText text to be used as place holder. - */ - void SetPlaceholderText( const std::string& placeHolderText ); - - /** - * @return the current set place holder text, empty string returned if not set. - */ - std::string GetPlaceholderText(); - - /** - * @brief set initial text to be displayed in text-input. - * - * Can be used to edit a pre-existing string. - * @param [in] initialText text to be initially displayed - */ - void SetInitialText(const std::string& initialText); - - /** - * @brief Manual method to set the focus on the TextInput so it starts or stops edit state. - * - * @pre The text input actor has been initialised. - * @param[in] editMode true or false to indicate editMode on or off - */ - void SetEditable(bool editMode); - - /** - * @see SetEditable(bool editMode). - * - * It sets the cursor in the closest character to the given touch point. - * - * @param[in] editMode true or false to indicate editMode on or off - * @param[in] touchPoint A position in actor coordinates within the text-input. - */ - void SetEditable(bool editMode, const Vector2& touchPoint); - - /** - * @brief Check if TextInput is in edit state. - * - * @pre The text input actor has been initialised. - * @return True or False to indicate editMode on or off - */ - bool IsEditable() const; - - /** - * @brief Method to enable or disable edit on touch/tap. - * - * If not enabled (set to false) then SetEditable(true) will be used to start edit mode. - * @pre The text input actor has been initialised. - * @param[in] editOnTouch true or false to indicate if editing should start on touch - * default is for editing to start on touching textinput - */ - void SetEditOnTouch(bool editOnTouch = true); - - /** - * @brief Check if TextInput starts edit mode on touch. - * - * @pre The text input actor has been initialised. - * @return True or False to indicate editOnTouch on or off - */ - bool IsEditOnTouch() const; - - /** - * @brief Check if Text Selection is enabled so required text can be highlighted. - * - * @pre The text input actor has been initialised. - * @param[in] textSelectable true or false to indicate if text can be selected or not - * default is for text to be select-able when in edit mode - */ - void SetTextSelectable(bool textSelectable = true); - - /** - * @brief Check if Text can be selected. - * - * @pre The text input actor has been initialised. - * @return True or False to indicate if text can be selected or not - */ - bool IsTextSelectable() const; - - /** - * @brief Check if any text is currently selected, can be used to determine if ApplyStyle or SetActiveStyle should be used. - * - * @pre The text input actor has been initialised. - * @return True if text selected else False - */ - bool IsTextSelected() const; - - /** - * @brief Selects text between the given positions. - * - * @pre TextInput should be in edit mode. - * @param start position to start selection - * @param end position to end selection, inclusive of this character. - * Providing 0 and result from GetNumberOfCharacters() will select all text. - */ - void SelectText(std::size_t start, std::size_t end); - - /** - * @brief If any text is selected then de-select it and hide highlight. - * - * @pre The text input actor has been initialised. - */ - void DeSelectText(); - - /** - * @brief Set the image to be used as the cursor grab hander. - * - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - */ - void SetGrabHandleImage( Image image ); - - /** - * Depreciated API. - * @brief Set the image to be used for the regular left to right cursor. - * - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - * @param[in] border The nine patch border for the image. - */ - void SetCursorImage(Dali::Image image, const Vector4& border ); - - /** - * @brief Retrieve the selection handle size. - * - * Both handles have same size. - * @return Vector3 the selection handle size. - */ - Vector3 GetSelectionHandleSize(); - - /** - * @brief Set the image to be used for the Right to Left cursor. - * - * @pre The text input actor has been initialised. - * @param[in] image The image to be used. - * @param[in] border The nine patch border for the image. - */ - void SetRTLCursorImage(Dali::Image image, const Vector4& border ); - - /** - * @brief Toggle to enable the grab handle, used to position cursor when magnifier not being used. - * - * Default behaviour is to use the magnifier to position the cursor, enabling this prevents the magnifier from being shown. - * @param[in] toggle true to enable, false to disable grab handle - */ - void EnableGrabHandle(bool toggle); - - /** - * @brief Method to check if grab handle is enabled, if false then the magnifier will be used to position cursor. - * - * @return bool returns true is grab handle enabled. - */ - bool IsGrabHandleEnabled(); - - /** - * @brief Set the bounding rectangle which handles, popup and similar decorations will not exceed. - * - * The default value is the width and height of the stage from the top left origin. - * If a title bar for example is on the top of the screen then the y should be the title's height and - * the boundary height the stage height minus the title's height. - * Restrictions - The boundary box should be set up with a fixed z position for the text-input and the default camera. - * @param[in] boundingOriginAndSize Rect( x coordinate, y coordinate, width, height ) - * @code - * +----------------------------------------+ - * |(x,y) | - * |+--------------------------------------+| - * || || - * || Bounding Box || boundary height - * || || - * |+--------------------------------------+| - * +----------------------------------------+ - * boundary width - * @endcode - */ - void SetBoundingRectangle( const Rect& boundingOriginAndSize ); - - /** - * @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 the bounding rectangle - */ - const Rect GetBoundingRectangle() const; - - /** - * @brief Sets the style for new text being typed. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @pre The text input actor has been initialised. - * @param[in] style The style for the new text. - * @param[in] mask The bit mask. - */ - void SetActiveStyle( const TextStyle& style, const TextStyle::Mask mask = TextStyle::ALL ); - - /** - * @brief Applies the given style to the selected text. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * Introduced text after this call uses the new style. - * @param[in] style The given style. - * @param[in] mask The bit mask. - */ - void ApplyStyle( const TextStyle& style, const TextStyle::Mask mask = TextStyle::ALL ); - - /** - * @brief Applies the given style to all text, selected or not selected. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @param[in] style The given style. - * @param[in] mask The bit mask. - */ - void ApplyStyleToAll( const TextStyle& style, const TextStyle::Mask mask = TextStyle::ALL ); - - /** - * @brief Get the style of the Text character before the cursor. - * - * If no character before then return the InputStyle. - * @return TextStyle, the style of the character before the cursor - */ - TextStyle GetStyleAtCursor() const; - - /** - * @brief Set the current text alignment (overrides default setting). - * - * The default alignment is dependent on the current text in the text field. - * If the text begins using LTR characters (e.g. European text) then the - * alignment is HorizontalLeft. If the text begins using RTL characters - * (e.g. Hebrew/Arabic text) then the alignment is HorizontalRight. - * If there is no text, then the alignment defaults to: - * (HorizontalLeft | VerticalCenter) - * @param[in] align The new alignment option. - */ - void SetTextAlignment( Toolkit::Alignment::Type align ); - - /** - * @brief Set the current line justification. (overrides default setting). - * - * The default justification is dependent on the current text in the text field. - * If the text begins using LTR characters (e.g. European text) then the - * justification is HorizontalLeft. If the text begins using RTL characters - * (e.g. Hebrew/Arabic text) then the justification is HorizontalRight. - * If there is no text, then the justification defaults to: - * (HorizontalLeft | VerticalCenter) - * @param[in] justification The new line justification. - */ - void SetTextLineJustification( Toolkit::TextView::LineJustification justification ); - - /** - * @brief Sets a fade boundary. - * - * @see TextView::FadeBoundary. - * - * @param[in] fadeBoundary The given fade boundary. - */ - void SetFadeBoundary( const Toolkit::TextView::FadeBoundary& fadeBoundary ); - - /** - * @brief Retrieves the fade boundary. - * - * @see TextView::FadeBoundary. - * - * @return The fade boundary. - */ - const Toolkit::TextView::FadeBoundary& GetFadeBoundary() const; - - /** - * @brief Get the current text alignment combined into a single value. - * - * The values can be tested by using the & operator - * and the desired flag. e.g. if (GetTextAlignment() & HorizontalCentre) ... - * @return The combined text alignment - */ - Toolkit::Alignment::Type GetTextAlignment() const; - - /** - * @brief Sets how to split the text in lines policy. - * - * @param policy The multi-line policy. - */ - void SetMultilinePolicy( Toolkit::TextView::MultilinePolicy policy ); - - /** - * @brief Gets the split in lines policy. - * - * @return The multi-line policy. - */ - Toolkit::TextView::MultilinePolicy GetMultilinePolicy() const; - - /** - * @brief Sets how to display the text inside the TextView when it exceeds the text-view's width. - * - * @param policy The exceed policy. - */ - void SetWidthExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @brief Gets the width exceed policy. - * - * @return The exceed policy. - */ - TextView::ExceedPolicy GetWidthExceedPolicy() const; - - /** - * @brief Sets how to display the text inside the TextView when it exceeds the text-view's height. - * - * @param policy The exceed policy. - */ - void SetHeightExceedPolicy( Toolkit::TextView::ExceedPolicy policy ); - - /** - * @brief Gets the height exceed policy. - * - * @return The exceed policy. - */ - TextView::ExceedPolicy GetHeightExceedPolicy() const; - - /** - * @brief Sets if the inputed text can exceed the text-input boundary. - * - * By default is enabled. - * - * @param[in] enable Whether the inputed text can exceed its boundary. - */ - void SetExceedEnabled( bool enable ); - - /** - * @brief Retrieves whether inputed text can exceed the text-input boundary. - * - * @return \e true if text inputed can exceed the boundary, otherwise \e false. - */ - bool GetExceedEnabled() const; - - /** - * @brief Allows modification of text-actor's position in the depth sort algorithm. - * - * @see Dali::RenderableActor::SetSortModifier() - * @param [in] depthOffset the offset to be given to the internal text-actors. Positive values pushing it further back. - */ - void SetSortModifier( float depthOffset ); - - /** - * @brief Sets whether text-view renders text using a previously generated snapshot. - * - * @see TextView::SetSnapshotModeEnabled() - * - * @param[in] enable Whether text-view is using or not a snapshot to render text. - */ - void SetSnapshotModeEnabled( bool enable ); - - /** - * @brief Retrieves whether text-view is using a snapshot to render text. - * - * @see TextView::IsSnapshotModeEnabled() - * - * @return \e true if text-view is using a snapshot to render text, otherwhise it returns \e false. - */ - bool IsSnapshotModeEnabled() const; - - /** - * @copydoc TextView::SetScrollEnabled() - */ - void SetScrollEnabled( bool enable ); - - /** - * @copydoc TextView::IsScrollEnabled() - */ - bool IsScrollEnabled() const; - - /** - * @copydoc TextView::SetScrollPosition() - */ - void SetScrollPosition( const Vector2& position ); - - /** - * @copydoc TextView::GetScrollPosition() - */ - Vector2 GetScrollPosition() const; - - /** - * @brief Sets whether markup processing should be carried out. - * - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ); - - /** - * @brief Returns whether markup processing is enabled or not - * - * @return true is markup processing is enabled - */ - bool IsMarkupProcessingEnabled() const; - - -public: /* Signals */ - - /// @brief Input Signal. - typedef Signal< void ( TextInput textInput ) > InputSignalType; - - /// @brief Input style changed signal. - typedef Signal< void ( TextInput textInput, const TextStyle& style ) > StyleChangedSignalType; - - /// @brief Text modified signal. - typedef Signal< void ( TextInput textInput ) > TextModifiedSignalType; - - /// @brief Max input characters reached signal. - typedef Signal< void ( TextInput textInput ) > MaxInputCharactersReachedSignalType; - - /// @brief Input text exceeds boundaries signal. - typedef Signal< void ( TextInput textInput ) > InputTextExceedBoundariesSignalType; - - /** - * @brief Signal emitted when the Text-Input starts receiving input. - */ - InputSignalType& InputStartedSignal(); - - /** - * @brief Signal emitted when the Text-Input is finished receiving input. - * - * TextInput::GetText() can be called to get current text string. - * @return The signal to connect to - */ - InputSignalType& InputFinishedSignal(); - - /** - * @brief Signal emitted when the cut and paste toolbar is displayed. - * - * @return The signal to connect to - */ - InputSignalType& CutAndPasteToolBarDisplayedSignal(); - - /** - * @brief Signal emitted when style changes. - * - * @return The signal to connect to - */ - StyleChangedSignalType& StyleChangedSignal(); - - /** - * @brief Signal emitted when text changes. - * - * @return The signal to connect to. - */ - TextModifiedSignalType& TextModifiedSignal(); - - /** - * @brief Signal emitted when max input characters are reached during text input. - * - * @return The signal to connect to - */ - MaxInputCharactersReachedSignalType& MaxInputCharactersReachedSignal(); - - /** - * @brief Signal emitted when input text exceeds the boundaries of the text-input. - * - * @return The signal to connect to - */ - InputTextExceedBoundariesSignalType& InputTextExceedBoundariesSignal(); - -public: // Not intended for application developers - - /** - * @brief Creates a handle using the Toolkit::Internal implementation. - * - * @param[in] implementation The Control implementation. - */ - DALI_INTERNAL TextInput(Internal::TextInput& implementation); - - /** - * @brief Allows the creation of this Control from an Internal::CustomActor pointer. - * - * @param[in] internal A pointer to the internal CustomActor. - */ - explicit DALI_INTERNAL TextInput(Dali::Internal::CustomActor* internal ); -}; - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_TEXT_INPUT_H__ diff --git a/dali-toolkit/public-api/controls/text-view/text-view.cpp b/dali-toolkit/public-api/controls/text-view/text-view.cpp deleted file mode 100644 index 85620de..0000000 --- a/dali-toolkit/public-api/controls/text-view/text-view.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 2014 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. - * - */ - -// CLASS HEADER -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace Toolkit -{ - -TextView::CharacterLayoutInfo::CharacterLayoutInfo() -: mSize(), - mPosition(), - mIsNewLineChar( false ), - mIsNewParagraphChar( false ), - mIsRightToLeftCharacter( false ), - mIsVisible( true ), - mDescender() -{ -} - -TextView::CharacterLayoutInfo::~CharacterLayoutInfo() -{ -} - -TextView::CharacterLayoutInfo::CharacterLayoutInfo( const TextView::CharacterLayoutInfo& characterLayoutInfo ) -: mSize( characterLayoutInfo.mSize ), - mPosition( characterLayoutInfo.mPosition ), - mIsNewLineChar( characterLayoutInfo.mIsNewParagraphChar ), - mIsNewParagraphChar( characterLayoutInfo.mIsNewParagraphChar ), - mIsRightToLeftCharacter( characterLayoutInfo.mIsRightToLeftCharacter ), - mIsVisible( characterLayoutInfo.mIsVisible ), - mDescender( characterLayoutInfo.mDescender ) -{ -} - -TextView::CharacterLayoutInfo& TextView::CharacterLayoutInfo::operator=( const TextView::CharacterLayoutInfo& characterLayoutInfo ) -{ - mSize = characterLayoutInfo.mSize; - mPosition = characterLayoutInfo.mPosition; - mIsNewLineChar = characterLayoutInfo.mIsNewParagraphChar; - mIsNewParagraphChar = characterLayoutInfo.mIsNewParagraphChar; - mIsRightToLeftCharacter = characterLayoutInfo.mIsRightToLeftCharacter; - mIsVisible = characterLayoutInfo.mIsVisible; - mDescender = characterLayoutInfo.mDescender; - - return *this; -} - -TextView::CharacterLayoutInfo::CharacterLayoutInfo( const Size& size, - const Vector3& position, - bool isNewParagraphChar, - bool isRightToLeftCharacter, - bool isVisible, - float descender ) -: mSize( size ), - mPosition( position ), - mIsNewLineChar( isNewParagraphChar ), - mIsNewParagraphChar( isNewParagraphChar ), - mIsRightToLeftCharacter( isRightToLeftCharacter ), - mIsVisible( isVisible ), - mDescender( descender ) -{ -} - -TextView::TextLayoutInfo::TextLayoutInfo() -: mCharacterLayoutInfoTable(), - mLines(), - mCharacterLogicalToVisualMap(), - mCharacterVisualToLogicalMap(), - mTextSize(), - mScrollOffset() -{ -} - -TextView::TextLayoutInfo::~TextLayoutInfo() -{ -} - -TextView::TextLayoutInfo::TextLayoutInfo( const TextView::TextLayoutInfo& textLayoutInfo ) -: mCharacterLayoutInfoTable( textLayoutInfo.mCharacterLayoutInfoTable ), - mLines( textLayoutInfo.mLines ), - mCharacterLogicalToVisualMap( textLayoutInfo.mCharacterLogicalToVisualMap ), - mCharacterVisualToLogicalMap( textLayoutInfo.mCharacterVisualToLogicalMap ), - mTextSize( textLayoutInfo.mTextSize ), - mScrollOffset( textLayoutInfo.mScrollOffset ) -{ -} - -TextView::TextLayoutInfo& TextView::TextLayoutInfo::operator=( const TextView::TextLayoutInfo& textLayoutInfo ) -{ - mCharacterLayoutInfoTable = textLayoutInfo.mCharacterLayoutInfoTable; - mLines = textLayoutInfo.mLines; - mCharacterLogicalToVisualMap = textLayoutInfo.mCharacterLogicalToVisualMap; - mCharacterVisualToLogicalMap = textLayoutInfo.mCharacterVisualToLogicalMap; - mTextSize = textLayoutInfo.mTextSize; - mScrollOffset = textLayoutInfo.mScrollOffset; - - return *this; -} - -TextView::FadeBoundary::FadeBoundary() -: mLeft( 0 ), - mRight( 0 ), - mTop( 0 ), - mBottom( 0 ) -{ -} - -TextView::FadeBoundary::FadeBoundary( PixelSize left, PixelSize right, PixelSize top, PixelSize bottom ) -: mLeft( left ), - mRight( right ), - mTop( top ), - mBottom( bottom ) -{ -} - -TextView::TextView() -{ -} - -TextView::TextView( const TextView& handle ) -: Control( handle ) -{ -} - -TextView::TextView( Dali::Internal::CustomActor* internal ) -: Control( internal ) -{ - VerifyCustomActorPointer(internal); -} - -TextView& TextView::operator=( const TextView& handle ) -{ - if( &handle != this ) - { - Control::operator=( handle ); - } - return *this; -} - -TextView TextView::New() -{ - return Internal::TextView::New(); -} - -TextView TextView::New( const std::string& text ) -{ - TextView textView = Internal::TextView::New(); - textView.SetText( text ); - return textView; -} - -TextView TextView::New( const MarkupProcessor::StyledTextArray& text ) -{ - TextView textView = Internal::TextView::New(); - textView.SetText( text ); - return textView; -} - -TextView TextView::DownCast( BaseHandle handle ) -{ - return Control::DownCast(handle); -} - -TextView::~TextView() -{ -} - -void TextView::SetText( const std::string& text ) -{ - GetImpl( *this ).SetText( text ); -} - -void TextView::SetText( const MarkupProcessor::StyledTextArray& text ) -{ - GetImpl( *this ).SetText( text ); -} - -void TextView::InsertTextAt( std::size_t position, const std::string& text ) -{ - GetImpl( *this ).InsertTextAt( position, text ); -} - -void TextView::InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text ) -{ - GetImpl( *this ).InsertTextAt( position, text ); -} - -void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ) -{ - GetImpl( *this ).ReplaceTextFromTo( position, numberOfCharacters, text ); -} - -void TextView::ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text ) -{ - GetImpl( *this ).ReplaceTextFromTo( position, numberOfCharacters, text ); -} - -void TextView::RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ) -{ - GetImpl( *this ).RemoveTextFrom( position, numberOfCharacters ); -} - -std::string TextView::GetText() const -{ - return GetImpl( *this ).GetText(); -} - -void TextView::SetLineHeightOffset( PointSize offset ) -{ - GetImpl( *this ).SetLineHeightOffset( offset ); -} - -PointSize TextView::GetLineHeightOffset() const -{ - return GetImpl( *this ).GetLineHeightOffset(); -} - -void TextView::SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask ) -{ - GetImpl( *this ).SetStyleToCurrentText( style, mask ); -} - -void TextView::SetTextAlignment( Alignment::Type align ) -{ - GetImpl( *this ).SetTextAlignment( align ); -} - -Alignment::Type TextView::GetTextAlignment() const -{ - return GetImpl( *this ).GetTextAlignment(); -} - -void TextView::SetMultilinePolicy( TextView::MultilinePolicy policy ) -{ - GetImpl( *this ).SetMultilinePolicy( policy ); -} - -TextView::MultilinePolicy TextView::GetMultilinePolicy() const -{ - return GetImpl( *this ).GetMultilinePolicy(); -} - -void TextView::SetWidthExceedPolicy( TextView::ExceedPolicy policy ) -{ - GetImpl( *this ).SetWidthExceedPolicy( policy ); -} - -TextView::ExceedPolicy TextView::GetWidthExceedPolicy() const -{ - return GetImpl( *this ).GetWidthExceedPolicy(); -} - -void TextView::SetHeightExceedPolicy( ExceedPolicy policy ) -{ - GetImpl( *this ).SetHeightExceedPolicy( policy ); -} - -TextView::ExceedPolicy TextView::GetHeightExceedPolicy() const -{ - return GetImpl( *this ).GetHeightExceedPolicy(); -} - -void TextView::SetLineJustification( TextView::LineJustification justification ) -{ - GetImpl( *this ).SetLineJustification( justification ); -} - -TextView::LineJustification TextView::GetLineJustification() const -{ - return GetImpl( *this ).GetLineJustification(); -} - -void TextView::SetFadeBoundary( const TextView::FadeBoundary& fadeBoundary ) -{ - GetImpl( *this ).SetFadeBoundary( fadeBoundary ); -} - -const TextView::FadeBoundary& TextView::GetFadeBoundary() const -{ - return GetImpl( *this ).GetFadeBoundary(); -} - -void TextView::SetEllipsizeText( const std::string& ellipsizeText ) -{ - GetImpl( *this ).SetEllipsizeText( ellipsizeText ); -} - -void TextView::SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText ) -{ - GetImpl( *this ).SetEllipsizeText( ellipsizeText ); -} - -std::string TextView::GetEllipsizeText() const -{ - return GetImpl( *this ).GetEllipsizeText(); -} - -void TextView::GetTextLayoutInfo( TextLayoutInfo& textLayoutInfo ) -{ - GetImpl( *this ).GetTextLayoutInfo( textLayoutInfo ); -} - -void TextView::SetSortModifier( float depthOffset ) -{ - GetImpl( *this ).SetSortModifier( depthOffset ); -} - -void TextView::SetSnapshotModeEnabled( bool enable ) -{ - GetImpl( *this ).SetSnapshotModeEnabled( enable ); -} - -bool TextView::IsSnapshotModeEnabled() const -{ - return GetImpl( *this ).IsSnapshotModeEnabled(); -} - -void TextView::SetScrollEnabled( bool enable ) -{ - GetImpl( *this ).SetScrollEnabled( enable ); -} - -bool TextView::IsScrollEnabled() const -{ - return GetImpl( *this ).IsScrollEnabled(); -} - -void TextView::SetScrollPosition( const Vector2& position ) -{ - GetImpl( *this ).SetScrollPosition( position ); -} - -const Vector2& TextView::GetScrollPosition() const -{ - return GetImpl( *this ).GetScrollPosition(); -} - -bool TextView::IsScrollPositionTrimmed() const -{ - return GetImpl( *this ).IsScrollPositionTrimmed(); -} - -TextView::ScrolledSignalType& TextView::ScrolledSignal() -{ - return GetImpl( *this ).ScrolledSignal(); -} - -void TextView::SetMarkupProcessingEnabled( bool enable ) -{ - return GetImpl( *this ).SetMarkupProcessingEnabled( enable ); -} - -bool TextView::IsMarkupProcessingEnabled() const -{ - return GetImpl( *this ).IsMarkupProcessingEnabled(); -} - -TextView::TextView( Internal::TextView& implementation ) -: Control( implementation ) -{ -} - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/public-api/controls/text-view/text-view.h b/dali-toolkit/public-api/controls/text-view/text-view.h deleted file mode 100644 index 0eb8024..0000000 --- a/dali-toolkit/public-api/controls/text-view/text-view.h +++ /dev/null @@ -1,674 +0,0 @@ -#ifndef __DALI_TOOLKIT_TEXT_VIEW_H__ -#define __DALI_TOOLKIT_TEXT_VIEW_H__ - -/* - * Copyright (c) 2014 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 - -// INTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal DALI_INTERNAL -{ -class TextView; -} - -/** - * @brief The TextView class is a UI Dali::Toolkit::Control designed to extend the capabilities of the basic Dali::TextActor. - * - * It provides support for multi-line wrapping, multi-language font detection, text alignment, scrolling and styling. - * - * See the \link text-view Text View \endlink page of the Programming Guide for more details and examples. - * - * Signals - * | %Signal Name | Method | - * |-------------------|---------------------------| - * | scrolled | @ref ScrolledSignal() | - */ -class DALI_IMPORT_API TextView : public Control -{ -public: - - /** - * @brief The start and end property ranges for this control. - */ - enum PropertyRange - { - PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, - PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 ///< Reserve property indices - }; - - /** - * @brief An enumeration of properties belonging to the TextView class. - */ - struct Property - { - enum - { - MARKUP_ENABLED = PROPERTY_START_INDEX, ///< name "markup-enabled", @see SetMarkupProcessingEnabled(), type bool - TEXT, ///< name "text", @see SetText(), type std::string - MULTILINE_POLICY, ///< name "multiline-policy", @see SetMultilinePolicy(), type std::string - WIDTH_EXCEED_POLICY, ///< name "width-exceed-policy", @see SetWidthExceedPolicy(), type std::string - HEIGHT_EXCEED_POLICY, ///< name "height-exceed-policy", @see SetHeightExceedPolicy(), type std::string - LINE_JUSTIFICATION, ///< name "line-justification", @see SetLineJustification(), type std::string - FADE_BOUNDARY, ///< name "fade-boundary", @see SetFadeBoundary(), type Vector4 - LINE_HEIGHT_OFFSET, ///< name "line-height-offset", @see SetLineHeightOffset(), type float - HORIZONTAL_ALIGNMENT, ///< name "horizontal-alignment", @see SetTextAlignment(), type std::string - VERTICAL_ALIGNMENT, ///< name "vertical-alignment", @see SetTextAlignment(), type std::string - }; - }; - - /** - * @brief Structure used to retrieve Layout info per character. - */ - struct CharacterLayoutInfo - { - /** - * @brief Default constructor. - * - * Initializes all members to their default values. - */ - CharacterLayoutInfo(); - - /** - * @brief Empty destructor. - * - * @note Added to increase coverage. - */ - ~CharacterLayoutInfo(); - - /** - * @brief Copy constructor. - */ - CharacterLayoutInfo( const CharacterLayoutInfo& characterLayoutInfo ); - - /** - * @brief Assignment operator. - */ - CharacterLayoutInfo& operator=( const CharacterLayoutInfo& character ); - - /** - * @brief Constructor. - * - * @param[in] size of the character. - * @param[in] position of the character. - * @param[in] isNewParagraphChar Whether the character is a new paragraph character. - * @param[in] isRightToLeftCharacter Whether is a right to left character. - * @param[in] visible Whether is visible. - * @param[in] descender of the character (distance from the base line to the bottom of the character.) - */ - CharacterLayoutInfo( const Size& size, - const Vector3& position, - bool isNewParagraphChar, - bool isRightToLeftCharacter, - bool visible, - float descender ); - - Size mSize; ///< Size of the character. - Vector3 mPosition; ///< Position of the character within the text view. - bool mIsNewLineChar:1; ///< @deprecated. Use mIsNewParagraphChar instead. - bool mIsNewParagraphChar:1; ///< Whether this character represent a new paragraph. - bool mIsRightToLeftCharacter:1; ///< Whether it's a right-to-left character. - bool mIsVisible:1; ///< Whether this character is visible or not. - float mDescender; ///< The character's descender which is the distance from the baseline to the bottom of the character - }; - - typedef std::vector CharacterLayoutInfoContainer; ///< Container of layout info per character. - - /** - * @brief Stores some info about a line. - */ - struct LineLayoutInfo - { - std::size_t mCharacterGlobalIndex; ///< Global index within the whole text of the first character of current line. - Size mSize; ///< Size of the current line. - float mAscender; ///< The max ascender of the current line. - }; - - typedef std::vector LineLayoutInfoContainer; ///< Container of layout info per line. - - /** - * @brief How text is laid out. - */ - struct TextLayoutInfo - { - /** - * @brief Default constructor. - */ - TextLayoutInfo(); - - /** - * @brief Empty destructor. - * - * @note Added to increase coverage. - */ - ~TextLayoutInfo(); - - /** - * @brief Copy constructor. - */ - TextLayoutInfo( const TextLayoutInfo& textLayoutInfo ); - - /** - * @brief Assignment operator. - */ - TextLayoutInfo& operator=( const TextLayoutInfo& textLayoutInfo ); - - CharacterLayoutInfoContainer mCharacterLayoutInfoTable; ///< The table of character's positions and sizes sorted by the character's visual index. - LineLayoutInfoContainer mLines; ///< For each line, it stores an index to the first character of the line. - std::vector mCharacterLogicalToVisualMap; ///< The map to store the character's logical (input) index according to its visual (reordered) index. - std::vector mCharacterVisualToLogicalMap; ///< The map to store the character's visual (reordered) index according to its logical (input) index. - Size mTextSize; ///< Text size after relayout. - Vector2 mScrollOffset; ///< Scroll's position. - }; - - /** - * @brief This structure represents a fade boundary. - * - * If the Exceed policy is set to Fade all text which does not fit within the text-view fade boundary is faded out. Text which exceeds the text-view boundary becomes invisible. - * The \e left, \e right, \e top and \e bottom values are positive, in pixels and set the distances between the text-view and fade boundaries. - */ - struct FadeBoundary - { - /** - * @brief Default constructor. - * - * Initializes all values to 0. It means no fade boundary. - */ - FadeBoundary(); - - /** - * @brief Constructor. - * - * Initializes the fade boundary with the given values. - * - * @param[in] left value in pixels. - * @param[in] right value in pixels. - * @param[in] top value in pixels. - * @param[in] bottom value in pixels. - */ - FadeBoundary( PixelSize left, PixelSize right, PixelSize top, PixelSize bottom ); - - PixelSize mLeft; ///< The left fade boundary - PixelSize mRight; ///< The right fade boundary - PixelSize mTop; ///< The top fade boundary - PixelSize mBottom; ///< The bottom fade bounday - }; - - /** - * @brief Define how to wrap the text's paragraphs in lines. - * - * \e SplitByNewLineChar will wrap the text's paragraphs in lines when a '\\n' character or a \
is found. - * \e SplitByWord has effect only when TextView size is assigned. - * It will wrap the text's paragraphs in lines when a '\\n' character or a \
is found or if a paragraph exceeds the TextView's boundary. This option won't split a word in two. - * \e SplitByChar has effect only when TextView size is assigned. - * It will wrap the text's paragraphs in lines when a '\\n' character or a \
is found or if a paragraph exceeds the TextView's boundary. This option might split a word in two. - * The default value is \e SplitByNewLineChar. - */ - enum MultilinePolicy - { - SplitByNewLineChar, ///< Text's paragraphs will wrap in lines when '\\n' character is found. - SplitByWord, ///< Text's paragraphs will wrap in lines by word or if '\\n' character is found. It has effect only when TextView size is assigned. - SplitByChar ///< Text's paragraphs will wrap in lines by char or if '\\n' character is found. It has effect only when TextView size is assigned. - }; - - /** - * @brief Define how to display the lines when they doesn't fit inside the TextView after the text's paragraphs are wrapped in lines. - * - * The default value is \e Original. - */ - enum ExceedPolicy - { - Original, ///< Will display the lines in their original size. If a line, a word or a character is bigger than the TextView size it may exceed its boundary. - Fade, ///< Will display the lines in their original size. It won't display the part of the line which exceeds the TextView boundary. It fades the text out. - Split, ///< Will split the lines in a new line(s). - ShrinkToFit, ///< Will shrink the lines to fit the TextView boundary. - EllipsizeEnd ///< Will ellipsize the lines by the end. - }; - - /** - * @brief Define how to justify lines inside the text's boundary. - * - * The default value is \e Left. - */ - enum LineJustification - { - Left, ///< Justify to the left. - Center, ///< Centered. - Right, ///< Justify to the right. - Justified ///< Line justified. - }; - -public: - /** - * @brief Create a TextView handle; this can be initialised with TextView::New(). - * - * Calling member functions with an uninitialised Dali::Object handle is not allowed. - */ - TextView(); - - /** - * @brief Copy constructor. - * - * Creates another handle that points to the same real object - * @param[in] handle The handle to copy from - */ - TextView( const TextView& handle ); - - /** - * @brief Assignment operator. - * - * Changes this handle to point to another real object - * @param[in] handle The handle to copy from - * @return a reference to this - */ - TextView& operator=( const TextView& handle ); - - /** - * @brief Create a TextView control with no text. - * - * @return A handle the TextView control. - */ - static TextView New(); - - /** - * @brief Create a TextView control. - * - * @param[in] text to display. - * @return A handle the TextView control. - */ - static TextView New( const std::string& text ); - - /** - * @brief Create a TextView control with styled text. - * - * @param[in] text The text with style to display. - * @return A handle the TextView control. - */ - static TextView New( const MarkupProcessor::StyledTextArray& text ); - - /** - * @brief Downcast an Object handle to TextView. - * - * If handle points to a TextView the - * downcast produces valid handle. If not the returned handle is left uninitialized. - * @param[in] handle Handle to an object - * @return handle to a TextView or an uninitialized handle - */ - static TextView DownCast( BaseHandle handle ); - - /** - * @brief Destructor - * - * This is non-virtual since derived Handle types must not contain data or virtual methods. - */ - ~TextView(); - - /** - * @brief Replace the current text with a new text string. - * - * @param[in] text to display. The string may contain style tags. - */ - void SetText( const std::string& text ); - - /** - * @brief Replace the current text with a new text string with style. - * - * @param[in] text The text with style to display. - */ - void SetText( const MarkupProcessor::StyledTextArray& text ); - - /** - * @brief Inserts the given text in the specified position. - * - * @param[in] position Where the given text is going to be added. - * @param[in] text The text to be added. - */ - void InsertTextAt( std::size_t position, const std::string& text ); - - /** - * @brief Inserts the given text with style in the specified position. - * - * @param[in] position Where the given text is going to be added. - * @param[in] text The text with style to be added. - */ - void InsertTextAt( std::size_t position, const MarkupProcessor::StyledTextArray& text ); - - /** - * @brief Replaces part of the text. - * - * It removes the specified number of characters from the given position and inserts the given text in the same specified position. - * - * @param[in] position of the first character to be removed and Where the given text is going to be added. - * @param[in] numberOfCharacters number of characters to be removed. - * @param[in] text The text to be added. - */ - void ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const std::string& text ); - - /** - * @brief Replaces part of the text. - * - * It removes the specified number of characters from the given position and inserts the given text with style in the same specified position. - * - * @param[in] position of the first character to be removed and Where the given text is going to be added. - * @param[in] numberOfCharacters number of characters to be removed. - * @param[in] text The text with style to be added. - */ - void ReplaceTextFromTo( std::size_t position, std::size_t numberOfCharacters, const MarkupProcessor::StyledTextArray& text ); - - /** - * @brief Removes the specified number of characters from the given position. - * - * @param[in] position of the first character to be removed. - * @param[in] numberOfCharacters number of characters to be removed. - */ - void RemoveTextFrom( std::size_t position, std::size_t numberOfCharacters ); - - /** - * @brief Get the currently displayed text. - * - * @return The currently displayed text. - */ - std::string GetText() const; - - /** - * @brief Sets a line height offset. - * - * The line height offset will be added to the font line height. - * @param [in] offset The height offset in PointSize units. - */ - void SetLineHeightOffset( PointSize offset ); - - /** - * @brief Retrieves the line height offset. - * - * @return The line height offset in PointSize units. - */ - PointSize GetLineHeightOffset() const; - - /** - * @brief Sets the given style to the current text. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @note TextView doesn't store a copy of the given style, it applies the given style to the current text only. - * Subsequent calls to SetText() will override any style set by this method. - * @param[in] style The given style - * @param[in] mask The bit mask. - */ - void SetStyleToCurrentText( const TextStyle& style, TextStyle::Mask mask = TextStyle::ALL ); - - /** - * @brief Set the current text alignment. - * - * Default alignment is (HorizontalCenter | VerticalCenter) - * @param[in] align The new alignment option. - */ - void SetTextAlignment( Alignment::Type align ); - - /** - * @brief Get the current text alignment combined into a single value. - * - * The values can be tested by using the & operator - * and the desired flag. e.g. if (GetTextAlignment() & HorizontalCentre) ... - * @return the combined alignment - */ - Alignment::Type GetTextAlignment() const; - - /** - * @brief Sets how to split the paragraphs into lines. - * - * @param policy The multi-line policy. \e SplitByNewLineChar is set by default. - */ - void SetMultilinePolicy( MultilinePolicy policy ); - - /** - * @brief Gets the wrap in lines policy. - * - * @return The multi-line policy. - */ - MultilinePolicy GetMultilinePolicy() const; - - /** - * @brief Sets how to display the text inside the TextView when it exceeds the text-view's width. - * - * @param policy The exceed policy. Original is set by default. - */ - void SetWidthExceedPolicy( ExceedPolicy policy ); - - /** - * @brief Gets the width exceed policy. - * - * @return The exceed policy. - */ - ExceedPolicy GetWidthExceedPolicy() const; - - /** - * @brief Sets how to display the text inside the TextView when it exceeds the text-view's height. - * - * @param policy The exceed policy. Original is set by default. - */ - void SetHeightExceedPolicy( ExceedPolicy policy ); - - /** - * @brief Gets the height exceed policy. - * - * @return The exceed policy. - */ - ExceedPolicy GetHeightExceedPolicy() const; - - /** - * @brief Sets how to justify lines inside the text's boundary. - * - * @param justification The line justification. Left is set by default. - */ - void SetLineJustification( LineJustification justification ); - - /** - * @brief Gets the line justification. - * - * @return The line justification. - */ - LineJustification GetLineJustification() const; - - /** - * @brief Sets a fade boundary. - * - * @see FadeBoundary. - * - * @param[in] fadeBoundary The given fade boundary. - */ - void SetFadeBoundary( const FadeBoundary& fadeBoundary ); - - /** - * @brief Retrieves the fade boundary. - * - * @see FadeBoundary. - * - * @return The fade boundary. - */ - const FadeBoundary& GetFadeBoundary() const; - - /** - * @brief Sets the ellipsize text. - * - * @param[in] ellipsizeText The new text. The string may contain style tags. By default the ellipsize text is '...' - */ - void SetEllipsizeText( const std::string& ellipsizeText ); - - /** - * @brief Sets the ellipsize text with style. - * - * @param[in] ellipsizeText The new text with its style. - */ - void SetEllipsizeText( const MarkupProcessor::StyledTextArray& ellipsizeText ); - - /** - * @brief Retrieves the ellipsize text. - * - * @return The ellipsize text. - */ - std::string GetEllipsizeText() const; - - /** - * @brief A mechanism to retrieve layout information from the TextView. - * - * It produces a vector of CharcterLayoutInfo structures which describe the size and position of each character, - * two vectors which maps the logical and visual positions of the characters in a bidirectional text, the size - * of the whole laid-out text and the scroll offset value. - * - * @see TextLayoutInfo. - * - * @param[out] textLayoutInfo A structure with text layout information. - */ - void GetTextLayoutInfo( TextLayoutInfo& textLayoutInfo ); - - /** - * @brief Allows modification of text-actor's position in the depth sort algorithm. - * - * @see Dali::RenderableActor::SetSortModifier() - * @param [in] depthOffset the offset to be given to the internal text-actors. Positive values pushing it further back. - */ - void SetSortModifier( float depthOffset ); - - /** - * @brief Sets whether text-view renders text using a previously generated snapshot. - * - * Rendering long text using a snapshot may increase performance. The default value is \e false (render without using a snapshot). - * - * @param[in] enable Whether text-view is using a snapshot to render text. - */ - void SetSnapshotModeEnabled( bool enable ); - - /** - * @brief Retrieves whether text-view is using a snapshot to render text. - * - * @return \e true if text-view is using a snapshot to render text, otherwhise it returns \e false. - */ - bool IsSnapshotModeEnabled() const; - - /** - * @brief Sets whether markup processing should be carried out. - * - * To use markup, applications need to SetMarkupProcessingEnabled first, then SetText(). - * - * @see SetText() - * @param[in] enable whether markup processing is carried out or not. - */ - void SetMarkupProcessingEnabled( bool enable ); - - /** - * @brief Retrieves whether text-view is processing markup text - * - * @return \e true if text-view markup processing is enabled, otherwhise it returns \e false. - */ - bool IsMarkupProcessingEnabled() const; - - /** - * @brief Enables or disables the text scroll. - * - * When scroll is enabled, snapshot mode will be enabled automatically. Equally, if scroll is disabled - * the snapshot mode is restored to the previous value. - * - * @param[in] enable Whether to enable the text scroll. - */ - void SetScrollEnabled( bool enable ); - - /** - * @brief Retrieves whether the text scroll is enabled. - * - * @return \e true if the scroll is enabled. - */ - bool IsScrollEnabled() const; - - /** - * @brief Sets a new scroll position. - * - * The new scroll position set could be trimmed if the text doesn't cover the whole text-view. - * i.e. If a text-view is 100x100 and a text is 200x100 a scroll position beyond 50x0 will be trimmed to 50x0. - * - * Call IsScrollPositionTrimmed() to know if the last scroll position set has been trimmed. - * - * A signal is emitted. @see ScrolledSignal(). - * - * @param[in] position The new scroll position. - */ - void SetScrollPosition( const Vector2& position ); - - /** - * @brief Recrieves current scroll position. - * - * @return The scroll position. - */ - const Vector2& GetScrollPosition() const; - - /** - * @brief Whether the last scroll position set was trimmed. - * - * @return \e true if the last scroll position set was trimmed, otherwise \e false. - */ - bool IsScrollPositionTrimmed() const; - -public: - /// @brief Signal types - typedef Signal< void ( TextView textView, Vector2 scrollDelta ) > ScrolledSignalType; - - /** - * @brief Signal emitted when the text is scrolled inside the text-view. - * - * A callback with the following prototype can be connected to this signal. - * - * Callback(TextView textView, Vector2 scrollDelta) - * - * \e textView is the handle of the text-view emitting the signal. - * \e scrollDelta is the differente of the current scroll position with the previous one. - * @return The signal to connect to - */ - ScrolledSignalType& ScrolledSignal(); - -public: // Not intended for application developers - - /** - * @brief Creates a handle using the Toolkit::Internal implementation. - * @note Not intended for application developers - * - * @param[in] implementation The Control implementation. - */ - DALI_INTERNAL TextView( Internal::TextView& implementation ); - - /** - * @brief Allows the creation of this Control from an Internal::CustomActor pointer. - * @note Not intended for application developers - * - * @param[in] internal A pointer to the internal CustomActor. - */ - explicit DALI_INTERNAL TextView( Dali::Internal::CustomActor* internal ); -}; - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_ITEM_VIEW_H__ diff --git a/dali-toolkit/public-api/controls/view/view.h b/dali-toolkit/public-api/controls/view/view.h index 5138266..b42340c 100644 --- a/dali-toolkit/public-api/controls/view/view.h +++ b/dali-toolkit/public-api/controls/view/view.h @@ -63,13 +63,12 @@ class View; * mView.SetBackground( backgroundImageActor ); * * // Connects the orientation signal with the View::OrientationChanged method. - * application.GetOrientation().ChangedSignal().Connect( &view, &Toolkit::View::OrientationChanged ); + * application.GetWindow().GetOrientation().ChangedSignal().Connect( &view, &Toolkit::View::OrientationChanged ); * * // Create a content layer. * Layer contentLayer = Layer::New(); * contentLayer.SetAnchorPoint( AnchorPoint::CENTER ); * contentLayer.SetParentOrigin( ParentOrigin::CENTER ); - * contentLayer.ApplyConstraint( ParentConstraint::Size::New( ParentSize() ) ); * view.AddContentLayer( contentLayer ); * \endcode * diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 5487676..8cfc291 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -31,7 +31,7 @@ namespace Toolkit const unsigned int TOOLKIT_MAJOR_VERSION = 1; const unsigned int TOOLKIT_MINOR_VERSION = 0; -const unsigned int TOOLKIT_MICRO_VERSION = 35; +const unsigned int TOOLKIT_MICRO_VERSION = 38; const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali-toolkit/public-api/file.list b/dali-toolkit/public-api/file.list index dddcd30..41c390a 100755 --- a/dali-toolkit/public-api/file.list +++ b/dali-toolkit/public-api/file.list @@ -7,6 +7,7 @@ public_api_src_files = \ $(public_api_src_dir)/controls/control-impl.cpp \ $(public_api_src_dir)/controls/control.cpp \ $(public_api_src_dir)/controls/alignment/alignment.cpp \ + $(public_api_src_dir)/controls/bubble-effect/bubble-emitter.cpp \ $(public_api_src_dir)/controls/buttons/button.cpp \ $(public_api_src_dir)/controls/buttons/check-box-button.cpp \ $(public_api_src_dir)/controls/buttons/push-button.cpp \ @@ -47,8 +48,9 @@ public_api_src_files = \ $(public_api_src_dir)/controls/slider/slider.cpp \ $(public_api_src_dir)/controls/super-blur-view/super-blur-view.cpp \ $(public_api_src_dir)/controls/table-view/table-view.cpp \ - $(public_api_src_dir)/controls/text-input/text-input.cpp \ - $(public_api_src_dir)/controls/text-view/text-view.cpp \ + $(public_api_src_dir)/controls/text-controls/text-label.cpp \ + $(public_api_src_dir)/controls/text-controls/text-field.cpp \ + $(public_api_src_dir)/controls/text-controls/text-selection-popup.cpp \ $(public_api_src_dir)/controls/tool-bar/tool-bar.cpp \ $(public_api_src_dir)/controls/bloom-view/bloom-view.cpp \ $(public_api_src_dir)/controls/cluster/cluster-style.cpp \ @@ -60,10 +62,12 @@ public_api_src_files = \ $(public_api_src_dir)/focus-manager/focus-manager.cpp \ $(public_api_src_dir)/focus-manager/keyboard-focus-manager.cpp \ $(public_api_src_dir)/focus-manager/keyinput-focus-manager.cpp \ - $(public_api_src_dir)/markup-processor/markup-processor.cpp \ + $(public_api_src_dir)/shader-effects/bubble-effect/bubble-effect.cpp \ + $(public_api_src_dir)/shader-effects/bubble-effect/color-adjuster.cpp \ $(public_api_src_dir)/shader-effects/alpha-discard-effect.cpp \ $(public_api_src_dir)/shader-effects/bendy-effect.cpp \ $(public_api_src_dir)/shader-effects/blind-effect.cpp \ + $(public_api_src_dir)/shader-effects/bouncing-effect.cpp \ $(public_api_src_dir)/shader-effects/carousel-effect.cpp \ $(public_api_src_dir)/shader-effects/displacement-effect.cpp \ $(public_api_src_dir)/shader-effects/dissolve-effect.cpp \ @@ -124,7 +128,8 @@ public_api_buttons_header_files = \ public_api_bloom_view_header_files = \ $(public_api_src_dir)/controls/bloom-view/bloom-view.h -public_api_bubble_emitter_header_files = +public_api_bubble_emitter_header_files = \ + $(public_api_src_dir)/controls/bubble-effect/bubble-emitter.h public_api_cluster_header_files = \ $(public_api_src_dir)/controls/cluster/cluster-style.h \ @@ -198,11 +203,10 @@ public_api_super_blur_view_header_files = \ public_api_table_view_header_files = \ $(public_api_src_dir)/controls/table-view/table-view.h -public_api_text_input_header_files = \ - $(public_api_src_dir)/controls/text-input/text-input.h - -public_api_text_view_header_files = \ - $(public_api_src_dir)/controls/text-view/text-view.h +public_api_text_controls_header_files = \ + $(public_api_src_dir)/controls/text-controls/text-label.h \ + $(public_api_src_dir)/controls/text-controls/text-field.h \ + $(public_api_src_dir)/controls/text-controls/text-selection-popup.h public_api_tool_bar_header_files = \ $(public_api_src_dir)/controls/tool-bar/tool-bar.h @@ -220,13 +224,11 @@ public_api_focus_manager_header_files = \ $(public_api_src_dir)/focus-manager/keyboard-focus-manager.h \ $(public_api_src_dir)/focus-manager/keyinput-focus-manager.h -public_api_markup_processor_header_files = \ - $(public_api_src_dir)/markup-processor/markup-processor.h - public_api_shader_effects_header_files = \ $(public_api_src_dir)/shader-effects/alpha-discard-effect.h \ $(public_api_src_dir)/shader-effects/bendy-effect.h \ $(public_api_src_dir)/shader-effects/blind-effect.h \ + $(public_api_src_dir)/shader-effects/bouncing-effect.h \ $(public_api_src_dir)/shader-effects/carousel-effect.h \ $(public_api_src_dir)/shader-effects/displacement-effect.h \ $(public_api_src_dir)/shader-effects/dissolve-effect.h \ @@ -252,7 +254,9 @@ public_api_shader_effects_header_files = \ $(public_api_src_dir)/shader-effects/swirl-effect.h \ $(public_api_src_dir)/shader-effects/water-effect.h -public_api_bubble_effect_header_files = +public_api_bubble_effect_header_files = \ + $(public_api_src_dir)/shader-effects/bubble-effect/bubble-effect.h \ + $(public_api_src_dir)/shader-effects/bubble-effect/color-adjuster.h public_api_styling_header_files = \ $(public_api_src_dir)/styling/style-manager.h @@ -267,3 +271,5 @@ public_api_scripting_header_files = \ $(public_api_src_dir)/scripting/script.h \ $(public_api_src_dir)/scripting/script-plugin.h +public_api_rendering_backend_header_files = \ + $(public_api_src_dir)/text/rendering-backend.h diff --git a/dali-toolkit/public-api/focus-manager/keyboard-focus-manager.cpp b/dali-toolkit/public-api/focus-manager/keyboard-focus-manager.cpp index 45d0fbf..cc315c0 100644 --- a/dali-toolkit/public-api/focus-manager/keyboard-focus-manager.cpp +++ b/dali-toolkit/public-api/focus-manager/keyboard-focus-manager.cpp @@ -20,6 +20,7 @@ #include // EXTERNAL INCLUDES +#include // for strcmp // INTERNAL INCLUDES diff --git a/dali-toolkit/public-api/markup-processor/markup-processor.cpp b/dali-toolkit/public-api/markup-processor/markup-processor.cpp deleted file mode 100644 index 83359fd..0000000 --- a/dali-toolkit/public-api/markup-processor/markup-processor.cpp +++ /dev/null @@ -1,1121 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -// HEADER INCLUDE -#include - -// EXTERNAL INCLUDES -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -namespace MarkupProcessor -{ - -namespace -{ -const std::string WEB_COLOR_TOKEN( "#" ); -const std::string HEX_COLOR_TOKEN( "0x" ); -const std::string ALPHA_ONE( "FF" ); - -const std::string BLACK_COLOR( "black" ); -const std::string WHITE_COLOR( "white" ); -const std::string RED_COLOR( "red" ); -const std::string GREEN_COLOR( "green" ); -const std::string BLUE_COLOR( "blue" ); -const std::string YELLOW_COLOR( "yellow" ); -const std::string MAGENTA_COLOR( "magenta" ); -const std::string CYAN_COLOR( "cyan" ); -const std::string TRANSPARENT_COLOR( "transparent" ); - -const std::string XHTML_B_TAG("b"); -const std::string XHTML_I_TAG("i"); -const std::string XHTML_U_TAG("u"); -const std::string XHTML_BR_TAG("br"); -const std::string XHTML_FONT_TAG("font"); -const std::string XHTML_SHADOW_TAG("shadow"); -const std::string XHTML_GLOW_TAG("glow"); -const std::string XHTML_OUTLINE_TAG("outline"); -const std::string XHTML_SMOOTH_EDGE_TAG("smooth"); -const std::string XHTML_SIZE_PROPERTY("size"); -const std::string XHTML_COLOR_PROPERTY("color"); -const std::string XHTML_FACE_PROPERTY("face"); -const std::string XHTML_STYLE_PROPERTY("style"); -const std::string XHTML_PARAM_PROPERTY("param"); -const std::string XHTML_PARAM_X_PROPERTY("paramx"); -const std::string XHTML_PARAM_Y_PROPERTY("paramy"); - -const char LESS_THAN( '<' ); -const char GREATER_THAN( '>' ); -const char EQUAL( '=' ); -const char QUOTATION_MARK( '\''); -const char LINE_SEPARATOR_CR( 0x0D ); // Carriage return character CR -const char LINE_SEPARATOR_LF( 0x0A ); // New line character LF -const char SLASH( '/' ); -const char BACK_SLASH( '\\' ); - -const std::string LINE_SEPARATOR_LF_STRING(1 , LINE_SEPARATOR_LF); ///< a string with 1 line separator character -/** - * Stores a property pair: name, value. - */ -struct Property -{ - Property( const std::string& n, const std::string& v ) - : name( n ), - value( v ) - {} - - std::string name; - std::string value; -}; - - -/** - * Compare if two strings are equal. - * - * The comparison is case insensitive. - * - * @param[in] string1 First of the two strings to be compared. - * @param[in] string2 Second of the strings to be compared. - * - * @return \e true if both strings are equal (case insensitive). - */ -bool CaseInsensitiveComparison( const std::string& string1, const std::string& string2 ) -{ - const std::size_t stringSize = string1.size(); - if( stringSize != string2.size() ) - { - // Early return. Strings have different sizes. - return false; - } - - bool equal = true; - for( std::size_t index = 0; equal && ( index < stringSize ); ++index ) - { - if( std::toupper( *( string1.begin() + index ) ) != std::toupper( *( string2.begin() + index ) ) ) - { - equal = false; - } - } - - return equal; -} - -/** - * Converts a string into a float value. - * @param[in] floatStr A float packed inside a string. - * @return The float value. - */ -float StringToFloat( const std::string& floatStr ) -{ - float ret = 0.f; - - std::istringstream( floatStr ) >> ret; - - return ret; -} - -/** - * Converts a float into a string. - * @param[in] value. A float. - * @return The float packed into a string. - */ -std::string FloatToString( float value ) -{ - std::ostringstream stream; - stream << value; - - return stream.str(); -} - -/** - * Converts a string into an hexadecimal unsigned int. - * @param[in] uintStr An hexadecimal unsigned int packed inside a string. - * @return The hexadecimal value. - */ -unsigned int StringToHex( const std::string& uintStr ) -{ - unsigned int ret = 0; - - std::string str( uintStr ); - if( uintStr.size() <= 8 ) - { - str.insert( 2, std::string( "ff" ) ); - } - - std::istringstream( str ) >> std::hex >> ret; - - return ret; -} - -/** - * Converts an hexadecimal value into a string. - * @param[in] value. An hexadecimal value. - * @return The hexadecimal value packed inside a string. - */ -std::string HexToString( unsigned int value ) -{ - std::ostringstream stream; - stream << std::hex << value; - return stream.str(); -} - -/** - * Converts an ARGB color packed in 4 byte unsigned int into a Vector4 color used in Dali. - * @param[in] color An ARGB color packed in an unsigned int. - * @param[out] retColor A Vector4 with the converted color. - */ -void UintColorToVector4( unsigned int color, Vector4& retColor ) -{ - retColor.a = static_cast( ( color & 0xFF000000 ) >> 24 ) / 255.f; - retColor.r = static_cast( ( color & 0x00FF0000 ) >> 16 ) / 255.f; - retColor.g = static_cast( ( color & 0x0000FF00 ) >> 8 ) / 255.f; - retColor.b = static_cast( color & 0x000000FF ) / 255.f; -} - -/** - * Converts an ARGB Vector4 color into a 4 byte packed inside an unsigned int. - * @param[in] color A Vector4 with an ARGB color. - * @return An unsigned int with the converted color. - */ -unsigned int Vector4ColorToUint( const Vector4& color ) -{ - unsigned int retColor = 0; - - retColor = static_cast( color.a * 255.f ) << 24; - retColor += static_cast( color.r * 255.f ) << 16; - retColor += static_cast( color.g * 255.f ) << 8; - retColor += static_cast( color.b * 255.f ); - - return retColor; -} - -/** - * Converts a color packed inside a string into an ARGB Vector4 color. - * The string color could be in hexadecimal ( 0xFF0000FF ), webcolor ( #0000FF or #00F ) or some constant values: - * black, white, red, green, blue, yellow, magenta, cyan, transparent. - * @param[in] colorStr A color packed inside a string.. - * @param[out] retColor A color packed inside a Vector4. - */ -void ColorStringToVector4( const std::string& colorStr, Vector4& retColor ) -{ - std::string subStr1 = colorStr.substr( 0, 1 ); - std::string subStr2 = colorStr.substr( 0, 2 ); - - if( WEB_COLOR_TOKEN == subStr1 ) - { - std::string webColor( colorStr.begin() + 1, colorStr.end() ); - if( 3 == webColor.size() ) // 3 component web color #F00 (red) - { - webColor.insert( 2, &( webColor[2] ), 1 ); - webColor.insert( 1, &( webColor[1] ), 1 ); - webColor.insert( 0, &( webColor[0] ), 1 ); - webColor.insert( 0, ALPHA_ONE ); - } - else if( 6 == webColor.size() ) // 6 component web color #FF0000 (red) - { - webColor.insert( 0, ALPHA_ONE ); - } - webColor.insert( 0, HEX_COLOR_TOKEN ); - - UintColorToVector4( StringToHex( webColor ), retColor ); - } - else if( CaseInsensitiveComparison( HEX_COLOR_TOKEN, subStr2 ) ) - { - UintColorToVector4( StringToHex( colorStr ), retColor ); - } - else if( CaseInsensitiveComparison( BLACK_COLOR, colorStr ) ) - { - retColor = Color::BLACK; - } - else if( CaseInsensitiveComparison( WHITE_COLOR, colorStr ) ) - { - retColor = Color::WHITE; - } - else if( CaseInsensitiveComparison( RED_COLOR, colorStr ) ) - { - retColor = Color::RED; - } - else if( CaseInsensitiveComparison( GREEN_COLOR, colorStr ) ) - { - retColor = Color::GREEN; - } - else if( CaseInsensitiveComparison( BLUE_COLOR, colorStr ) ) - { - retColor = Color::BLUE; - } - else if( CaseInsensitiveComparison( YELLOW_COLOR, colorStr ) ) - { - retColor = Color::YELLOW; - } - else if( CaseInsensitiveComparison( MAGENTA_COLOR, colorStr ) ) - { - retColor = Color::MAGENTA; - } - else if( CaseInsensitiveComparison( CYAN_COLOR, colorStr ) ) - { - retColor = Color::CYAN; - } - else if( CaseInsensitiveComparison( TRANSPARENT_COLOR, colorStr ) ) - { - retColor = Color::TRANSPARENT; - } -} - -/** - * Converts a color packed inside a Vector4 into a string. - * The string color could be in hexadecimal ( 0xFF0000FF ), webcolor ( #0000FF or #00F ) or some constant values: - * black, white, red, green, blue, yellow, magenta, cyan, transparent. - * @param[in] color A color packed inside a Vector4 - * @return The color packed inside a string. - */ -std::string Vector4ToColorString( const Vector4& color ) -{ - std::string colorStr; - - if( Color::BLACK == color ) - { - colorStr = BLACK_COLOR; - } - else if( Color::WHITE == color ) - { - colorStr = WHITE_COLOR; - } - else if( Color::RED == color ) - { - colorStr = RED_COLOR; - } - else if( Color::GREEN == color ) - { - colorStr = GREEN_COLOR; - } - else if( Color::BLUE == color ) - { - colorStr = BLUE_COLOR; - } - else if( Color::YELLOW == color ) - { - colorStr = YELLOW_COLOR; - } - else if( Color::MAGENTA == color ) - { - colorStr = MAGENTA_COLOR; - } - else if( Color::CYAN == color ) - { - colorStr = CYAN_COLOR; - } - else if( Color::TRANSPARENT == color ) - { - colorStr = TRANSPARENT_COLOR; - } - else - { - colorStr = HEX_COLOR_TOKEN + HexToString( Vector4ColorToUint( color ) ); - } - - return colorStr; -} - -/** - * Skips any unnecessary white space. - * @param[in,out] it Iterator pointing to the current character of the markup string which is being parsed. - * @param[in] endIt Iterator pointing to the end of the markup string. - */ -void SkipWhiteSpace( std::string::const_iterator& it, const std::string::const_iterator& endIt ) -{ - bool found = false; - for( ; ( !found ) && ( it != endIt ); ++it ) - { - if( !isspace( *it ) ) - { - found = true; - --it; - } - } -} - -/** - * Adds a line separator 'LF' character to the given styled text array. - * @param[in] style The current style. - * @param[in,out] styledTextArray The given styled text array. - */ -void AddNewLineChar( const TextStyle& style, StyledTextArray& styledTextArray ) -{ - const Text text( LINE_SEPARATOR_LF_STRING ); - styledTextArray.push_back( StyledText( text, style ) ); -} - -/** - * Adds text to the given styled text array. - * It splits the text in characters. - * @param[in] textToBeStored The text to be stored. - * @param[in] styleToBeStored The current style. - * @param[in,out] styledTextArray The given styled text array. - */ -void AddText( const std::string& textToBeStored, const TextStyle& styleToBeStored, StyledTextArray& styledTextArray ) -{ - const Text text( textToBeStored ); - for( size_t i = 0, length = text.GetLength(); i < length; ++i ) - { - styledTextArray.push_back( StyledText( Text( text[i] ), styleToBeStored ) ); - } -} - -/** - * Splits the tag string into the tag name and its properties. - * @param[in] tag The tag string with its pairs property, value. - * @param[out] tagName The name of the tag. - * @param[out] properties Vector of properties. - */ -void ParseProperties( const std::string& tag, std::string& tagName, std::vector& properties ) -{ - // Find first the tag name. - bool found = false; - bool isQuotationOpen = false; - std::string::const_iterator it, endIt; - for( it = tag.begin(), endIt = tag.end(); ( !found ) && ( it != endIt ); ++it ) - { - const char character( *it ); - if( !isspace( character ) ) - { - tagName += character; - } - else - { - found = true; - } - } - SkipWhiteSpace( it, endIt ); - - // Find the properties. - std::string name; - std::string value; - bool addToNameValue = true; - for( ; it != endIt; ++it ) - { - const char character( *it ); - if( isspace( character ) && !isQuotationOpen ) - { - if( !name.empty() && !value.empty() ) - { - // Every time a white space is found, a new property is created and stored in the properties vector. - properties.push_back( Property( name, value ) ); - name .clear(); - value.clear(); - addToNameValue = true; // next read characters will be added to the name. - } - } - else if( EQUAL == character ) // '=' - { - addToNameValue = false; // next read characters will be added to the value. - SkipWhiteSpace( it, endIt ); - } - else if( QUOTATION_MARK == character ) // '\'' - { - // Do not add quotation marks to neither name nor value. - isQuotationOpen = !isQuotationOpen; - } - else - { - // Adds characters to the name or the value. - if( addToNameValue ) - { - name += character; - } - else - { - value += character; - } - } - } - if( !name.empty() && !value.empty() ) - { - // Checks if the last property needs to be added. - properties.push_back( Property( name, value ) ); - } -} - -/** - * It parses a tag and its properties if the given iterator \e it is pointing at a tag beginning. - * @param[in,out] it Iterator pointing to the current character of the markup string which is being parsed. - * @param[in] endIt Iterator pointing to the end of the markup string. - * @param[out] tag Name of the tag. - * @param[out] isEndTag Whether the tag is and end tag i.e or not. - * @param[out] properties The vector with tag properties. - * @return \e true if the iterator \e it is pointing a markup tag. Otherwise \e false. - */ -bool IsTag( std::string::const_iterator& it, const std::string::const_iterator& endIt, std::string& tag, bool& isEndTag, std::vector& properties ) -{ - bool isTag = false; - bool isQuotationOpen = false; - bool propertiesFound = false; - std::string tagString; - - const char character( *it ); - if( LESS_THAN == character ) // '<' - { - // if the iterator is pointing to a '<' character, then check if it's a markup tag is needed. - ++it; - if( it != endIt ) - { - SkipWhiteSpace( it, endIt ); - - for( ; ( !isTag ) && ( it != endIt ); ++it ) - { - const char character( *it ); - - if( SLASH == character ) // '/' - { - // if the tag has a '/' then it's an end or empty tag. - isEndTag = true; - - if( ( it + 1 != endIt ) && ( isspace( *( it + 1 ) ) ) && ( !isQuotationOpen ) ) - { - ++it; - SkipWhiteSpace( it, endIt ); - --it; - } - } - else if( GREATER_THAN == character ) // '>' - { - isTag = true; - } - else if(QUOTATION_MARK == character) - { - isQuotationOpen = !isQuotationOpen; - tagString += character; - } - else if( isspace( character ) ) // ' ' - { - // If the tag contains white spaces then it may have properties. - if ( !isQuotationOpen ) - { - propertiesFound = true; - } - tagString += character; - } - else - { - // If it's not any of the 'special' characters then just add it to the tag string. - tagString += character; - } - } - --it; - } - } - - // If the tag string has white spaces, then parse the properties is needed. - if( propertiesFound ) - { - ParseProperties( tagString, tag, properties ); - } - else - { - tag = tagString; - } - - return isTag; -} - -} // namespace - -void GetStyledTextArray( const std::string& markupString, StyledTextArray& styledTextArray, bool scanForMarkup ) -{ - styledTextArray.clear(); - - if ( !scanForMarkup ) - { - const Text text( markupString ); - const std::size_t size = text.GetLength(); - - styledTextArray.resize( size, StyledText( Text(), TextStyle() ) ); - - std::size_t index = 0; - for( StyledTextArray::iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it, ++index ) - { - StyledText& styledText( *it ); - - styledText.mText.Append( text[index] ); - } - return; - } - - TextStyle defaultStyle; - std::stack styleStack; - - styleStack.push( defaultStyle ); - TextStyle currentStyle = styleStack.top(); - std::string textToBeStored; - TextStyle styleToBeStored( currentStyle ); - for( std::string::const_iterator it = markupString.begin(), endIt = markupString.end(); it != endIt; ++it ) - { - std::string tag; - bool isEndTag = false; - std::vector tagProperties; - if( IsTag( it, endIt, tag, isEndTag, tagProperties ) ) - { - if( CaseInsensitiveComparison( XHTML_I_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - newStyle.SetItalics( true ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_U_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - newStyle.SetUnderline( true ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_B_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - newStyle.SetWeight( TextStyle::BOLD ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_BR_TAG, tag ) ) - { - if( isEndTag ) - { - AddText( textToBeStored, styleToBeStored, styledTextArray ); - AddNewLineChar( currentStyle, styledTextArray ); - textToBeStored.clear(); - } - } //
- else if( CaseInsensitiveComparison( XHTML_FONT_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_FACE_PROPERTY, property.name ) ) - { - newStyle.SetFontName( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_STYLE_PROPERTY, property.name ) ) - { - newStyle.SetFontStyle( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_COLOR_PROPERTY, property.name ) ) - { - Vector4 color; - ColorStringToVector4( property.value, color ); - newStyle.SetTextColor( color ); - } - else if( CaseInsensitiveComparison( XHTML_SIZE_PROPERTY, property.name ) ) - { - newStyle.SetFontPointSize( PointSize( StringToFloat( property.value ) ) ); - } - } - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_SHADOW_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - Vector4 color( TextStyle::DEFAULT_SHADOW_COLOR ); - Vector2 offset( TextStyle::DEFAULT_SHADOW_OFFSET ); - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_PARAM_X_PROPERTY, property.name ) ) - { - offset.x = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_PARAM_Y_PROPERTY, property.name ) ) - { - offset.y = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_COLOR_PROPERTY, property.name ) ) - { - ColorStringToVector4( property.value, color ); - } - } - newStyle.SetShadow( true, color, offset ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_GLOW_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - Vector4 color( TextStyle::DEFAULT_GLOW_COLOR ); - float intensity = TextStyle::DEFAULT_GLOW_INTENSITY; - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_PARAM_PROPERTY, property.name ) ) - { - intensity = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_COLOR_PROPERTY, property.name ) ) - { - ColorStringToVector4( property.value, color ); - } - } - newStyle.SetGlow( true, color, intensity ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_OUTLINE_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - Vector4 color( TextStyle::DEFAULT_OUTLINE_COLOR ); - Vector2 thickness( TextStyle::DEFAULT_OUTLINE_THICKNESS ); - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_PARAM_X_PROPERTY, property.name ) ) - { - thickness.x = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_PARAM_Y_PROPERTY, property.name ) ) - { - thickness.y = StringToFloat( property.value ); - } - else if( CaseInsensitiveComparison( XHTML_COLOR_PROPERTY, property.name ) ) - { - ColorStringToVector4( property.value, color ); - } - } - newStyle.SetOutline( true, color, thickness ); - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - else if( CaseInsensitiveComparison( XHTML_SMOOTH_EDGE_TAG, tag ) ) - { - if( !isEndTag ) - { - TextStyle newStyle( currentStyle ); - for( std::vector::const_iterator it = tagProperties.begin(), endIt = tagProperties.end(); it != endIt; ++it ) - { - const Property& property( *it ); - if( CaseInsensitiveComparison( XHTML_PARAM_PROPERTY, property.name ) ) - { - newStyle.SetSmoothEdge( StringToFloat( property.value ) ); - } - } - styleStack.push( newStyle ); - currentStyle = styleStack.top(); - } - else - { - styleStack.pop(); - currentStyle = styleStack.top(); - } - } // - } // end if( IsTag() ) - else - { - char character( *it ); - - // Adding < or > special character. - if( ( BACK_SLASH == character ) && ( it + 1 != endIt ) ) - { - const char nextChar( *( it + 1 ) ); - if( ( LESS_THAN == nextChar ) || ( GREATER_THAN == nextChar ) ) - { - character = nextChar; - ++it; - } - } - else if( ( LINE_SEPARATOR_CR == character ) && ( it + 1 != endIt ) ) - { - if( LINE_SEPARATOR_LF == *( it + 1 ) ) - { - character = LINE_SEPARATOR_LF; - ++it; - } - } - - if( styleToBeStored != currentStyle ) - { - if( !textToBeStored.empty() ) - { - AddText( textToBeStored, styleToBeStored, styledTextArray ); - textToBeStored.clear(); - } - styleToBeStored = currentStyle; - } - textToBeStored.insert( textToBeStored.end(), character ); - } - } - if( !textToBeStored.empty() ) - { - AddText( textToBeStored, styleToBeStored, styledTextArray ); - textToBeStored.clear(); - } -} - -void GetPlainString( const StyledTextArray& styledTextArray, std::string& plainString ) -{ - // First step is put all simultaneous characters with same style together. - for( StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it ) - { - const StyledText& styledText( *it ); - plainString += styledText.mText.GetText(); - } -} - -void GetMarkupString( const StyledTextArray& styledTextArray, std::string& markupString ) -{ - const std::string WHITE_SPACE( " " ); - - TextStyle previousStyle; - StyledText newStyledText; - StyledTextArray compressedStyledTextArray; - - markupString.clear(); - - // First step is put all simultaneous characters with same style together. - for( StyledTextArray::const_iterator it = styledTextArray.begin(), endIt = styledTextArray.end(); it != endIt; ++it ) - { - const StyledText& styledText( *it ); - - if( previousStyle != styledText.mStyle ) - { - if( !newStyledText.mText.IsEmpty() ) - { - compressedStyledTextArray.push_back( newStyledText ); - } - newStyledText = StyledText(); - newStyledText.mStyle = styledText.mStyle; - } - - if( !styledText.mText.IsEmpty() ) - { - const char character = styledText.mText.GetText()[0]; - if( ( character == LESS_THAN ) || ( character == GREATER_THAN ) ) - { - newStyledText.mText.Append( Text( std::string( &BACK_SLASH, 1 ) ) ); - } - } - - newStyledText.mText.Append( styledText.mText ); - - previousStyle = newStyledText.mStyle; - } - - //Add the last characters. - if( !newStyledText.mText.IsEmpty() ) - { - compressedStyledTextArray.push_back( newStyledText ); - } - - // Write markup string. - const std::string lineSeparatorStr( &LINE_SEPARATOR_LF ); - const Text lineSeparator( lineSeparatorStr ); - - const TextStyle defaultStyle; - for( StyledTextArray::const_iterator it = compressedStyledTextArray.begin(), endIt = compressedStyledTextArray.end(); it != endIt; ++it ) - { - const StyledText& styledText( *it ); - - bool isItalics = styledText.mStyle.IsItalicsEnabled(); - bool isBold = defaultStyle.GetWeight() != styledText.mStyle.GetWeight(); - bool isUnderline = styledText.mStyle.IsUnderlineEnabled(); - bool hasFontFace = defaultStyle.GetFontName() != styledText.mStyle.GetFontName(); - bool hasFontStyle = defaultStyle.GetFontStyle() != styledText.mStyle.GetFontStyle(); - bool hasFontSize = fabsf( defaultStyle.GetFontPointSize() - styledText.mStyle.GetFontPointSize() ) > GetRangedEpsilon( defaultStyle.GetFontPointSize(), styledText.mStyle.GetFontPointSize() ); - bool hasFontColor = defaultStyle.GetTextColor() != styledText.mStyle.GetTextColor(); - - bool hasSmooth = fabsf( defaultStyle.GetSmoothEdge() - styledText.mStyle.GetSmoothEdge() ) > GetRangedEpsilon( defaultStyle.GetSmoothEdge(), styledText.mStyle.GetSmoothEdge() ); - bool hasShadowColor = defaultStyle.GetShadowColor() != styledText.mStyle.GetShadowColor(); - bool hasShadowParams = defaultStyle.GetShadowOffset() != styledText.mStyle.GetShadowOffset(); - bool hasGlowColor = defaultStyle.GetGlowColor() != styledText.mStyle.GetGlowColor(); - bool hasGlowParams = fabsf( defaultStyle.GetGlowIntensity() - styledText.mStyle.GetGlowIntensity() ) > GetRangedEpsilon( defaultStyle.GetGlowIntensity(), styledText.mStyle.GetGlowIntensity() ); - bool hasOutlineColor = defaultStyle.GetOutlineColor() != styledText.mStyle.GetOutlineColor(); - bool hasOutlineParams = defaultStyle.GetOutlineThickness() != styledText.mStyle.GetOutlineThickness(); - - // Write font info. - if( hasFontFace || hasFontStyle || hasFontSize || hasFontColor ) - { - markupString += LESS_THAN + XHTML_FONT_TAG; - - if( hasFontFace ) - { - markupString += WHITE_SPACE + XHTML_FACE_PROPERTY + EQUAL + QUOTATION_MARK + styledText.mStyle.GetFontName() + QUOTATION_MARK; // face='' - } - - if( hasFontStyle ) - { - markupString += WHITE_SPACE + XHTML_STYLE_PROPERTY + EQUAL + QUOTATION_MARK + styledText.mStyle.GetFontStyle() + QUOTATION_MARK; // style='' - } - - if( hasFontSize ) - { - markupString += WHITE_SPACE + XHTML_SIZE_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetFontPointSize() ) + QUOTATION_MARK; // size='' - } - - if( hasFontColor ) - { - markupString += WHITE_SPACE + XHTML_COLOR_PROPERTY + EQUAL + QUOTATION_MARK + Vector4ToColorString( styledText.mStyle.GetTextColor() ) + QUOTATION_MARK; // color='' - } - - markupString += GREATER_THAN; - } // - - // Write italics. - if( isItalics ) - { - markupString += LESS_THAN + XHTML_I_TAG + GREATER_THAN; - } // - - // Write bold. - if( isBold ) - { - markupString += LESS_THAN + XHTML_B_TAG + GREATER_THAN; - } // - - // Write underline. - if( isUnderline ) - { - markupString += LESS_THAN + XHTML_U_TAG + GREATER_THAN; - } // - - // Write smooth. - if( hasSmooth ) - { - markupString += LESS_THAN + XHTML_SMOOTH_EDGE_TAG + WHITE_SPACE + XHTML_PARAM_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetSmoothEdge() ) + QUOTATION_MARK + GREATER_THAN; - } - - // Write shadow. - if( styledText.mStyle.IsShadowEnabled() ) - { - markupString += LESS_THAN + XHTML_SHADOW_TAG; - - if( hasShadowColor ) - { - markupString += WHITE_SPACE + XHTML_COLOR_PROPERTY + EQUAL + QUOTATION_MARK + Vector4ToColorString( styledText.mStyle.GetShadowColor() ) + QUOTATION_MARK; - } - - if( hasShadowParams ) - { - markupString += WHITE_SPACE + XHTML_PARAM_X_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetShadowOffset().x ) + QUOTATION_MARK; - markupString += WHITE_SPACE + XHTML_PARAM_Y_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetShadowOffset().y ) + QUOTATION_MARK; - } - - markupString += GREATER_THAN; - } - - // Write glow. - if( styledText.mStyle.IsGlowEnabled() ) - { - markupString += LESS_THAN + XHTML_GLOW_TAG; - - if( hasGlowColor ) - { - markupString += WHITE_SPACE + XHTML_COLOR_PROPERTY + EQUAL + QUOTATION_MARK + Vector4ToColorString( styledText.mStyle.GetGlowColor() ) + QUOTATION_MARK; // color='' - } - - if( hasGlowParams ) - { - markupString += WHITE_SPACE + XHTML_PARAM_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetGlowIntensity() ) + QUOTATION_MARK; // param='' - } - - markupString += GREATER_THAN; - } // - - // Write outline. - if( styledText.mStyle.IsOutlineEnabled() ) - { - markupString += LESS_THAN + XHTML_OUTLINE_TAG; - - if( hasOutlineColor ) - { - markupString += WHITE_SPACE + XHTML_COLOR_PROPERTY + EQUAL + QUOTATION_MARK + Vector4ToColorString( styledText.mStyle.GetOutlineColor() ) + QUOTATION_MARK; // color = '' - } - - if( hasOutlineParams ) - { - markupString += WHITE_SPACE + XHTML_PARAM_X_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetOutlineThickness().x ) + QUOTATION_MARK; // paramx='' - markupString += WHITE_SPACE + XHTML_PARAM_Y_PROPERTY + EQUAL + QUOTATION_MARK + FloatToString( styledText.mStyle.GetOutlineThickness().y ) + QUOTATION_MARK; // paramy='' - } - - markupString += GREATER_THAN; - } // - - // Write text. - if( styledText.mText[0] == lineSeparator[0] ) - { - markupString += LESS_THAN + XHTML_BR_TAG + WHITE_SPACE + SLASH + GREATER_THAN; //
- } - else - { - markupString += styledText.mText.GetText(); - } - - // Write outline close tag. - if( styledText.mStyle.IsOutlineEnabled() ) - { - markupString += LESS_THAN + ( SLASH + XHTML_OUTLINE_TAG + GREATER_THAN ); //
- } - - // Write glow close tag. - if( styledText.mStyle.IsGlowEnabled() ) - { - markupString += LESS_THAN + ( SLASH + XHTML_GLOW_TAG + GREATER_THAN ); //
- } - - // Write shadow close tag. - if( styledText.mStyle.IsShadowEnabled() ) - { - markupString += LESS_THAN + ( SLASH + XHTML_SHADOW_TAG + GREATER_THAN ); // - } - - // Write smooth close tag. - if( hasSmooth ) - { - markupString += LESS_THAN + ( SLASH + XHTML_SMOOTH_EDGE_TAG + GREATER_THAN ); // - } - - // Write underline close tag. - if( isUnderline ) - { - markupString += LESS_THAN + ( SLASH + XHTML_U_TAG + GREATER_THAN ); //
- } - - // Write bold close tag. - if( isBold ) - { - markupString += LESS_THAN + ( SLASH + XHTML_B_TAG + GREATER_THAN ); //
- } - - // Write italics close tag. - if( isItalics ) - { - markupString += LESS_THAN + ( SLASH + XHTML_I_TAG + GREATER_THAN ); //
- } - - // Write font close tag. - if( hasFontFace || hasFontStyle || hasFontSize || hasFontColor ) - { - markupString += LESS_THAN + ( SLASH + XHTML_FONT_TAG + GREATER_THAN ); //
- } - } -} - -void SetTextStyle( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) -{ - if( !styledTextArray.empty() ) - { - const size_t size = styledTextArray.size() - 1; - SetTextStyleToRange( styledTextArray, style, mask, 0, size ); - } -} - -void SetTextStyle( const Text& text, StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) -{ - if( !text.IsEmpty() ) - { - const size_t size = text.GetLength(); - - for( size_t i = 0; i < size; ++i ) - { - StyledText styledText; - styledText.mText = Text( text[i] ); - styledText.mStyle = style; - - styledTextArray.push_back( styledText ); - } - - SetTextStyleToRange( styledTextArray, style, mask, 0, size - 1 ); - } -} - -void SetTextStyleToRange( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask, std::size_t begin, std::size_t end ) -{ - const size_t size = styledTextArray.size(); - DALI_ASSERT_ALWAYS( begin < size ); - DALI_ASSERT_ALWAYS( end < size ); - - for( StyledTextArray::iterator it = styledTextArray.begin() + std::min(begin, end), endIt = styledTextArray.begin() + std::max(begin, end) + 1; it != endIt; ++it ) - { - StyledText& styledText( *it ); - - styledText.mStyle.Copy( style, mask ); - } // for loop -} - -} // namespace MarkupProcessor - -} // namespace Toolkit - -} // namespace Dali diff --git a/dali-toolkit/public-api/markup-processor/markup-processor.h b/dali-toolkit/public-api/markup-processor/markup-processor.h deleted file mode 100644 index 0a10996..0000000 --- a/dali-toolkit/public-api/markup-processor/markup-processor.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef __DALI_TOOLKIT_MARKUP_PROCESSOR_H__ -#define __DALI_TOOLKIT_MARKUP_PROCESSOR_H__ - -/* - * Copyright (c) 2014 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 -#include -#include - -namespace Dali -{ - -namespace Toolkit -{ - -/** - * @brief Markup Processor enumerations, structures and functions. - * - * See the \link markup-processor Markup Processor \endlink page in the Programming Guide. - */ -namespace MarkupProcessor -{ - -/** - * @brief A pair of Dali::Text and Dali::TextStyle. - * - * mText is a Dali::Text object which can store text in different - * languages. mStyle is a Dali::TextStyle object which can store all - * text styling features provided by Dali::TextActor. - */ -struct StyledText -{ - /** - * @brief Constructor - */ - StyledText() - : mText(), - mStyle() - { - } - - /** - * @brief Constructor - * - * @param[in] text A Text object - * @param[in] style A Style object - */ - StyledText( const Text& text, const TextStyle& style ) - : mText( text ), - mStyle( style ) - { - } - - Text mText; ///< Store text. Could be a mix of different languages. - TextStyle mStyle; ///< Store the style for the text. -}; - -/** - * @brief This type defines a vector of StyledText. - * - * It's used to store a whole text with its style and set it to a - * Dali::Toolkit::TextView. It could be used in other UI - * Dali::Toolkit::Control classes which need text with style. - */ -typedef std::vector StyledTextArray; - -/** - * @brief Creates a text array with its style from a markup string. - * - * Refer to the \link markup-processor Markup Processor \endlink page in the Programming Guide - * to see the html-ish sintax and some examples. - * - * @param [in] markupString A string with style. - * @param [out] styledTextArray A text array split in characters, each one with its style. - * @param [in] scanForMarkup If true will check to see string contains markup, else assume not - */ -DALI_IMPORT_API void GetStyledTextArray( const std::string& markupString, StyledTextArray& styledTextArray, bool scanForMarkup ); - -/** - * @brief Creates a plain string from a text array (thus stripping the style meta). - * - * @param [in] styledTextArray A text array split in characters, each one with its style. - * @param [out] plainString A string without style. - */ -DALI_IMPORT_API void GetPlainString( const StyledTextArray& styledTextArray, std::string& plainString ); - -/** - * @brief Creates a markup string from a text array with its style. - * - * @param [in] styledTextArray A text array split in characters, each one with its style. - * @param [out] markupString A string with style. - */ -DALI_IMPORT_API void GetMarkupString( const StyledTextArray& styledTextArray, std::string& markupString ); - -/** - * @brief Sets a text style to the given text. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @param[in,out] styledTextArray The given text - * @param[in] style The given style - * @param[in] mask The bit mask. - */ -DALI_IMPORT_API void SetTextStyle( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask = TextStyle::ALL ); - -/** - * @brief Sets a text style to the given text. - * - * @see SetTextStyle( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) - * - * @param[in] text The input text. - * @param[out] styledTextArray The input text with the given style. - * @param[in] style The given style. - * @param[in] mask The bit mask. - */ -DALI_IMPORT_API void SetTextStyle( const Text& text, StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask = TextStyle::ALL ); - -/** - * @brief Sets a text style to a range of characters of the given text. - * - * By default all style settings are applied but a bit mask could be used to modify only certain style settings. - * @param[in,out] styledTextArray The given text - * @param[in] style The given style - * @param[in] mask The bit mask. - * @param[in] begin The first character of the range. - * @param[in] end The last character of the range. - * @note It will assert if begin or end are out of range, or if begin > end. - */ -DALI_IMPORT_API void SetTextStyleToRange( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask, std::size_t begin, std::size_t end ); - -} // namespace MarkupProcessor - -} // namespace Toolkit - -} // namespace Dali - -#endif // __DALI_TOOLKIT_MARKUP_PROCESSOR_H__ diff --git a/dali-toolkit/public-api/scripting/script.h b/dali-toolkit/public-api/scripting/script.h index 53c82aa..a3dd4bc 100644 --- a/dali-toolkit/public-api/scripting/script.h +++ b/dali-toolkit/public-api/scripting/script.h @@ -18,9 +18,9 @@ * */ -// INTERNAL INCLUDES +// EXTERNAL INCLUDES #include -#include +#include namespace Dali { diff --git a/dali-toolkit/public-api/shader-effects/bouncing-effect.cpp b/dali-toolkit/public-api/shader-effects/bouncing-effect.cpp new file mode 100644 index 0000000..9961fdf --- /dev/null +++ b/dali-toolkit/public-api/shader-effects/bouncing-effect.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace +{ + +#define MAKE_STRING(A)#A + +const std::string PROGRESS_RATE_PROPERTY_NAME( "uProgressRate" ); + +} // namespace + +BouncingEffect::BouncingEffect() +{ +} + +BouncingEffect::BouncingEffect( ShaderEffect handle ) +:ShaderEffect( handle ) +{ +} + +BouncingEffect::~BouncingEffect() +{ +} + +BouncingEffect BouncingEffect::New( const Vector4& color ) +{ + std::string fragmentShader = MAKE_STRING( + precision mediump float;\n + uniform float uProgressRate;\n + uniform vec4 uAssignedColor;\n + void main()\n + {\n + float progressRate = abs(uProgressRate)*0.5;\n + float amplitude = 0.15 - progressRate*0.15 ;\n + float x1 = 7.5 * (vTexCoord.x - progressRate);\n + float x2 = 7.5 * (vTexCoord.x - 1.0 + progressRate);\n + float height1 = max(0.00001, 0.3 - amplitude * ( exp(x1) + exp(-x1) ) );\n + float height2 = max(0.00001, 0.3 - amplitude * ( exp(x2) + exp(-x2) ) );\n + float height3 = max(0.00001, 1.0 - 3.0 * amplitude * ( exp(x1*0.5) + exp(-x1*0.5) ) );\n + float height4 = max(0.00001, 1.0 - 3.0 * amplitude * ( exp(x2*0.5) + exp(-x2*0.5) ) );\n + vec4 fragColor = vec4(0.0);\n + float y = vTexCoord.y/(height1+height2);\n + float y2 = vTexCoord.y/max(height3,height4);\n + float coef = max(height1,height2)*5.0/( 1.0+exp(y*12.0-6.0) );\n + float alpha = pow( max(0.0,(1.0-y2))*(1.0-min(abs(x1),abs(x2))/5.0), 2.0);\n + if( vTexCoord.y < 0.075 )\n + {\n + fragColor= mix(uAssignedColor, vec4(1.0), coef);\n + fragColor += (vec4(1.0)-fragColor) * alpha;\n + }\n + else if (y2<1.0)\n + {\n + fragColor =vec4(1.0,1.0,1.0, alpha + (1.0-alpha)*coef);\n + fragColor.rgb -= ( vec3(1.0)-uAssignedColor.rgb )*min(clamp(y*1.2-0.3, 0.0, 0.3),clamp(0.9-y*1.2,0.0,0.3));\n + }\n + fragColor.a *= 10.0*min(min(vTexCoord.x, 1.0-vTexCoord.x),0.1)*min(1.0, progressRate/0.2);\n + gl_FragColor = fragColor;\n + } + ); + + ShaderEffect shaderEffect; + shaderEffect = ShaderEffect::New( "", fragmentShader, + GeometryType( GEOMETRY_TYPE_IMAGE), + ShaderEffect::GeometryHints( ShaderEffect::HINT_BLENDING ) ); + BouncingEffect handle( shaderEffect ); + + handle.SetUniform( "uAssignedColor", color ); + handle.SetProgressRate( 0.f ); + + return handle; +} + +void BouncingEffect::SetProgressRate( float progress ) +{ + SetUniform( PROGRESS_RATE_PROPERTY_NAME, progress ); +} + +const std::string& BouncingEffect::GetProgressRatePropertyName() const +{ + return PROGRESS_RATE_PROPERTY_NAME; +} + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/public-api/shader-effects/bouncing-effect.h b/dali-toolkit/public-api/shader-effects/bouncing-effect.h new file mode 100644 index 0000000..eebe525 --- /dev/null +++ b/dali-toolkit/public-api/shader-effects/bouncing-effect.h @@ -0,0 +1,99 @@ +#ifndef __DALI_TOOLKIT_SHADER_EFFECT_BOUNCING_H__ +#define __DALI_TOOLKIT_SHADER_EFFECT_BOUNCING_H__ + +/* + * Copyright (c) 2014 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 + +namespace Dali +{ + +namespace Toolkit +{ + +/** + * @brief BouncingEffect is a custom overscroll effect with two waves appearing at two sides then moving towards center and overlapping. + * + * Usage Example: + * + * // Create the an imageActor, set shader effect, and add it to the stage + * ImageActor imageActor = ImageActor::New( BufferImage::New( 1, 1 ) ); + * imageActor.SetSize(720.f,58.f); + * Toolkit::BouncingEffect bouncingEffect = Toolkit::BouncingEffect::New( Vector4(0.f,1.f,1.f,0.5f) ); + * imageActor.SetShaderEffect( bouncingEffect ); + * imageActor.SetParentOrigin( ParentOrigin::CENTER ); + * Stage::GetCurrent().Add( imageActor ); + * + * // Start the animation + * Animation animation = Animation::New(1.f); + * animation.AnimateTo( Property( bouncingEffect, bouncingEffect.GetProgressRatePropertyName() ), + * 1.f, AlphaFunctions::Bounce ); + * animation.Play(); + */ +class DALI_IMPORT_API BouncingEffect : public ShaderEffect +{ +public: + + /** + * @brief Creates an empty BouncingEffect handle + */ + BouncingEffect(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~BouncingEffect(); + + /** + * @brief Create a BouncingEffect object + * + * @param[in] color The color used on the bouncing stripe + * @return A handle to a newly allocated Dali resource. + */ + static BouncingEffect New( const Vector4& color ); + + /** + * @brief Set the progress rate to the effect. + * + * The whole progress ( with progress rate from 0.0 to 1.0 ): + * two waves appear at two sides; move towards center and overlap. + * @param[in] progressRate The progress rate value. + */ + void SetProgressRate( float progressRate ); + + /** + * @brief Get the name for the progress rate property. + * + * @return A std::string containing the property name. + */ + const std::string& GetProgressRatePropertyName() const; + + +private: // Not intended for application developers + DALI_INTERNAL BouncingEffect( ShaderEffect handle ); + +}; + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_SHADER_EFFECT_BOUNCING_H__ diff --git a/dali-toolkit/public-api/shader-effects/carousel-effect.cpp b/dali-toolkit/public-api/shader-effects/carousel-effect.cpp index 9e360c2..49246cd 100644 --- a/dali-toolkit/public-api/shader-effects/carousel-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/carousel-effect.cpp @@ -69,7 +69,7 @@ CarouselEffect CarouselEffect::New() ShaderEffect shaderEffectCustom = ShaderEffect::New(vertexShader, "", - GeometryType( GEOMETRY_TYPE_IMAGE | GEOMETRY_TYPE_TEXT ), + GeometryType( GEOMETRY_TYPE_IMAGE ), ShaderEffect::GeometryHints( ShaderEffect::HINT_GRID | ShaderEffect::HINT_DEPTH_BUFFER )); // Pass ownership to CarouselEffect through overloaded constructor, So that it now has access to the diff --git a/dali-toolkit/public-api/shader-effects/motion-blur-effect.cpp b/dali-toolkit/public-api/shader-effects/motion-blur-effect.cpp index a444640..9c281b4 100644 --- a/dali-toolkit/public-api/shader-effects/motion-blur-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/motion-blur-effect.cpp @@ -19,10 +19,8 @@ #include // EXTERNAL INCLUDES -#include #include #include -#include namespace Dali { @@ -85,20 +83,15 @@ MotionBlurEffect::~MotionBlurEffect() MotionBlurEffect MotionBlurEffect::Apply( RenderableActor renderable ) { MotionBlurEffect newEffect = New( MOTION_BLUR_NUM_SAMPLES ); - ImageActor imageActor = ImageActor::DownCast(renderable); - if( imageActor ) - { - imageActor.SetShaderEffect( newEffect ); - } + renderable.SetShaderEffect( newEffect ); Dali::Property::Index uModelProperty = newEffect.GetPropertyIndex( MOTION_BLUR_MODEL_LASTFRAME ); - Constraint constraint = Constraint::New( uModelProperty, - Source( renderable, Actor::Property::WORLD_MATRIX ), - EqualToConstraint() ); + Constraint constraint = Constraint::New( newEffect, uModelProperty, EqualToConstraint() ); + constraint.AddSource( Source( renderable, Actor::Property::WORLD_MATRIX ) ); // and set up constraint. - newEffect.ApplyConstraint( constraint ); + constraint.Apply(); return newEffect; } diff --git a/dali-toolkit/public-api/shader-effects/motion-stretch-effect.cpp b/dali-toolkit/public-api/shader-effects/motion-stretch-effect.cpp index 4dd15f2..8817171 100644 --- a/dali-toolkit/public-api/shader-effects/motion-stretch-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/motion-stretch-effect.cpp @@ -19,10 +19,8 @@ #include // EXTERNAL INCLUDES -#include #include #include -#include namespace Dali { @@ -99,21 +97,15 @@ MotionStretchEffect::~MotionStretchEffect() MotionStretchEffect MotionStretchEffect::Apply( RenderableActor renderable ) { MotionStretchEffect newEffect = New(); - - ImageActor imageActor = ImageActor::DownCast(renderable); - if( imageActor ) - { - imageActor.SetShaderEffect( newEffect ); - } + renderable.SetShaderEffect( newEffect ); Dali::Property::Index uModelProperty = newEffect.GetPropertyIndex( MOTION_STRETCH_MODELVIEW_LASTFRAME ); - Constraint constraint = Constraint::New( uModelProperty, - Source( renderable, Actor::Property::WORLD_MATRIX ), - EqualToConstraint() ); + Constraint constraint = Constraint::New( newEffect, uModelProperty, EqualToConstraint() ); + constraint.AddSource( Source( renderable, Actor::Property::WORLD_MATRIX ) ); // and set up constraint. - newEffect.ApplyConstraint(constraint); + constraint.Apply(); return newEffect; } diff --git a/dali-toolkit/public-api/shader-effects/nine-patch-mask-effect.cpp b/dali-toolkit/public-api/shader-effects/nine-patch-mask-effect.cpp index 0aef67f..d2b8967 100644 --- a/dali-toolkit/public-api/shader-effects/nine-patch-mask-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/nine-patch-mask-effect.cpp @@ -19,7 +19,6 @@ #include // EXTERNAL INCLUDES -#include #include #include #include @@ -34,14 +33,17 @@ namespace Toolkit namespace NinePatchMaskEffect { -struct NinePatchMaskEffectSizeConstraint +namespace { - Vector2 operator()( const Vector2& current, const PropertyInput& property ) - { - const Vector3& actorSize = property.GetVector3(); - return Vector2( actorSize.x, actorSize.y ); - } -}; + +void NinePatchMaskEffectSizeConstraint( Vector2& current, const PropertyInputContainer& inputs ) +{ + const Vector3& actorSize = inputs[0]->GetVector3(); + current.x = actorSize.x; + current.y = actorSize.y; +} + +} // unnamed namespace static void DoApply( ImageActor actor, const std::string& maskImage, const Vector2& maskSize, Vector4 maskBorder ) { @@ -90,9 +92,10 @@ static void DoApply( ImageActor actor, const std::string& maskImage, const Vecto maskEffect.SetEffectImage( ResourceImage::New( maskImage ) ); maskEffect.SetUniform( "uImageSize", Vector2(0,0) /*Constrained to actor size*/ ); - maskEffect.ApplyConstraint( Constraint::New( maskEffect.GetPropertyIndex("uImageSize"), - Source(actor, Actor::Property::SIZE), - NinePatchMaskEffectSizeConstraint() ) ); + + Constraint constraint = Constraint::New( maskEffect, maskEffect.GetPropertyIndex("uImageSize"), NinePatchMaskEffectSizeConstraint ); + constraint.AddSource( Source(actor, Actor::Property::SIZE) ); + constraint.Apply(); maskEffect.SetUniform( "uMaskSize", maskSize ); diff --git a/dali-toolkit/public-api/shader-effects/ripple-effect.cpp b/dali-toolkit/public-api/shader-effects/ripple-effect.cpp index 9ebf825..bdbeaec 100644 --- a/dali-toolkit/public-api/shader-effects/ripple-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/ripple-effect.cpp @@ -94,7 +94,7 @@ RippleEffect RippleEffect::New() // Create the implementation, temporarily owned on stack Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( - vertexShader, imageFragmentShader, vertexShader, "", GeometryHints(HINT_GRID) ); + vertexShader, imageFragmentShader, GeometryType(GEOMETRY_TYPE_IMAGE), GeometryHints(HINT_GRID) ); /* Pass ownership to RippleEffect through overloaded constructor, So that it now has access to the Dali::ShaderEffect implementation */ diff --git a/dali-toolkit/public-api/shader-effects/shear-effect.cpp b/dali-toolkit/public-api/shader-effects/shear-effect.cpp index 51d64b7..fb0dd37 100644 --- a/dali-toolkit/public-api/shader-effects/shear-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/shear-effect.cpp @@ -71,7 +71,7 @@ ShearEffect ShearEffect::New() ShaderEffect shaderEffectCustom = Dali::ShaderEffect::New( vertexShader, "", - GeometryType( GEOMETRY_TYPE_IMAGE | GEOMETRY_TYPE_TEXT ), + GeometryType( GEOMETRY_TYPE_IMAGE ), GeometryHints( HINT_GRID )); // Pass ownership to ShearEffect through overloaded constructor, So that it now has access to the diff --git a/dali-toolkit/public-api/shader-effects/soft-button-effect.cpp b/dali-toolkit/public-api/shader-effects/soft-button-effect.cpp index 9789576..f516973 100644 --- a/dali-toolkit/public-api/shader-effects/soft-button-effect.cpp +++ b/dali-toolkit/public-api/shader-effects/soft-button-effect.cpp @@ -16,7 +16,6 @@ */ // EXTERNAL INCLUDES -#include #include #include @@ -58,20 +57,14 @@ const float SOFT_BUTTON_RECTANGLE_SIZE_SCALE_DEFAULT = 0.5f; } // namespace /** - * ReciprocalConstraint + * InverseConstraint * * f(current, property) = 1.0 / property */ -struct ReciprocalConstraint +void InverseConstraint( float& current, const PropertyInputContainer& inputs ) { - ReciprocalConstraint(){} - - float operator()(const float current, const PropertyInput& property) - { - return 1.0f / property.GetFloat(); - } -}; - + current = 1.0f / inputs[0]->GetFloat(); +} //////////////////////////////////////////////////// // @@ -373,8 +366,9 @@ SoftButtonEffect SoftButtonEffect::New(Type type) // precalc 1.0 / uInsideCircleSizeScale on CPU to save shader insns, using constraint to tie to the normal property Dali::Property::Index insideCircleSizeScalePropertyIndex = handle.GetPropertyIndex(SOFT_BUTTON_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME); Dali::Property::Index recipInsideCircleSizeScalePropertyIndex = handle.GetPropertyIndex(SOFT_BUTTON_RECIP_INSIDE_SHAPE_SIZE_SCALE_PROPERTY_NAME); - Constraint constraint = Constraint::New( recipInsideCircleSizeScalePropertyIndex, LocalSource(insideCircleSizeScalePropertyIndex), ReciprocalConstraint()); - handle.ApplyConstraint(constraint); + Constraint constraint = Constraint::New( handle, recipInsideCircleSizeScalePropertyIndex, InverseConstraint ); + constraint.AddSource( LocalSource(insideCircleSizeScalePropertyIndex) ); + constraint.Apply(); } return handle; diff --git a/dali-toolkit/public-api/styling/style-manager.h b/dali-toolkit/public-api/styling/style-manager.h index f7f22a6..2d19f4b 100644 --- a/dali-toolkit/public-api/styling/style-manager.h +++ b/dali-toolkit/public-api/styling/style-manager.h @@ -51,7 +51,7 @@ class StyleManager; * void OnInit(Application& app) * { * Toolkit::StyleManager::Get().RequestThemeChange( CUSTOM_THEME ); - * Toolkit::StyleManager::Get().SetOrientation( app.GetOrientation() ); + * Toolkit::StyleManager::Get().SetOrientation( app.GetWindow().GetOrientation() ); * ... * } * @endcode diff --git a/dali-toolkit/public-api/text/rendering-backend.h b/dali-toolkit/public-api/text/rendering-backend.h new file mode 100644 index 0000000..522a307 --- /dev/null +++ b/dali-toolkit/public-api/text/rendering-backend.h @@ -0,0 +1,45 @@ +#ifndef __DALI_TOOLKIT_RENDERING_BACKEND_H__ +#define __DALI_TOOLKIT_RENDERING_BACKEND_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. + * + */ + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +// The type of text renderer required +enum RenderingType +{ + RENDERING_BASIC, ///< A bitmap-based reference implementation + RENDERING_SHARED_ATLAS ///< A bitmap-based solution where renderers can share a texture atlas +}; + +const unsigned int DEFAULT_RENDERING_BACKEND = RENDERING_SHARED_ATLAS; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // __DALI_TOOLKIT_RENDERING_BACKEND_H__ diff --git a/dali-toolkit/styles/mobile/tizen-dark-theme.json b/dali-toolkit/styles/mobile/tizen-dark-theme.json new file mode 100644 index 0000000..8deaa50 --- /dev/null +++ b/dali-toolkit/styles/mobile/tizen-dark-theme.json @@ -0,0 +1,93 @@ +/* +Copyright (c) 2000-2014 Samsung Electronics Co., Ltd All Rights Reserved + +This file is part of Dali Toolkit + +PROPRIETARY/CONFIDENTIAL + +This software is the confidential and proprietary information of +SAMSUNG ELECTRONICS ("Confidential Information"). You shall not +disclose such Confidential Information and shall use it only in +accordance with the terms of the license agreement you entered +into with SAMSUNG ELECTRONICS. + +SAMSUNG make no representations or warranties about the suitability +of the software, either express or implied, including but not limited +to the implied warranties of merchantability, fitness for a particular +purpose, or non-infringement. SAMSUNG shall not be liable for any +damages suffered by licensee as a result of using, modifying or +distributing this software or its derivatives. +*/ + + + +//****************************************************************************** +// +// Default style theme for Tizen dark theme, The values should come from +// UX design document. +// +//****************************************************************************** + +{ + "styles": + { + "textlabel": + { + "font-family":"SamsungSans", + "font-style":"Regular" + }, + + "textlabel-font-size-0": + { + "point-size":8 + }, + "textlabel-font-size-1": + { + "point-size":10 + }, + "textlabel-font-size-2": + { + "point-size":15 + }, + "textlabel-font-size-3": + { + "point-size":19 + }, + "textlabel-font-size-4": + { + "point-size":25 + }, + + "textfield": + { + "font-family":"SamsungSans", + "font-style":"Regular" + }, + + "textfield-font-size-0": + { + "point-size":10 + }, + "textfield-font-size-1": + { + "point-size":10 + }, + "textfield-font-size-2": + { + "point-size":10 + }, + "textfield-font-size-3": + { + "point-size":10 + }, + "textfield-font-size-4": + { + "point-size":10 + }, + + "scrollview": + { + "overshoot-effect-color":"B018" + } + } +} diff --git a/dali-toolkit/styles/mobile/tizen-default-theme.json b/dali-toolkit/styles/mobile/tizen-default-theme.json new file mode 120000 index 0000000..bdcd8ba --- /dev/null +++ b/dali-toolkit/styles/mobile/tizen-default-theme.json @@ -0,0 +1 @@ +./tizen-dark-theme.json \ No newline at end of file diff --git a/dali-toolkit/styles/tizen-dark-theme.json b/dali-toolkit/styles/tizen-dark-theme.json index a771860..f850715 100644 --- a/dali-toolkit/styles/tizen-dark-theme.json +++ b/dali-toolkit/styles/tizen-dark-theme.json @@ -31,23 +31,17 @@ distributing this software or its derivatives. { "styles": { - "textinput": + "textlabel": { - "highlight-color":"F060", - "cut-and-paste-bg-color":"B061L41", - "cut-and-paste-pressed-color":"B061L41P", - "cut-and-paste-border-color":"B061L42", - "cut-and-paste-icon-color":"T126", - "cut-and-paste-icon-pressed-color":"T126P", - "cut-and-paste-text-color":"T1221", - "cut-and-paste-text-pressed-color":"T1221P", - "cut-button-position-priority":4, - "copy-button-position-priority":3, - "paste-button-position-priority":5, - "select-button-position-priority":1, - "select-all-button-position-priority":2, - "clipboard-button-position-priority":6, - "cursor-color":"F052" + "font-family":"HelveticaNeue", + "font-style":"Regular", + "point-size":18 + }, + "textfield": + { + "font-family":"HelveticaNeue", + "font-style":"Regular", + "point-size":18 }, "scrollview": { diff --git a/docs/content/example-code/property-example.cpp b/docs/content/example-code/property-example.cpp index 35e7869..e0f40e6 100644 --- a/docs/content/example-code/property-example.cpp +++ b/docs/content/example-code/property-example.cpp @@ -101,7 +101,7 @@ class PropertyButtonsController: public ConnectionTracker } // Create the last selected button text view. - mTagText = Toolkit::TextView::New( "None selected" ); + mTagText = Toolkit::TextLabel::New( "None selected" ); mTagText.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); mTagText.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); mTagText.SetPosition( Vector3( 0.0f, -30.0f, 0.0f ) ); @@ -121,14 +121,14 @@ class PropertyButtonsController: public ConnectionTracker // Property::Index index = button.GetPropertyIndex( TAG_PROPERTY_NAME ); valueText << "Selected: " << button.GetProperty< float >( mTagPropertyIndex ); - mTagText.SetText( valueText.str() ); + mTagText.SetProperty( TextLabel::Property::TEXT, valueText.str() ); return true; } private: - Toolkit::TextView mTagText; ///< A text label used to show the last button pressed. + Toolkit::TextLabel mTagText; ///< A text label used to show the last button pressed. Property::Index mTagPropertyIndex; ///< A cached property index of our custom tag property. }; diff --git a/docs/content/images/actors/Text-Actor.png b/docs/content/images/actors/Text-Actor.png deleted file mode 100644 index 6bba38e..0000000 Binary files a/docs/content/images/actors/Text-Actor.png and /dev/null differ diff --git a/docs/content/images/actors/Text-Label.png b/docs/content/images/actors/Text-Label.png new file mode 100644 index 0000000..cc2dc30 Binary files /dev/null and b/docs/content/images/actors/Text-Label.png differ diff --git a/docs/content/images/background/BackgroundTextView.png b/docs/content/images/background/BackgroundTextLabel.png similarity index 100% rename from docs/content/images/background/BackgroundTextView.png rename to docs/content/images/background/BackgroundTextLabel.png diff --git a/docs/content/images/text-controls/ArabicBegin.png b/docs/content/images/text-controls/ArabicBegin.png new file mode 100644 index 0000000..56dcec1 Binary files /dev/null and b/docs/content/images/text-controls/ArabicBegin.png differ diff --git a/docs/content/images/text-controls/ArabicCenter.png b/docs/content/images/text-controls/ArabicCenter.png new file mode 100644 index 0000000..cbc77d3 Binary files /dev/null and b/docs/content/images/text-controls/ArabicCenter.png differ diff --git a/docs/content/images/text-controls/ArabicEnd.png b/docs/content/images/text-controls/ArabicEnd.png new file mode 100644 index 0000000..e35e1a8 Binary files /dev/null and b/docs/content/images/text-controls/ArabicEnd.png differ diff --git a/docs/content/images/text-controls/HelloWorld-HeightForWidth.png b/docs/content/images/text-controls/HelloWorld-HeightForWidth.png new file mode 100644 index 0000000..915862c Binary files /dev/null and b/docs/content/images/text-controls/HelloWorld-HeightForWidth.png differ diff --git a/docs/content/images/text-controls/HelloWorld-NaturalSize.png b/docs/content/images/text-controls/HelloWorld-NaturalSize.png new file mode 100644 index 0000000..28d24d1 Binary files /dev/null and b/docs/content/images/text-controls/HelloWorld-NaturalSize.png differ diff --git a/docs/content/images/text-controls/LatinBegin.png b/docs/content/images/text-controls/LatinBegin.png new file mode 100644 index 0000000..bec2507 Binary files /dev/null and b/docs/content/images/text-controls/LatinBegin.png differ diff --git a/docs/content/images/text-controls/LatinCenter.png b/docs/content/images/text-controls/LatinCenter.png new file mode 100644 index 0000000..ef5aa57 Binary files /dev/null and b/docs/content/images/text-controls/LatinCenter.png differ diff --git a/docs/content/images/text-controls/LatinEnd.png b/docs/content/images/text-controls/LatinEnd.png new file mode 100644 index 0000000..4e22cbc Binary files /dev/null and b/docs/content/images/text-controls/LatinEnd.png differ diff --git a/docs/content/images/text-controls/PlainText.png b/docs/content/images/text-controls/PlainText.png new file mode 100644 index 0000000..5ef9ff1 Binary files /dev/null and b/docs/content/images/text-controls/PlainText.png differ diff --git a/docs/content/images/text-controls/RedText.png b/docs/content/images/text-controls/RedText.png new file mode 100644 index 0000000..f2fe9fe Binary files /dev/null and b/docs/content/images/text-controls/RedText.png differ diff --git a/docs/content/images/text-controls/TextLabelCenter.png b/docs/content/images/text-controls/TextLabelCenter.png new file mode 100644 index 0000000..07558e3 Binary files /dev/null and b/docs/content/images/text-controls/TextLabelCenter.png differ diff --git a/docs/content/images/text-controls/TextLabelTopLeft.png b/docs/content/images/text-controls/TextLabelTopLeft.png new file mode 100644 index 0000000..ad8f492 Binary files /dev/null and b/docs/content/images/text-controls/TextLabelTopLeft.png differ diff --git a/docs/content/images/text-controls/TextWith1pxUnderline.png b/docs/content/images/text-controls/TextWith1pxUnderline.png new file mode 100644 index 0000000..082d19e Binary files /dev/null and b/docs/content/images/text-controls/TextWith1pxUnderline.png differ diff --git a/docs/content/images/text-controls/TextWithBiggerShadow.png b/docs/content/images/text-controls/TextWithBiggerShadow.png new file mode 100644 index 0000000..921f745 Binary files /dev/null and b/docs/content/images/text-controls/TextWithBiggerShadow.png differ diff --git a/docs/content/images/text-controls/TextWithColorShadow.png b/docs/content/images/text-controls/TextWithColorShadow.png new file mode 100644 index 0000000..a82635d Binary files /dev/null and b/docs/content/images/text-controls/TextWithColorShadow.png differ diff --git a/docs/content/images/text-controls/TextWithColorUnderline.png b/docs/content/images/text-controls/TextWithColorUnderline.png new file mode 100644 index 0000000..42ec4ff Binary files /dev/null and b/docs/content/images/text-controls/TextWithColorUnderline.png differ diff --git a/docs/content/images/text-controls/TextWithShadow.png b/docs/content/images/text-controls/TextWithShadow.png new file mode 100644 index 0000000..1cde8d2 Binary files /dev/null and b/docs/content/images/text-controls/TextWithShadow.png differ diff --git a/docs/content/images/text-controls/TextWithUnderline.png b/docs/content/images/text-controls/TextWithUnderline.png new file mode 100644 index 0000000..530920a Binary files /dev/null and b/docs/content/images/text-controls/TextWithUnderline.png differ diff --git a/docs/content/images/text-view/AlessBlessC.png b/docs/content/images/text-view/AlessBlessC.png deleted file mode 100644 index b4cc01c..0000000 Binary files a/docs/content/images/text-view/AlessBlessC.png and /dev/null differ diff --git a/docs/content/images/text-view/Black-Shadow.png b/docs/content/images/text-view/Black-Shadow.png deleted file mode 100644 index 899c8b3..0000000 Binary files a/docs/content/images/text-view/Black-Shadow.png and /dev/null differ diff --git a/docs/content/images/text-view/Blue-Glow.png b/docs/content/images/text-view/Blue-Glow.png deleted file mode 100644 index a9b6cfb..0000000 Binary files a/docs/content/images/text-view/Blue-Glow.png and /dev/null differ diff --git a/docs/content/images/text-view/Bold.png b/docs/content/images/text-view/Bold.png deleted file mode 100644 index 0f4f60e..0000000 Binary files a/docs/content/images/text-view/Bold.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix01.png b/docs/content/images/text-view/FontAppendix01.png deleted file mode 100644 index e600bf4..0000000 Binary files a/docs/content/images/text-view/FontAppendix01.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix02.png b/docs/content/images/text-view/FontAppendix02.png deleted file mode 100644 index 7b002b3..0000000 Binary files a/docs/content/images/text-view/FontAppendix02.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix03.png b/docs/content/images/text-view/FontAppendix03.png deleted file mode 100644 index 024a977..0000000 Binary files a/docs/content/images/text-view/FontAppendix03.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix04.png b/docs/content/images/text-view/FontAppendix04.png deleted file mode 100644 index 337a1d7..0000000 Binary files a/docs/content/images/text-view/FontAppendix04.png and /dev/null differ diff --git a/docs/content/images/text-view/FontAppendix05.png b/docs/content/images/text-view/FontAppendix05.png deleted file mode 100644 index 331daf4..0000000 Binary files a/docs/content/images/text-view/FontAppendix05.png and /dev/null differ diff --git a/docs/content/images/text-view/FreeSerifFont.png b/docs/content/images/text-view/FreeSerifFont.png deleted file mode 100644 index fa945ff..0000000 Binary files a/docs/content/images/text-view/FreeSerifFont.png and /dev/null differ diff --git a/docs/content/images/text-view/Italic.png b/docs/content/images/text-view/Italic.png deleted file mode 100644 index 61fe21e..0000000 Binary files a/docs/content/images/text-view/Italic.png and /dev/null differ diff --git a/docs/content/images/text-view/Red-Outline.png b/docs/content/images/text-view/Red-Outline.png deleted file mode 100644 index 794960b..0000000 Binary files a/docs/content/images/text-view/Red-Outline.png and /dev/null differ diff --git a/docs/content/images/text-view/Smooth-Text.png b/docs/content/images/text-view/Smooth-Text.png deleted file mode 100644 index 7ca0d3b..0000000 Binary files a/docs/content/images/text-view/Smooth-Text.png and /dev/null differ diff --git a/docs/content/images/text-view/Underline.png b/docs/content/images/text-view/Underline.png deleted file mode 100644 index 468cac3..0000000 Binary files a/docs/content/images/text-view/Underline.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-01.png b/docs/content/images/text-view/text-view-example-01.png deleted file mode 100644 index 3b8eacd..0000000 Binary files a/docs/content/images/text-view/text-view-example-01.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-02.png b/docs/content/images/text-view/text-view-example-02.png deleted file mode 100644 index 32a532a..0000000 Binary files a/docs/content/images/text-view/text-view-example-02.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-03.png b/docs/content/images/text-view/text-view-example-03.png deleted file mode 100644 index 0fd7457..0000000 Binary files a/docs/content/images/text-view/text-view-example-03.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-04.png b/docs/content/images/text-view/text-view-example-04.png deleted file mode 100644 index 5d0a2dc..0000000 Binary files a/docs/content/images/text-view/text-view-example-04.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-05.png b/docs/content/images/text-view/text-view-example-05.png deleted file mode 100644 index eccfde5..0000000 Binary files a/docs/content/images/text-view/text-view-example-05.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-06.png b/docs/content/images/text-view/text-view-example-06.png deleted file mode 100644 index 02a5f19..0000000 Binary files a/docs/content/images/text-view/text-view-example-06.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-07.png b/docs/content/images/text-view/text-view-example-07.png deleted file mode 100644 index 2326de4..0000000 Binary files a/docs/content/images/text-view/text-view-example-07.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view-example-08.png b/docs/content/images/text-view/text-view-example-08.png deleted file mode 100644 index 0224b2e..0000000 Binary files a/docs/content/images/text-view/text-view-example-08.png and /dev/null differ diff --git a/docs/content/images/text-view/text-view.png b/docs/content/images/text-view/text-view.png deleted file mode 100644 index 5d11c48..0000000 Binary files a/docs/content/images/text-view/text-view.png and /dev/null differ diff --git a/docs/content/main-page.h b/docs/content/main-page.h index ab76aa7..3802d3d 100644 --- a/docs/content/main-page.h +++ b/docs/content/main-page.h @@ -14,7 +14,7 @@ * - \link hello-world Hello World - explained \endlink * * \section Actors Actors - * - \link image-text-mesh-actor Image, Text and Mesh actors \endlink + * - \link image-mesh-actor Image and Mesh actors \endlink * - \link event-system Event Handling \endlink * - \link custom-actor Custom Actor \endlink * @@ -34,12 +34,10 @@ * - \link size-negotiation Size Negotiation \endlink * * \section UIControls UI Controls + * - \link text-label Text Label \endlink * - \link item-view Item View \endlink - * - \link text-view Text View \endlink - * - \link text-input Text Input \endlink * - \link scroll-view Scroll View \endlink * - \link size-negotiation-controls Size Negotiation for Controls \endlink - * - \link markup-processor Markup Processor \endlink * - \link type-registration Type Registration \endlink * - \link properties Properties \endlink * - \link background Background \endlink diff --git a/docs/content/programming-guide/animation-example.h b/docs/content/programming-guide/animation-example.h index 577dcfe..d133614 100644 --- a/docs/content/programming-guide/animation-example.h +++ b/docs/content/programming-guide/animation-example.h @@ -20,8 +20,8 @@ Here we add the animators, these are the building blocks (functions) of the animation and define what we want to see @code - myAnimation.OpacityTo(actor, 1.0f); - myAnimation.MoveTo(actor, x, y, z); + myAnimation.AnimateTo(Property(actor, Actor::Property::OPACITY), 1.0f); + myAnimation.AnimateTo(Property(actor, Actor::Property::POSITION), Vector3(x, y, z)); @endcode start animation, when this is called we want the animation to start playing so here the actor will move whilst the opacity changes. @@ -30,15 +30,13 @@ @endcode \section advanced-anims Adding more advanced animators, if simply moving the actor is not enough we have further animations methods. - For actor there exists a range of methods ranging from Move, Rotate, Scale, Opacity, Color to Resize. The API explains in detail what each does and the parameters to these methods but there are some points worth noting; - - xxxxBy and xxxxTo, method names are appended by 'By' or 'To' either animate to a supplied value or animate by a supplied value. For example an actor at (10,10,10) calling MoveBy(actor, 50,0,0) would mean its location is (60,0,0) whilst MoveTo(actor, 50,0,0) would result in a location (50,0,0). + AnimateBy and AnimateTo, method names are appended by 'By' or 'To' either animate to a supplied value or animate by a supplied value. For example an actor at (10,10,10) calling AnimateBy(Property(actor, Actor::Property::POSITION), 50,0,0) would mean its location is (60,0,0) whilst AnimateTo(Property(actor, Actor::Property::POSITION), 50,0,0) would result in a location (50,0,0). Dali::AlphaFunctions can be used to give interesting effects to the animation, for example the MOVEment of an actor on screen can speed up and slow down following a sine curve by using the Dali::AlphaFunctions::EaseInOutSine instead of AlphaFunctions::Linear. @code - myAnimation.MoveTo(actor, Vector3(x, y, z), AlphaFunctions::Linear, delay, ANIMATOR_DURATION); - myAnimation.Resize(actor, actorSize, AlphaFunctions::EaseIn, delay, ANIMATOR_DURATION); + myAnimation.AnimateTo(Property(actor, Actor::Property::POSITION), Vector3(x, y, z), AlphaFunctions::Linear, delay, ANIMATOR_DURATION); + myAnimation.AnimateTo(Property(actor, Actor::Property::SIZE), actorSize, AlphaFunctions::EaseIn, delay, ANIMATOR_DURATION); @endcode \section playback-control Controlling a playing animation diff --git a/docs/content/programming-guide/animation-rotation.h b/docs/content/programming-guide/animation-rotation.h index 2e01044..0351ec9 100644 --- a/docs/content/programming-guide/animation-rotation.h +++ b/docs/content/programming-guide/animation-rotation.h @@ -15,19 +15,15 @@ * actor.RotateBy(q); * @endcode * - * The Dali::Animation class provides several RotateTo methods that - * use \ref Dali::Quaternion "Quaternions" directly. The other - * RotateTo methods are specified using Axis+Angle, and these convert - * to Quaternion internally. You will only need to use the quaternion - * based methods when you are doing something more complex than - * initialising with Axis+Angle, such as applying several rotations - * together. + * The Dali::Animation class provides several AnimateTo methods that + * use \ref Dali::Quaternion "Quaternions" directly to change the orientation. + * * @code * mAnimation = Animation::New(5.0f); // 5 seconds * Quaternion q(Radian(Degree(45.0f)).value, Vector3::YAXIS); * Quaternion r(Radian(Degree(30.0f)).value, Vector3::ZAXIS); * q *= r; - * mAnimation.RotateTo(mActor, q, AlphaFunctions::EaseInOut); + * mAnimation.AnimateTo(Property(mActor, Actor::Property::ORIENTATION), q, AlphaFunctions::EaseInOut); * mAnimation.Play(); * @endcode */ diff --git a/docs/content/programming-guide/background.h b/docs/content/programming-guide/background.h index 44972f4..a8dc916 100644 --- a/docs/content/programming-guide/background.h +++ b/docs/content/programming-guide/background.h @@ -16,15 +16,15 @@ control.SetBackgroundColor( Dali::Color::RED ); -This can be used for ALL existing controls like TextView as well: +This can be used for ALL existing controls like TextLabel as well: @code -Dali::Toolkit::TextView textView = Dali::Toolkit::TextView::New( "Hello World" ); -textView.SetBackgroundColor( Dali::Color::RED ); +Dali::Toolkit::TextLabel label = Dali::Toolkit::TextLabel::New( "Hello World" ); +label.SetBackgroundColor( Dali::Color::RED ); @endcode
-\image html BackgroundTextView.png +\image html BackgroundTextLabel.png
diff --git a/docs/content/programming-guide/custom-actor.h b/docs/content/programming-guide/custom-actor.h index 147ad73..808bfca 100644 --- a/docs/content/programming-guide/custom-actor.h +++ b/docs/content/programming-guide/custom-actor.h @@ -2,7 +2,7 @@ * The Dali::CustomActor is used as a base class for UI controls. It is a proxy object to enable derived classes access * to a subset of the methods defined in the internal Actor class. * - * Classes deriving from Custom Actor should follow the same design principle as the rest of the Dali API. + * Classes deriving from Custom Actor should follow the same handle - body design principle as the rest of the Dali API. * * One class of the new UI control should inherit from Dali::CustomActor, while a second should inherit * Dali::CustomActorImpl. This implementation class contains a number of pure virtual methods that enable the new UI @@ -13,30 +13,12 @@ * * In the New() method for the myNewButton class, the user should then create a new instance of the myNewButtonImpl class * and pass this to the constructor of the myNewButton object. Internally the connection will be made - * between the new widget actor and Dali, thus allowing messages such as OnSizeSet to be received by the new actor. + * between the new widget actor and Dali, thus allowing messages such as OnPropertySet to be received by the new actor. * * It is the responsibility of the implementation of the new UI control to implement the method bodies for the inherited * pure virtual methods from Dali::CustomActorImpl. Obviously the application won't compile if the methods are not * overidden, but the user does not need to fill in the code for methods they don't want or need to use. * - * The following code shows the static New() method from the implementation part of the TextView UI control: - * \code - * Dali::Toolkit::TextView TextView::New() - * { - * // Create the implementation, temporarily owned on stack - * boost::intrusive_ptr< TextView > textView = new TextView; - * - * // Pass ownership to CustomActor - * Dali::Toolkit::TextView handle( *textView ); - * - * // Second-phase init of the implementation - * // This can only be done after the CustomActor connection has been made... - * textView->Initialize(); - * - * return handle; - * } - * \endcode - * * After the implementation object is created it is passed back to the basic Text View through the constructor,the * constructor uses this passed in object to initialise the internal implementation objects. * @@ -47,10 +29,4 @@ * handler methods, and do all the rest of their widget processing the the main myNewButton class. Access to the * implementation class can be gained using the GetImpl(*this) method. For example: * - * \code - * void TextView::SetFont(const Font newFont) - * { - * GetImpl(*this).SetFont(newFont); - * } - * \endcode */ diff --git a/docs/content/programming-guide/dynamics-bodies.h b/docs/content/programming-guide/dynamics-bodies.h index a8a9200..a6761d5 100644 --- a/docs/content/programming-guide/dynamics-bodies.h +++ b/docs/content/programming-guide/dynamics-bodies.h @@ -125,7 +125,7 @@ * body.SetKinematic( true ); * // create a second animation to move the actor 100 units to the right * Animation animation( Animation::New( 1 ) ); - * animation.MoveBy( actor, Vector3( 100, 0, 0 ), AlphaFunctions::Linear ); + * animation.AnimateBy( Property( actor, Actor::Property::POSITION ), Vector3( 100, 0, 0 ), AlphaFunctions::Linear ); * animation.Play(); * \endcode *
diff --git a/docs/content/programming-guide/hello-world.h b/docs/content/programming-guide/hello-world.h index 8031d99..2065659 100644 --- a/docs/content/programming-guide/hello-world.h +++ b/docs/content/programming-guide/hello-world.h @@ -12,56 +12,71 @@ Let's take a look at the code for this test application.

Example code

\code -#include -using namespace Dali; +#include -/****************************************************** - * Demonstrates how to display "Hello World" on screen - ******************************************************/ +using namespace Dali; +using Dali::Toolkit::TextLabel; -class ExampleApp +// This example shows how to create and display Hello World! using a simple TextActor +// +class HelloWorldController : public ConnectionTracker { public: - ExampleApp(Application &app) - : mApp(app) + + HelloWorldController( Application& application ) + : mApplication( application ) { - // Connect to Dali::Application init signal. Do not make calls to Dali before this signal is received. - app.SignalInit().Connect(this, &ExampleApp::Create); + // Connect to the Application's Init signal + mApplication.InitSignal().Connect( this, &HelloWorldController::Create ); } - ~ExampleApp() + ~HelloWorldController() { - // Remove Hello World TextActor from stage - Stage::GetCurrent().Remove(mTextActor); + // Remove Hello World actor from stage + Stage::GetCurrent().Remove(mTextLabel); } -public: - - void Create(Application& app) + // The Init signal is received once (only) during the Application lifetime + void Create( Application& application ) { - // Initialize the actor - mTextActor = TextActor::New("Hello World"); + // Get a handle to the stage + Stage stage = Stage::GetCurrent(); + + mTextLabel = TextLabel::New( "Hello World" ); + mTextLabel.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + stage.Add( mTextLabel ); - // Center the actor. Note: default anchor point is CENTER - mTextActor.SetParentOrigin(ParentOrigin::CENTER); + // Respond to a click anywhere on the stage + stage.GetRootLayer().TouchedSignal().Connect( this, &HelloWorldController::OnTouch ); + } - // Display the actor on the stage - Stage::GetCurrent().Add(mTextActor); + bool OnTouch( Actor actor, const TouchEvent& touch ) + { + // quit the application + mApplication.Quit(); + return true; } private: - Application& mApp; - TextActor mTextActor; + Application& mApplication; + TextLabel mTextLabel; }; -int -main(int argc, char **argv) +void RunTest( Application& application ) +{ + HelloWorldController test( application ); + + application.MainLoop(); +} + +// Entry point for Linux & Tizen applications +// +int main( int argc, char **argv ) { - Application daliApp(&argc, &argv); + Application application = Application::New( &argc, &argv ); - ExampleApp helloApp (daliApp); - daliApp.MainLoop(); + RunTest( application ); return 0; } @@ -85,10 +100,10 @@ main(int argc, char **argv) That's why we store the Actor's handle: \code ... - mTextActor = TextActor::New("Hello World"); + mTextLabel = TextLabel::New("Hello World"); ... \endcode - Even if the TextActor is removed from the stage, it will be kept alive through our reference.\n + Even if the TextLabel is removed from the stage, it will be kept alive through our reference.\n You can read more about implicit smart-pointer semantics in chapter \link handle-body-idiom Handle – body\endlink.

Main loop

@@ -107,6 +122,12 @@ main(int argc, char **argv) After running './hello' this should be visible on the screen: - \image html Text-Actor.png "Hello world example" + + + + +
+ \image html Text-Label.png "Hello world example" +
*/ diff --git a/docs/content/programming-guide/image-text-mesh-actor.h b/docs/content/programming-guide/image-mesh-actor.h similarity index 66% rename from docs/content/programming-guide/image-text-mesh-actor.h rename to docs/content/programming-guide/image-mesh-actor.h index 014c95e..c579101 100644 --- a/docs/content/programming-guide/image-text-mesh-actor.h +++ b/docs/content/programming-guide/image-mesh-actor.h @@ -1,12 +1,11 @@ -/*! \page image-text-mesh-actor Image, Text and Mesh actors +/*! \page image-mesh-actor Image and Mesh actors * * *

Overview

- * The Dali::ImageActor, Dali::TextActor, Dali::MeshActor are inherited from Dali::Actor and provide means to display resources like Images, Text and Geometries (Triangle meshes) on the stage. + * The Dali::ImageActor & Dali::MeshActor are inherited from Dali::Actor and provide means to display resources like Images and Geometries (Triangle meshes) on the stage. * All the Dali::Actor methods can be called on them.
* * - ImageActor: An actor for displaying Images. It allows the developer to display a Dali::Image object on the stage.
- * - TextActor: An actor for displaying text.
* - MeshActor: An actor for displaying one or more mesh geometries. It may have children, which may be plain actors or other mesh actors.
* *

Image Actor

@@ -107,80 +106,6 @@ * @endcode * * - * - * - * - *

Text Actor

- * - * - *

Displaying Text

- * The text displayed by the text actor is initialised/set on construction, which can be changed later. - * - * @code - * Dali::TextActor myTextActor = Dali::TextActor::New("Hi"); - * std::string str("Hello"); - * if (myTextActor.GetText() != str) - * { - * myTextActor.SetText(str); - * } - * @endcode - * - * - *

Fonts

- * It's possible to specify a font for the text displayed by the text actor. - * @code - * Dali::Font freeSerif = Dali::Font::New("FreeSerif", 8); - * myTextActor.SetFont(freeSerif); - * @endcode - * - * - *

Ellipsis

- * It is possible to display an ellipsis in the TextActor when the text is truncated. - * @code - * std::string str("..."); - * if (myTextActor.GetEllipsis() != str) - * { - * myTextActor.SetEllipsis(str); - * } - * @endcode - * - *

Style

- * - * By calling the Dali::TextActor::SetTextStyle or by passing a Dali::TextStyle to the constructor, it's possible to define styling parameters such as color, font, size, outline, glow, shadow, italics or bold. - * @code - * TextStyle style; - * style.SetItalic( true ); - * - * myTextActor.SetTextStyle( style ); - * @endcode - * - * @see Dali::TextActor::SetTextStyle() - * - * It is possible to specify the text fit style for the text actor. The developer can specify whether the ellipsis should appear on the left, centre, or at the end - * @code - * // default : NONE - * myTextActor.SetTextFitStyle(TextUtilities::EllipsizeRight); - * @endcode - * - *

Loading state

- * It is possible to get the font loading status for the text and do processing accordingly. - * @code - * // observe text loading and do some processing when it's done - * if( Dali::ResourceLoadingSucceeded == myTextActor.GetLoadingState() ) - * { - * // text already loaded, Do the processing here - * OnTextFontLoaded(); - * } - * else - * { - * // text not yet loaded, Connect to the SignalTextAvailable signal and Do the processing when it occurs - * myTextActor.SignalTextAvailable().Connect(this, &MyClass::OnTextFontLoaded); - * } - * @endcode - * - * - * - * *

Mesh Actor

* *

Construction

diff --git a/docs/content/programming-guide/markup-processor.h b/docs/content/programming-guide/markup-processor.h deleted file mode 100644 index bd8ba9a..0000000 --- a/docs/content/programming-guide/markup-processor.h +++ /dev/null @@ -1,184 +0,0 @@ -/*! \page markup-processor Markup processor - * - *

Overview

- * - * Dali::Toolkit::MarkupProcessor functions provide mechanisms to build and modify a Dali::Toolkit::MarkupProcessor::StyledTextArray used to store text with style. - * - *

Build a styled text array from a markup string

- * - * Dali::Toolkit::MarkupProcessor::GetStyledTextArray() could be used to convert an html-ish markup string into a styled text array. This string uses html-ish tags to - * define the text's style as follows: - * - *
    - *
  • \e \\ Bold text. - * i.e. \Bold text\" - * \image html text-view/Bold.png - * - *
  • \e \\ Italic text. - * i.e. \Italic text\" - * \image html text-view/Italic.png - * - *
  • \e \\ Underlined text. - * i.e. \Underline text\" - * \image html text-view/Underline.png - * - *
  • \e \
    New line. - * - *
  • \e \\ Specifies font properties: - *
      - *
    • \e face The name of a font or font family. - *
    • \e style The style of a font. - *
    • \e size Font point size. @see Dali::PointSize. - *
    • \e color Font color. See the \ref color section for more details. - *
    - * - * i.e. \FreeSerif font\ - * \image html text-view/FreeSerifFont.png - * - *
  • \e \\ Specifies shadow properties. - *
      - *
    • \e paramx X offset. - *
    • \e paramy Y offset. - *
    • \e color Shadow color. See the \ref color section for more details. - *
    - * - * i.e. \Black shadow\ - * \image html text-view/Black-Shadow.png - * - * @see Dali::TextActor::SetShadow() - *

    - *
  • \e \\ Specifies glow properties. - *
      - *
    • \e param Glow around the text. - *
    • \e color Glow color. See the \ref color section for more details. - *
    - * - * i.e. \\Blue glow\\ - * \image html text-view/Blue-Glow.png - * - * @see Dali::TextActor::SetGlow() - *

    - *
  • \e \\ Specifies outline properties. - *
      - *
    • \e paramx X thickness. - *
    • \e paramy Y thickness. - *
    • \e color Outline color. See the \ref color section for more details. - *
    - * - * i.e. \Red outline\ - * \image html text-view/Red-Outline.png - * - * @see Dali::TextActor::SetOutline() - *

    - *
  • \e \\ Specify the smooth edge. - *
      - *
    • \e param Distance field. - *
    - * - * i.e. \Smooth text\ - * \image html text-view/Smooth-Text.png - * - * @see Dali::TextActor::SetSmoothEdge() - *
- * - * See also \ref color, \ref special_characters and \ref example for more details. - * - *

Get a markup string from a styled text array

- * - * Dali::Toolkit::MarkupProcessor::GetMarkupString() could be used to convert a styled text array into an html-ish markup string. - * - *

Modify a styled text array

- * - * Different functions are provided to modify whole or part of a styled text array with a given style. A mask could be used to modify only some properties of the style. - * - * @see Dali::Toolkit::MarkupProcessor::SetTextStyle( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) - * @see Dali::Toolkit::MarkupProcessor::SetTextStyle( const Text& text, StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask ) - * @see Dali::Toolkit::MarkupProcessor::SetTextStyleToRange( StyledTextArray& styledTextArray, const TextStyle& style, TextStyle::Mask mask, std::size_t begin, std::size_t end ) - * - *

Appendix

- * \section color Color - * - * Different options could be used to define a color: - * - *
    - *
  • Hexadecimal with alpha channel. 0xAARRGGBB with the alpha channel in the most significant bits. - *
  • Hexadecimal without alpha channel. 0xRRGGBB. - *
  • Web color format (six or three digits). \#RRGGBB, \#RGB - *
  • Some colors could be defined with natural language: black, white, red, green, blue, yellow, magenta, cyan and \e transparent. - *
- * - * \section special_characters Special characters - * - * \< and \> characters are used to build the html-ish tags. To type them is needed to add a back slash character in front of them. - * @note in c and c++ the back slash is represented with a double back slash '\\\\'. - * - * i.e. text.SetText("a \\< b \\< c"); - * \image html text-view/AlessBlessC.png - * - * It transform any pair CR+LF new line characters into a single LF new line character. - * - * \section fonts Font Style, Weight and Smooth - * - * This appendix shows the differences and relations between the font style, the font weight, the smoothness and the italics. - * - * When a font is loaded, Dali uses different mechanisms to modify the render of glyphs.

- * i.e \Hello World\ produces the "Hello World" bellow. - * \image html text-view/FontAppendix01.png - * By adding the \ \ \ tags to the markup string or using the Dali::TextStyle::SetItalics(), Dali::TextStyle::SetWeight() or Dali::TextStyle::SetSmoothEdge() methods, - * Dali modifies how glyphs of the same font are rendered.

- * i.e \\Hello World\\ - * \image html text-view/FontAppendix02.png - * i.e \\Hello World\\ - * \image html text-view/FontAppendix03.png - * - * The smooth parameter can be used to adjust the thickness of the rendered glyphs.

- * i.e
\\Hello World\\
\

- * \Hello World\\

- * \\Hello World\\\

- * \\Hello World\\\

- * \\Hello World\\ - * - * \image html text-view/FontAppendix04.png - * - * All "Hello World" above have been rendered using the same font, saving some memory. Alternatively, the platform can provide fonts with different styles.
- * - * i.e. Samsung platform provides among others:
- * Samsung Sans:style=Light
- * Samsung Sans:style=Regular
- * Samsung Sans:style=Medium
- * - * \Hello World\\

- * \Hello World\\

- * \Hello World\ - * \image html text-view/FontAppendix05.png - * - * The three "Hello World" above have been rendered with three different fonts.
- * - * The fc-list command can be executed on the platform command line to check with fonts and which styles are supported. - * - * \section example Example - * - * \code - * const std::string text( "" - * "Italics: 기울임 꼴
" - * "Underline: 밑줄
" - * "Bold: 두꺼운
" - * "Font FreeSerif
" - * "Shadow: 그림자
" - * "Glow: 빛나다
" - * "Outline: 윤곽선
" - * "Smooth: 부드럽게
" - * "
" ); - * - * Toolkit::MarkupProcessor::StyledTextArray styledText; - * Toolkit::MarkupProcessor::GetStyledTextArray( text, styledText, true ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( styledText ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * - * \image html text-view/text-view.png - * Text generated with the example above. - */ diff --git a/docs/content/programming-guide/properties.h b/docs/content/programming-guide/properties.h index 8838e78..0a85d51 100644 --- a/docs/content/programming-guide/properties.h +++ b/docs/content/programming-guide/properties.h @@ -244,7 +244,7 @@ This is a basic example of a button defined in JSON by setting the default prope } }, "label-actor": { - "type": "TextView", + "type": "TextLabel", "text": "Normal" } } diff --git a/docs/content/programming-guide/script-hello.h b/docs/content/programming-guide/script-hello.h index 837e022..3bb5ece 100644 --- a/docs/content/programming-guide/script-hello.h +++ b/docs/content/programming-guide/script-hello.h @@ -6,19 +6,13 @@ * * @code * { - * "fonts": - * { - * "freesans": {"name": "FreeSans", "point-size": 12.0, "weight": "WEIGHT_REGULAR" } - * }, - * "actors": - * [ - * {"name":"text-actor", - * "type":"Text", - * "text":"Hello World", - * "font":"freesans", - * "parent-origin":"CENTER" - * } - * ] + * // a tree of actors + * "stage": [{ + * "name": "text-label", + * "type": "TextLabel", + * "text": "Hello World", + * "parent-origin": "CENTER" + * }] * } * @endcode * @@ -31,7 +25,7 @@ * * builder.LoadFromString(json_data); * - * Actor actor = builder.GetActor("text-actor"); + * Actor actor = builder.GetActor("text-label"); * * Stage::GetCurrent().Add(actor); * @endcode @@ -46,15 +40,15 @@ * daliscript hello-world.js * @endcode * - * The TextActor control to display Hello World can be constructed using Javascript dot notation accessing Dali Actor Properties. + * The TextLabel control to display Hello World can be constructed using Javascript dot notation accessing Dali Actor Properties. * * @code - * var textActor = Dali.TextActor(); + * var textLabel = Dali.TextLabel(); * - * textActor.text = "Hello World"; - * textActor.font = "FreeSans"; - * textActor.font-weight = "WEIGHT_REGULAR"; - * textActor.parent-origin = "CENTER"; + * textLabel.text = "Hello World"; + * textLabel.font-family = "FreeSans"; + * textLabel.font-style = "Regular"; + * textLabel.parent-origin = "CENTER"; * * Dali.Run(); * @endcode diff --git a/docs/content/programming-guide/size-negotiation-controls.h b/docs/content/programming-guide/size-negotiation-controls.h index 641da16..d0a8a93 100644 --- a/docs/content/programming-guide/size-negotiation-controls.h +++ b/docs/content/programming-guide/size-negotiation-controls.h @@ -27,7 +27,7 @@ Relayout requests are put in automatically when a property is changed on an acto In addition to the resize policies detailed in the Size Negotiation Programming Guide there is one additional policy available to control writers: -- USE_ASSIGNED_SIZE: Tells the actor to use the size that was passed into the size negotiation algorithm for it. This is used in the OnRelayout +- ResizePolicy::USE_ASSIGNED_SIZE: Tells the actor to use the size that was passed into the size negotiation algorithm for it. This is used in the OnRelayout method derived from Actor when passing back controls to be negotiated using the container argument to the method.

Creating a Control: Popups

@@ -47,43 +47,42 @@ and resized by the popup. The following screen shot shows an example popup. \image html size-negotiation/PopupExample.png The first step is to set the default resize policies. This is done in the OnInitialize method. In the following snippet the popup -is set to have a height resize policy of FIT_TO_CHILDREN. This assumes that the width of the popup will be specified by the user of +is set to have a height resize policy of ResizePolicy::FIT_TO_CHILDREN. This assumes that the width of the popup will be specified by the user of the popup and that the desired behaviour is to fit the height of the popup to the size of its content. @code void Popup::OnInitialize() ... Actor self = Self(); -self.SetResizePolicy( FIT_TO_CHILDREN, HEIGHT ); +self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::HEIGHT ); @endcode The popup will use a layer to place its content in. The layer is created and specified to fill the whole screen by using the following command. @code -mLayer.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); +mLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); @endcode A half transparent backing image is added to the layer and told to fill the layer with the following. @code -mBacking.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); +mBacking.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS ); @endcode The popup control is added to the layer and a background image is specified to fill the size of the popup and add a border by the following. @code -mBackgroundImage.SetResizePolicy( FILL_TO_PARENT, ALL_DIMENSIONS ); -mBackgroundImage.SetSizeMode( SIZE_FIXED_OFFSET_FROM_PARENT ); +mBackgroundImage.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS ); Vector3 border( mPopupStyle->backgroundOuterBorder.x, mPopupStyle->backgroundOuterBorder.z, 0.0f ); mBackgroundImage.SetSizeModeFactor( border ); @endcode A table view is added to the popup to specify layout. It will fill to the width of the popup and expand/contract around its children cell heights. @code -mPopupLayout.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -mPopupLayout.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT ); +mPopupLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); @endcode Override the OnRelayout method to position and resize the buttons. The trick to this is that the buttons do not know they are part of a popup and are about to be resized so could already have had their sizes negotiated. The call to PropagateRelayoutFlags on the button will ensure that it and all its child dependents are ready for a new size negotiation pass. The container.Add call will add the button to the relayout queue to be processed this frame. The buttonSize parameter is the desired size for the button. The desired size will only be set if the size policy of the button has already been changed to -USE_ASSIGNED_SIZE, which is what happens when a button is added to the popup. +ResizePolicy::USE_ASSIGNED_SIZE, which is what happens when a button is added to the popup. @code void Popup::AddButton( Toolkit::Button button ) ... -button.SetResizePolicy( USE_ASSIGNED_SIZE, ALL_DIMENSIONS ); +button.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::ALL_DIMENSIONS ); ... void Popup::OnRelayout( const Vector2& size, RelayoutContainer& container ) @@ -97,22 +96,22 @@ container.Add( button, buttonSize ); Another aspect to the popup is that depending which resize policies are active on it then the inner table view requires different resize policies itself. OnSetResizePolicy can be overridden to receive notice that the resize policy has changed on the control and action can be taken. @code -void Popup::OnSetResizePolicy( ResizePolicy policy, Dimension dimension ) +void Popup::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) ... -if( policy == FIT_TO_CHILDREN ) +if( policy == ResizePolicy::FIT_TO_CHILDREN ) { // Make content fit to children - mPopupLayout.SetResizePolicy( USE_NATURAL_SIZE, dimension ); - if( dimension & HEIGHT ) + mPopupLayout.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, dimension ); + if( dimension & Dimension::HEIGHT ) { mPopupLayout.SetFitHeight( 1 ); } } else { - mPopupLayout.SetResizePolicy( FILL_TO_PARENT, dimension ); + mPopupLayout.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, dimension ); // Make the content cell fill the whole of the available space - if( dimension & HEIGHT ) + if( dimension & Dimension::HEIGHT ) { mPopupLayout.SetRelativeHeight( 1, 1.0f ); } @@ -138,7 +137,7 @@ These overridable methods in control provide customization points for the size n

Responding to the Change of Size on a Control

OnRelayout is called during the relayout process at the end of the frame immediately after the new size has been set on the actor. If the actor has calculated -the size of child actors then add them to container with their desired size and set the USE_ASSIGNED_SIZE resize policy on them. +the size of child actors then add them to container with their desired size and set the ResizePolicy::USE_ASSIGNED_SIZE resize policy on them. At this point the size of the actor has been calculated so it is a good place to calculate positions of child actors etc. @code virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) @endcode @@ -149,11 +148,11 @@ children of an actor that is not a control. The OnCalculateRelayoutSize is called right before the size is calculated for an actor's dimension during the size negotiation phase. At this point all other actors this actor is dependent on have been negotiated so calculations depending on these actors can be performed before the size for this actor is calculated. Useful for container size calculations. -@code virtual void OnCalculateRelayoutSize( Dimension dimension ) @endcode +@code virtual void OnCalculateRelayoutSize( Dimension::Type dimension ) @endcode OnLayoutNegotiated is called right after the size in a given dimension has been negotiated for an actor. This allows calculations to be performed in response to the change in a given dimension but before OnRelayout is called. -@code virtual void OnLayoutNegotiated( float size, Dimension dimension ) @endcode +@code virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ) @endcode

Calculating Sizes

@@ -161,11 +160,11 @@ Calculate the natural size for this control. This will be called when a control' For example, TableView will calculated the size of the table given its various cell properties. @code virtual Vector3 GetNaturalSize() @endcode -Given an input width return the correct height for this control. This will be called when the resize policy is set to DIMENSION_DEPENDENCY and +Given an input width return the correct height for this control. This will be called when the resize policy is set to ResizePolicy::DIMENSION_DEPENDENCY and height has a dependency on width. @code virtual float GetHeightForWidth( float width ) @endcode -Given the input height return the correct width for this control. This will be called when the resize policy is set to DIMENSION_DEPENDENCY and +Given the input height return the correct width for this control. This will be called when the resize policy is set to ResizePolicy::DIMENSION_DEPENDENCY and width has a dependency on height. @code virtual float GetWidthForHeight( float height ) @endcode @@ -173,15 +172,15 @@ width has a dependency on height. Return true from this method if this control is dependent on any of its children to calculate its own size. All relayout containers that can be dependent on their children for their own size need to return true from this. -@code virtual bool RelayoutDependentOnChildren( Dimension dimension = ALL_DIMENSIONS ) @endcode +@code virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) @endcode -This will be called by children when they are using the FILL_TO_PARENT resize policy. It is the parent's responsibility to calculate the child's correct size. -@code virtual float CalculateChildSize( const Dali::Actor& child, Dimension dimension ) @endcode +This will be called by children when they are using the ResizePolicy::FILL_TO_PARENT resize policy. It is the parent's responsibility to calculate the child's correct size. +@code virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) @endcode

Events

OnSetResizePolicy is called when the resize policy is set on an actor. Allows deriving actors to respond to changes in resize policy. -@code virtual void OnSetResizePolicy( ResizePolicy policy, Dimension dimension ) @endcode +@code virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) @endcode

Creating a Control: TableView

@@ -198,19 +197,19 @@ We need to be able to calculate the fixed sizes of all actors placed into table this is called every actor the table view is dependent on has already had their sizes calculated. Calculations can be made that the main calculation for the actor can then use. @code -void TableView::OnCalculateRelayoutSize( Dimension dimension ) +void TableView::OnCalculateRelayoutSize( Dimension::Type dimension ) ... CalculateRowColumnData(); -if( dimension & WIDTH ) +if( dimension & Dimension::WIDTH ) { - CalculateFixedSizes( mColumnData, WIDTH ); + CalculateFixedSizes( mColumnData, Dimension::WIDTH ); mFixedTotals.width = CalculateTotalFixedSize( mColumnData ); } -if( dimension & HEIGHT ) +if( dimension & Dimension::HEIGHT ) { - CalculateFixedSizes( mRowData, HEIGHT ); + CalculateFixedSizes( mRowData, Dimension::HEIGHT ); mFixedTotals.height = CalculateTotalFixedSize( mRowData ); } ... @@ -226,7 +225,7 @@ return Vector3( mFixedTotals.width, mFixedTotals.height, 1.0f ); When the time comes to calculate the size of each child in the table cells the following method will be called. @code -float TableView::CalculateChildSize( const Actor& child, Dimension dimension ) +float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimension ) ... // Use cell data to calculate child size @endcode @@ -234,7 +233,7 @@ float TableView::CalculateChildSize( const Actor& child, Dimension dimension ) The table view is dependent on its children if its size policy is set to USE_NATURAL_SIZE or a row or column is set to "fit" an actor. The following code shows calling the base class RelayoutDependentOnChildren to check the resize policy and then searches for fit row or columns. @code -bool TableView::RelayoutDependentOnChildren( Dimension dimension ) +bool TableView::RelayoutDependentOnChildren( Dimension::Type dimension ) { if ( Control::RelayoutDependentOnChildren( dimension ) ) { diff --git a/docs/content/programming-guide/size-negotiation.h b/docs/content/programming-guide/size-negotiation.h index 536a8f8..2f64d83 100644 --- a/docs/content/programming-guide/size-negotiation.h +++ b/docs/content/programming-guide/size-negotiation.h @@ -18,10 +18,10 @@ The topics covered are: The notion of width and height is generalised into the concept of a Dimension. Several methods take a Dimension parameter. The Dimension enum specifies the available dimensions as bitfields: -- WIDTH -- HEIGHT +- Dimension::WIDTH +- Dimension::HEIGHT -If a method can process width and height at the same time then the ALL_DIMENSIONS mask can be specified. +If a method can process width and height at the same time then the Dimension::ALL_DIMENSIONS mask can be specified.

Resize Policies

@@ -29,11 +29,13 @@ If a method can process width and height at the same time then the ALL_DIMENSION The ResizePolicy enum specifies a range of options for controlling the way actors resize. These are powerful rules that enable much automatic resizing behaviour. They are as following: -- FIXED: This is the option to use when you want the specific definite size as set by SetPreferredSize -- USE_NATURAL_SIZE: Use this option for objects such as images or text to get their natural size e.g. The dimensions of the image, or the size of the text without wrapping. Also use this on TableViews when the size of the table is dependent on its children. -- FILL_TO_PARENT: Size will fill up to the size of its parent's size, taking a size factor into account to allow proportionate filling -- FIT_TO_CHILDREN: Size will scale around the size of the actor's children. E.g. A popup's height may resize itself around it's contents. -- DIMENSION_DEPENDENCY: This covers rules such as width-for-height and height-for-width. You specify that one dimension depends on another. +- ResizePolicy::FIXED: This is the option to use when you want the specific definite size as set by SetSize (This is the default for all actors) +- ResizePolicy::USE_NATURAL_SIZE: Use this option for objects such as images or text to get their natural size e.g. The dimensions of the image, or the size of the text without wrapping. Also use this on TableViews when the size of the table is dependent on its children. +- ResizePolicy::FILL_TO_PARENT: Size will fill up to the size of its parent's size, taking a size factor into account to allow proportionate filling +- ResizePolicy::SIZE_RELATIVE_TO_PARENT: Fill up the parent with a relative scale. Use SetSizeModeFactor to specify the ratio to fill up to the parent. +- ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT: Fill up the parent and add a fixed offset using SetSizeModeFactor. +- ResizePolicy::FIT_TO_CHILDREN: Size will scale around the size of the actor's children. E.g. A popup's height may resize itself around it's contents. +- ResizePolicy::DIMENSION_DEPENDENCY: This covers rules such as width-for-height and height-for-width. You specify that one dimension depends on another. \image html size-negotiation/ResizePolicies.png @@ -44,19 +46,23 @@ This section details how an actor may be used with size negotiation.

Enabling Size Negotiation

The first thing to do is to specify whether you want an actor to be included or excluded from the relayout process. The following method is used to enable or disable the relayout -for an individual actor. +for an individual actor. Make sure this is the first thing that is called after the actor is created otherwise the actor may still be negotiated. @code void SetRelayoutEnabled( bool enabled ) @endcode Text and image actors have relayout enabled by default, while a plain Actor is disabled. Be aware that if desiring to use an Actor in relayout then relayout needs to be explicitly enabled first.

Specifying Size Policies

+Actors have different size policies by default. For example ImageActor is set to USE_NATURAL_SIZE. This ensures that when an image actor is +placed on the stage it will use its natural size by default. However if the user calls SetSize with non-zero sizes on the image actor then the current +size policy is overridden by the FIXED size policy and the actor will take on the size specified. + The next step is to specify how an actor will be size negotiated. The resize policies for an actor may be specified by the following method: -@code void SetResizePolicy( ResizePolicy policy, Dimension dimension ) @endcode +@code void SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) @endcode It is common to specifiy different policies for the different dimensions of width and height to achive different layouts. Different actors have different resize policies specified by default. For example ImageActors are set to use USE_NATURAL_SIZE. -The following example code snippet shows rootActor having its width policy set to FILL_TO_PARENT and its height policy set to FIT_TO_CHILDREN. +The following example code snippet shows rootActor having its width policy set to ResizePolicy::FILL_TO_PARENT and its height policy set to ResizePolicy::FIT_TO_CHILDREN. It has an ImageActor added to it with an explicit call to USE_NATURAL_SIZE in both dimensions called on it. This will make an actor that will fill up the space of its parent in the width dimension and fit to its child in the height dimension. As the image actor child is using natural size the height of the root actor will fit to the height of the child image. @@ -64,10 +70,10 @@ the height of the root actor will fit to the height of the child image. @code Actor rootActor = Actor::New(); rootActor.SetRelayoutEnabled( true ); -rootActor.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -rootActor.SetResizePolicy( FIT_TO_CHILDREN, HEIGHT ); +rootActor.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +rootActor.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::HEIGHT ); ImageActor image = ImageActor::New( Image::New( MY_IMAGE_PATH ) ); -image.SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS ); +image.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); rootActor.Add( image ); @endcode @@ -81,24 +87,19 @@ After: This example shows an actor rootActor set to expand to its parent's width and contract/expand around its child's height. The child image actor is set to natural size which means it will display at the acutal size of the image. -To specify that a dimension has a dependency on another dimension use the following method. Calling this method will automatically set the resize policy to be DIMENSION_DEPENDENCY -for the given dimension. -@code void SetDimensionDependency( Dimension dimension, Dimension dependency ) @endcode -For example if dimension is HEIGHT and dependency is WIDTH then there is a height-for-width dependency in effect. The classic use case for this +To specify that a dimension has a dependency on another dimension use ResizePolicy::DIMENSION_DEPENDENCY. For example if dimension is Dimension::HEIGHT and dependency is +Dimension::WIDTH then there is a height-for-width dependency in effect. The classic use case for this is a text view that wraps its text. The following example snippet shows a text view that expands its width to the size of its parent, wraps its contents and then determines its height based on the width. @code -TextView text = TextView::New( "Example" ); -text.SetMultilinePolicy( SplitByWord ); -text.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -text.SetDimensionDependency( HEIGHT, WIDTH ); +TextLabel text = TextLabel::New( "Example" ); +text.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +text.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); @endcode

Specifying Sizes and Size Limits

-When wanting a specific fixed size for an actor then specify the resize policy to be FIXED and set the desired, or preferred size using the following method. -This method is to be used instead of SetSize when wishing to specify a size for an actor being size negotiated. -@code void SetPreferredSize( const Vector2& size ) @endcode +When wanting a specific fixed size for an actor then specify the resize policy to be FIXED and set the desired, or preferred size using SetSize. If only one dimension is FIXED then the other value in the size parameter will be ignored, so it is safe to set it to zero. To constrain the final negotiated size of an actor, set the following for minimum and maximum sizes respectively. @@ -109,19 +110,11 @@ void SetMaximumSize( const Vector2& size )

Altering Negotiated Size

-The following method specifies a size mode to use. Use one of: USE_OWN_SIZE, SIZE_RELATIVE_TO_PARENT or SIZE_FIXED_OFFSET_FROM_PARENT. SIZE_RELATIVE_TO_PARENT will -scale the image relative to it's parent size when the resize policy of FILL_TO_PARENT is in effect. While SIZE_FIXED_OFFSET_FROM_PARENT will -add an offset to this parent size, for example when wanting an image to act as a border around its parent. -@code void SetSizeMode( const SizeMode mode ) @endcode - -Use the following with SetSizeMode to specify either the size relative to parent or the fixed offset to apply. -@code void SetSizeModeFactor( const Vector3& factor ) @endcode - When an actor is required to maintain the aspect ratio of its natural size the following method can be used. This is useful for size negotiating images -to ensure they maintain their aspect ratio while still fitting within the bounds they have been allocated. This can be one of USE_SIZE_SET, FIT_WITH_ASPECT_RATIO -or FILL_WITH_ASPECT_RATIO. The first is the default. The second will fit the actor within the bounds it has been allocated while maintaining aspect ratio. The +to ensure they maintain their aspect ratio while still fitting within the bounds they have been allocated. This can be one of SizeScalePolicy::USE_SIZE_SET, SizeScalePolicy::FIT_WITH_ASPECT_RATIO +or SizeScalePolicy::FILL_WITH_ASPECT_RATIO. The first is the default. The second will fit the actor within the bounds it has been allocated while maintaining aspect ratio. The third will fill all available space, potentially overflowing its bounds, while maintaining apsect ratio. -@code void SetSizeScalePolicy( SizeScalePolicy policy ) @endcode +@code void SetSizeScalePolicy( SizeScalePolicy::Type policy ) @endcode

Using Actors in Containers

@@ -139,34 +132,30 @@ mPopup.SetTitle( "Warning" ); // Content Toolkit::TableView content = Toolkit::TableView::New( 2, 2 ); -content.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -content.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT ); +content.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +content.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); content.SetFitHeight( 0 ); content.SetFitHeight( 1 ); content.SetPadding( Padding( 20.0f, 20.0f, 20.0f, 0.0f ) ); // Text -Toolkit::TextView text = Toolkit::TextView::New(); -text.SetText( "Do you really want to quit?" ); -text.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); -text.SetWidthExceedPolicy( Toolkit::TextView::Split ); -text.SetLineJustification( Toolkit::TextView::Left ); -text.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -text.SetDimensionDependency( HEIGHT, WIDTH ); +Toolkit::TextLabel text = Toolkit::TextLabel::New( "Do you really want to quit?" ); +text.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +text.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); content.AddChild( text, Toolkit::TableView::CellPosition( 0, 0 ) ); // Image ImageActor image = ImageActor::New( ResourceImage::New( IMAGE1 ) ); -image.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -image.SetDimensionDependency( HEIGHT, WIDTH ); +image.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +image.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); image.SetPadding( Padding( 20.0f, 0.0f, 0.0f, 0.0f ) ); content.AddChild( image, Toolkit::TableView::CellPosition( 0, 1 ) ); // Checkbox and text Toolkit::TableView root = Toolkit::TableView::New( 1, 2 ); -root.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -root.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT ); +root.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +root.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); root.SetFitHeight( 0 ); root.SetFitWidth( 0 ); root.SetPadding( Padding( 0.0f, 0.0f, 0.0f, 20.0f ) ); @@ -176,14 +165,11 @@ Dali::Image checked = Dali::ResourceImage::New( CHECKBOX_CHECKED_IMAGE ); Toolkit::CheckBoxButton checkBox = Toolkit::CheckBoxButton::New(); checkBox.SetBackgroundImage( unchecked ); checkBox.SetSelectedImage( checked ); -checkBox.SetPreferredSize( Vector2( 48, 48 ) ); -checkBox.SetResizePolicy( FIXED, ALL_DIMENSIONS ); +checkBox.SetSize( Vector2( 48, 48 ) ); root.AddChild( checkBox, Toolkit::TableView::CellPosition( 0, 0 ) ); -Toolkit::TextView text2 = Toolkit::TextView::New(); -text2.SetText( "Don't show again" ); -text2.SetLineJustification( Toolkit::TextView::Left ); +Toolkit::TextLabel text2 = Toolkit::TextLabel::New( "Don't show again" ); text2.SetPadding( Padding( 20.0f, 0.0f, 0.0f, 10.0f ) ); root.AddChild( text2, Toolkit::TableView::CellPosition( 0, 1 ) ); @@ -197,42 +183,42 @@ The resulting popup with additional buttons added is shown below. \image html size-negotiation/Popup.png The key things to pick out from this example are the use of the size negotiation API. -The content table view is set to FILL_TO_PARENT for its width and USE_NATURAL_SIZE for its height. This will result +The content table view is set to ResizePolicy::FILL_TO_PARENT for its width and USE_NATURAL_SIZE for its height. This will result in the table view expanding its width to fit the available space in the popup while also expanding/contracting its height based on the size of the contents in its cells. @code -content.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -content.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT ); +content.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +content.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); @endcode To add a little space around the left, right and bottom of the table view, some padding is added. @code content.SetPadding( Padding( 20.0f, 20.0f, 20.0f, 0.0f ) ); @endcode -The first text view has its width set to FILL_TO_PARENT and its height has a dimension dependency on its width. This +The first text view has its width set to ResizePolicy::FILL_TO_PARENT and its height has a dimension dependency on its width. This will result in a text view that fills up its width to available space in the table cell and then then calculates its height based on its new width. The table view will then fit its height taking the height of the text view into account. @code -text.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -text.SetDimensionDependency( HEIGHT, WIDTH ); +text.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +text.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); @endcode The image view performs a similar relayout. It fits its width to the size of the cell and calculates its height based on the new width. Some padding is added to the left of it as well to center it more. @code -image.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -image.SetDimensionDependency( HEIGHT, WIDTH ); +image.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +image.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); image.SetPadding( Padding( 20.0f, 0.0f, 0.0f, 0.0f ) ); @endcode The sub table view is similar as well in that it expands its width to the size of its cell. When it is added to the table view it will span two columns. Its height is set to natural size so that it will grow or shrink based on its children cells. Note that for -a container like table view, USE_NATURAL_SIZE acts in a similar manner to FIT_TO_CHILDREN in that the size of the container could +a container like table view, USE_NATURAL_SIZE acts in a similar manner to ResizePolicy::FIT_TO_CHILDREN in that the size of the container could grow or shrink based on the sizes of the child actors. @code -root.SetResizePolicy( FILL_TO_PARENT, WIDTH ); -root.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT ); +root.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +root.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); @endcode The checkbox is set to have a fixed size. @code -checkBox.SetResizePolicy( FIXED, ALL_DIMENSIONS ); +checkBox.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS ); @endcode The second text view has not specified a resize policy so will use its default of USE_NATURAL_SIZE. @@ -243,10 +229,10 @@ describe a pitfall to avoid when creating scenes and a way to print debug output

Infinite Dependency Loops

Despite the power of the resize rules there is one pitfall to be aware of: infinite dependency loops. The most simplest form of this is -shown by a parent actor with resize policy set to FIT_TO_CHILDREN with a child that has a resize policy of FILL_TO_PARENT. Who should -determine the size in this case? A more complex loop occurs when DIMENSION_DEPENDENCY comes into play. Say a parent has a width policy -of DIMENSION_DEPENDENCY with height and a height policy of FIT_TO_CHILDREN. The parent has a single child with a height policy DIMENSION_DEPENDENCY -with width. If the child's width policy is FILL_TO_PARENT then a loop will occur. These are two simple examples but the loops could occur +shown by a parent actor with resize policy set to ResizePolicy::FIT_TO_CHILDREN with a child that has a resize policy of ResizePolicy::FILL_TO_PARENT. Who should +determine the size in this case? A more complex loop occurs when ResizePolicy::DIMENSION_DEPENDENCY comes into play. Say a parent has a width policy +of ResizePolicy::DIMENSION_DEPENDENCY with height and a height policy of ResizePolicy::FIT_TO_CHILDREN. The parent has a single child with a height policy ResizePolicy::DIMENSION_DEPENDENCY +with width. If the child's width policy is ResizePolicy::FILL_TO_PARENT then a loop will occur. These are two simple examples but the loops could occur over larger spreads of parent child relationships. These loops are detected by the relayout algorithm with the result being that actors will receive zero sizes. These loops are not common but are still something to watch out for. @@ -263,7 +249,7 @@ PushButton, OKAY_BUTTON - Pos: [185, 0, 0.1] Size: [165, 76, 76], Dirty: (FALSE, The format is as follows: -[Actor type], [Actor name] – Pos:[X, Y, Z] Size[WIDTH, HEIGHT, DEPTH], Dirty:(WIDTH, HEIGHT), Negotiated: (WIDTH, HEIGHT), Enabled: BOOLEAN, (Object address) +[Actor type], [Actor name] – Pos:[X, Y, Z] Size[Dimension::WIDTH, Dimension::HEIGHT, DEPTH], Dirty:(Dimension::WIDTH, Dimension::HEIGHT), Negotiated: (Dimension::WIDTH, Dimension::HEIGHT), Enabled: BOOLEAN, (Object address) - Actor type: The type name of the actor E.g. PushButton - Actor name: The name set on the actor with SetName(). Useful for debugging. - Pos: The position of the actor diff --git a/docs/content/programming-guide/text-input.h b/docs/content/programming-guide/text-input.h deleted file mode 100644 index cc24e46..0000000 --- a/docs/content/programming-guide/text-input.h +++ /dev/null @@ -1,92 +0,0 @@ -/*! \page text-input Text Input - * - TextInput is a Dali::Actor which allows the input of text from an on-screen virtual keyboard or attached hardware keyboard. - - -

Basic Text Input Set-up

- - The below code creates a new TextInput - - @code - Dali::Toolkit::TextInput myTextInput; - myTextInput = Dali::Toolkit::TextInput::New(); - @endcode - - The following code sets the size and adds it to the stage - @code - myTextInput.SetParentOrigin(ParentOrigin::CENTER); - myTextInput.SetSize(stageWidth*0.25f, stageWidth*0.5f); - Stage::GetCurrent().Add(myTextInput); - @endcode - - For a TextInput to receive input from the keyboard it must be in edit mode. - - To enter edit mode the below call can be made. If the virtual on-screen keyboard is supported then it will be displayed. - Internally TextInput will set focus to this TextInput and key events will be sent to it. - - @code myTextInput.SetEditable(true);@endcode - - After this call the TextInput will receive any key press. If you have more than one TextInput the focus will change between them when the edit mode is - initiated on any Text Input. - - To automatically start edit mode when the TextInput is "tapped" you can call the following: - - @code myTextInput.SetEditOnTouch()@endcode - - You will then need to end edit mode by making the call below or swiping away the keyboard (Virtual On-screen Keyboard) - @code myTextInput.SetEditable(false);@endcode - - The call will hide the virtual keyboard if previously shown by Text Input. - - Then the input string as plain text can be retrieved using - @code Dali::Toolkit::TextInput::GetText()@endcode - -

Text Selection

- - The SetTextSelectable API when set to true enables text to be highlighted, once highlighted the text style can be changed, - the text can be cut, or copied, overwritten with new text or deleted. - - The user does a Long-Press on the text to get the option of text selection. - - @code Dali::Toolkit::TextInput::SetTextSelectable( true ) @endcode - -

Text Styling

- - In conjunction with TextView and the Markup processor, TextInput enables text to be styled. - - There are 3 ways to effect the text styling. - - SetActiveStyle, new input text is set to the Red glow style - @code - TextStyle style; - style.SetGlow ( true, Dali::Color::RED ); - myTextInput.SetActiveStyle( style, MarkupProcessor::GLOW ); - @endcode - - ApplyStyle, selected/highlighted text now has the Red glow style - @code - TextStyle style; - style.SetGlow ( true, Dali::Color::RED ); - myTextInput.ApplyStyle( style, MarkupProcessor::GLOW ); - @endcode - - ApplyStyleToAll, all text now has the Red glow style - @code - TextStyle style; - style.SetGlow ( true, Dali::Color::RED ); - myTextInput.ApplyStyleToAll( style, MarkupProcessor::GLOW ); - @endcode - - Then the input string with Mark-up defining the style can be retrieved using - @code Dali::Toolkit::TextInput::GetMarkupText()@endcode - This would be usefull if you wish to save the styled text the user has input so it can be re-displayed another time. - - Signals are emitted when style changes. - - See Dali::Toolkit::TextInput::StyleMask for available styling options. - - - - - */ - diff --git a/docs/content/programming-guide/text-label.h b/docs/content/programming-guide/text-label.h new file mode 100644 index 0000000..24f8b1b --- /dev/null +++ b/docs/content/programming-guide/text-label.h @@ -0,0 +1,343 @@ +/*! \page text-label Text Label + * +\section overview Overview +The Dali::Toolkit::TextLabel is a Dali::Toolkit::Control which renders a short text string.\n +Text labels are lightweight, non-editable and do not respond to user input. + +\subsection basictextlabelusage Basic usage + +To display a TextLabel the TEXT property must be set using a UTF-8 string. + +\code +TextLabel label = TextLabel::New(); +label.SetProperty( TextLabel::Property::TEXT, "Hello World" ); +label.SetAnchorPoint( AnchorPoint::TOP_LEFT ); +Stage::GetCurrent().Add( label ); +\endcode + +The label must also be added to the stage, or to an actor which is on the stage.\n +The position of the label on-screen is dependent on the parent-origin and anchor-point properties.\n + + + + + + + + +
+ \image html TextLabelTopLeft.png +
+ (ParentOrigin::TOP_LEFT, AnchorPoint::TOP_LEFT) +
+ +\subsection fontSelection Font Selection + +By default TextLabel will automatically select a suitable font from the platform.\n +Typically fonts do not support all scripts, for example Latin fonts often do not provide Arabic glyphs.\n +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: +\code +label.SetProperty( TextLabel::Property::FONT_FAMILY, "HelveticaNue" ); +label.SetProperty( TextLabel::Property::FONT_STYLE, "Regular" ); +label.SetProperty( TextLabel::Property::POINT_SIZE, 12.0f ); +\endcode +However the TextLabel will fall-back to using the default font, if the requested font does not support the required scripts. + +\subsection fontStyles Font Styles + +Setting a font size programmatically is not ideal for applications which support multiple screen resolutions etc.\n +A more flexible approach is to prepare various JSON stylesheets, and request a different style for each platform:\n + +\code +StyleManager styleManager = StyleManager::Get(); +styleManager.RequestThemeChange( "example-path/example.json" ); +\endcode + +To change the font for standard text labels, this JSON syntax can be used: + +\code +{ + "styles": + { + "textlabel": + { + "font-family":"Arial", + "font-style":"Regular", + "point-size":8 + } + } +} +\endcode + +However the same point-size is unlikely to be suitable for all labels in an application.\n +To set custom sizes simply set a "style name" for each case, and then provide a style override in JSON: + +\code + label.SetProperty( Control::Property::STYLE_NAME, "custom" ); +\endcode + +\code +{ + "styles": + { + "textlabel": + { + "font-family":"Arial", + "font-style":"Regular", + "point-size":8 + }, + + "custom": + { + "point-size":10 + } + } +} +\endcode + +In the example above, standard text labels will have point-size 8, and "custom" labels will have point-size 10.\n + +\subsection textAlignment Text Alignment + +Wrapping can be enabled using the MULTI_LINE property:\n +\code +label.SetProperty( TextLabel::Property::MULTI_LINE, true ); +\endcode + +The text can be either aligned horizontally to the beginning, end, or center of the available area: +\code +label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "BEGIN" ); // "CENTER" or "END" +\endcode + + + + + + + + + + + + + + + + + + + + + + + +
+ Here is the "BEGIN" alignment shown for left-to-right (Latin) and right-to-left (Arabic) scripts: +
+ \image html LatinBegin.png + + \image html ArabicBegin.png +
+ Here is the "CENTER" alignment shown for left-to-right (Latin) and right-to-left (Arabic) scripts: +
+ \image html LatinCenter.png + + \image html ArabicCenter.png +
+ Here is the "END" alignment shown for left-to-right (Latin) and right-to-left (Arabic) scripts: +
+ \image html LatinEnd.png + + \image html ArabicEnd.png +
+ +The examples above assume that the TextLabel size greater than the minimum required.\n +The next section provides details about the other size related options. + +\subsection negotiatingSize Negotiating size + +\link size-negotiation Size negotiation \endlink is a layouting feature supported by UI controls such as TextLabel.\n +There are several resize policies which are commonly used with TextLabels.\n +The following examples show TextLabels actual size by setting a colored background, whilst the black area represents the size of the parent control:\n + +

Using natural size

+ +With a "natural" size TextLabel will be large enough to display the text without wrapping, and will not have extra space to align the text within.\n +Therefore in this example the same result would be displayed, regardless of the alignment or multi-line properties.\n + +\code +TextLabel label = TextLabel::New( "Hello World" ); +label.SetAnchorPoint( AnchorPoint::TOP_LEFT ); +label.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); +label.SetBackgroundColor( Color::BLUE ); +Stage::GetCurrent().Add( label ); +\endcode + + + + + +
+ \image html HelloWorld-NaturalSize.png +
+ +

Height-for-width negotiation

+ +To layout text labels vertically, a fixed (maximum) width should be provided by the parent control.\n +Each TextLabel will then report a desired height for the given width.\n +Here is an example of this behavior using TableView as the parent: + +\code +TableView parent = TableView::New( 3, 1 ); +parent.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +parent.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::HEIGHT ); +parent.SetAnchorPoint( AnchorPoint::TOP_LEFT ); +Stage::GetCurrent().Add( parent ); + +TextLabel label = TextLabel::New( "Hello World" ); +label.SetAnchorPoint( AnchorPoint::TOP_LEFT ); +label.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +label.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); +label.SetBackgroundColor( Color::BLUE ); +parent.AddChild( label, TableView::CellPosition( 0, 0 ) ); +parent.SetFitHeight( 0 ); + +label = TextLabel::New( "A Quick Brown Fox Jumps Over The Lazy Dog" ); +label.SetAnchorPoint( AnchorPoint::TOP_LEFT ); +label.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +label.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); +label.SetBackgroundColor( Color::GREEN ); +label.SetProperty( TextLabel::Property::MULTI_LINE, true ); +parent.AddChild( label, TableView::CellPosition( 1, 0 ) ); +parent.SetFitHeight( 1 ); + +label = TextLabel::New( "لإعادة ترتيب الشاشات، يجب تغيير نوع العرض إلى شبكة قابلة للتخصيص." ); +label.SetAnchorPoint( AnchorPoint::TOP_LEFT ); +label.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); +label.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); +label.SetBackgroundColor( Color::BLUE ); +label.SetProperty( TextLabel::Property::MULTI_LINE, true ); +parent.AddChild( label, TableView::CellPosition( 2, 0 ) ); +parent.SetFitHeight( 2 ); +\endcode + + + + + +
+ \image html HelloWorld-HeightForWidth.png +
+ +Note that the "Hello World" text label (above) has been given the full width, not the natural width. + +\subsection textLabelDecorations TextLabel Decorations + +

Color

+ +To change the color of the text, the recommended way is to use the TEXT_COLOR property.\n +Note that unlike the Actor::COLOR property, this will not affect child Actors added to the TextLabel.\n + +\code +label.SetProperty( TextLabel::Property::TEXT, "Red Text" ); +label.SetProperty( TextLabel::Property::TEXT_COLOR, Color::RED ); +\endcode + + + + + +
+ \image html RedText.png +
+ +

Drop Shadow

+ +To add a drop-shadow to the text, simply set the SHADOW_OFFSET property with non-zero values.\n +The color can also be selected using the SHADOW_COLOR property.\n + +\code +stage.SetBackgroundColor( Color::BLUE ); + +label1.SetProperty( TextLabel::Property::TEXT, "Plain Text" ); + +label2.SetProperty( TextLabel::Property::TEXT, "Text with Shadow" ); +label2.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 1.0f, 1.0f ) ); +label4.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK ); + +label3.SetProperty( TextLabel::Property::TEXT, "Text with Bigger Shadow" ); +label3.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 2.0f, 2.0f ) ); +label4.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLACK ); + +label4.SetProperty( TextLabel::Property::TEXT, "Text with Color Shadow" ); +label4.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 1.0f, 1.0f ) ); +label4.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::RED ); +\endcode + + + + + + + + + + + + + + +
+ \image html PlainText.png +
+ \image html TextWithShadow.png +
+ \image html TextWithBiggerShadow.png +
+ \image html TextWithColorShadow.png +
+ +

Underline

+ +The text can be underlined by setting UNDERLINE_ENABLED.\n +The color can also be selected using the UNDERLINE_COLOR property.\n + +\code +label1.SetProperty( TextLabel::Property::TEXT, "Text with Underline" ); +label1.SetProperty( TextLabel::Property::UNDERLINE_ENABLED, true ); + +label2.SetProperty( TextLabel::Property::TEXT, "Text with Color Underline" ); +label2.SetProperty( TextLabel::Property::UNDERLINE_ENABLED, true ); +label2.SetProperty( TextLabel::Property::UNDERLINE_COLOR, Color::GREEN ); +\endcode + + + + + + + + +
+ \image html TextWithUnderline.png +
+ \image html TextWithColorUnderline.png +
+ +By default the underline height will be taken from the font metrics, however this can be overridden using the UNDERLINE_HEIGHT property: + +\code +label1.SetProperty( TextLabel::Property::UNDERLINE_HEIGHT, 1.0f ); +\endcode + + + + + +
+ \image html TextWith1pxUnderline.png +
+ +*/ diff --git a/docs/content/programming-guide/text-view.h b/docs/content/programming-guide/text-view.h deleted file mode 100644 index b64b895..0000000 --- a/docs/content/programming-guide/text-view.h +++ /dev/null @@ -1,447 +0,0 @@ -/*! \page text-view Text View - * - * \section overview Overview - * - * The Dali::Toolkit::TextView class is a UI Dali::Toolkit::Control designed to extend the capabilities of the basic Dali::TextActor. - * It provides support for multi-line wrapping, multi-language font detection, text alignment, scrolling and styling. - * - * Dali::Toolkit::TextView also provides text layout information which could be used in other UI Dali::Toolkit::Control classes or other applications. - * - * \section multiline Multi-line wrapping - * - * Different multi-line and exceed policies could be set to layout the given text. - * - * Both multi-line and exceed policies work together. - * Dali::Toolkit::TextView::MultilinePolicy policies define how to wrap a line if it doesn't fit inside the boundary's width - * whereas Dali::Toolkit::TextView::ExceedPolicy policies define what to do if the wrapped text is bigger than the text view's boundary. - * - * i.e. \e SplitByWord could be used as 'multi-line policy' to wrap a line if it's too long. If one of the words is longer than the text-view's width, \e Split could be - * used as 'width exceed policy' to split a word in different lines. If the text is too long and exceeds the text-view's height, \e EllipsizedEnd could be - * used as 'height exceed policy' to render only the text which fits inside the boundaries of the text-view. - * - * @see more \ref examples. - * - * \subsection multiline_policies Multi-line policies - * - *
    - *
  • Split by new line character. - * Text will be wrapped when an end of line \\n or \
    is found. - * - *
  • Split by word. - * Text will be wrapped when an end of line \\n or \
    is found or if the text doesn't fit in the text view width. - * In that case, some words will be moved to a new line. - * - *
  • Split by character. - * Text will be wrapped when an end of line \\n or \
    is found or if the text doesn't fit in the text view width. - * In that case, words which don't fit will be wrapped in two and the remaining text moved to a new line. - *
- * Dali::Toolkit::TextView::SplitByNewLineChar is set by default. - * - * \subsection exceed_policies Exceed policies - * - *
    - *
  • Original size. - * Text will be displayed with its original size. - * - *
  • Fade. - * Text will be faded out. - * - *
  • Split. - * Text will be wrapped and moved to a new line. - * - *
  • Shrink to fit. - * Text will be shrunk to fit in the text view's boundary. - * - *
  • Ellipsize at the end. - * Text will be truncated to fit in the text view's boundary and the ellipsize text will be added. ( '...' by default). - *
- * Dali::Toolkit::TextView::Original is set by default. - * - * @see Dali::Toolkit::TextView::SetMultilinePolicy - * @see Dali::Toolkit::TextView::SetWidthExceedPolicy - * @see Dali::Toolkit::TextView::SetHeightExceedPolicy - * @see Dali::Toolkit::TextView::SetFadeBoundary - * @see Dali::Toolkit::TextView::SetEllipsizeText - * - * @note Multiple combinations are possible but not all of them are already implemented. - * @see \ref exceed_policies_combinations table to check which combinations are implemented - * - * \section scroll Scroll - * - * Text could be scrolled if it exceeds the boundaries of the text-view. - * - * @see Dali::Toolkit::TextView::SetScrollEnabled - * @see Dali::Toolkit::TextView::SetScrollPosition - * - * \section line_height_spacing Line height spacing - * - * The default space between lines could be modified by setting an offset with Dali::Toolkit::TextView::SetLineHeightOffset(). - * - *

Font support and multi-language detection

- * - * Dali::Toolit::TextView uses the font specified in the styled text array to display the given text. - * - * See \link markup-processor Markup Processor \endlink for more details on how to create styling markup strings and styled text arrays. - * - * To support multi-language texts, text-view does the following actions per character: - *
    - *
  • Check if there is a font defined in the styled text array. - *
  • If there isn't, try to use the default platform font. - *
  • Check if the character is supported by the font. - *
  • If isn't, find the most suitable font for the character. - *
- * - * \section text_alignment Text alignment and justification - * - * Dali::Toolkit::TextView provides a method to align the whole text inside the text view's boundary as well as a method to justify each line - * inside the text. - * - * The Dali::Toolkit::Alignment::Type is used to align the whole text in the text view's area. - * A text could be horizontally aligned (left, center, right) and/or vertically aligned (top, center, bottom). - * Dali::Toolkit::Alignment::HorizontalCenter | Dali::Toolkit::Alignment::VerticalCenter is set by default. - * - * The Dali::Toolkit::TextView::LineJustification is used to justify each line inside the text (left, center, right, justified). - * Dali::Toolkit::TextView::Left is set by default. - * - * @see Dali::Toolkit::TextView::SetTextAlignment @see Dali::Toolkit::TextView::SetLineJustification - * - * \section text_styling Text styling - * - * Dali::Toolkit::TextView supports all text styling features provided by Dali::TextActor (font type, color, size, outline, etc). - * - * Different techniques are provided to set or modify the text view's style: - * - *
    - *
  • By setting a Dali::Toolkit::MarkupProcessor::StyledTextArray with the Dali::Toolkit::TextView::SetText(const MarkupProcessor::StyledTextArray& text) method. - *
  • By setting a new Dali::TextStyle to the current text with the Dali::Toolkit::TextView::SetStyleToCurrentText() method. - *
  • By setting an html-ish markup string which contains both text and style with the Dali::Toolkit::TextView::SetText(const std::string& text) method. - @note By default the style markup processor is disabled. @see Dali::Toolkit::TextView::SetMarkupProcessingEnabled to enable the markup processing. - *
- * - * See \link markup-processor Markup Processor \endlink for more details on how to create styling markup strings and styled text arrays. - * - * \section retrieve Retrieve text layout information - * - * The Dali::Toolkit::TextView::GetTextLayoutInfo() retrieves how the input text has been laid out. - * - * For each character it retrieves its size and position, visibility, etc. @see Dali::Toolkit::TextView::CharacterLayoutInfo. - * - * For each laid-out line it retrieves the index of the first character of the line, size, etc. @see Dali::Toolkit::TextView::LineLayoutInfo. - * - * \section appendix Appendix - * \subsection examples Examples - * - * The following examples show how to use TextView. The grey square is an actor which has been added just to show the size of the text-view. - * - * Creation of a text view actor with all its parameters by default. - * \code - * Toolkit::TextView textView = Toolkit::TextView::New( "Hello world!" ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * - * This example wraps the text in lines only when a \\n character is found. The size of the text-view will be automatically resized to fit the whole text inside. - * \code - * const std::string text( "" - * "Lorem ipsum dolor sit amet, consectetur adipisicing elit,\n" - * "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - * "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( "" ); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Original ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::Original ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-01.png - * - * This example wraps the lines by the next word when it exceeds the width of the text-view. The height exceed policy is set to \e Original so it may exceed the height of the text-view. - * - * \code - * const std::string text( "" - * "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " - * "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - * "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( "" ); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 125.f ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Original ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::Original ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-02.png - * - * This example wraps the lines by the next word when it exceeds the width of the text-view. If a word is bigger than the text-view's width, it splits the word. If the text exceeds the height of the text-view, the text is ellipsized. - * - * \code - * const std::string text( "" - * "Loremipsumdolorsitametconsectetur adipisicing elit,\n" - * "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - * "" ); - * const std::string ellipsizeText( "..." ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( "" ); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetEllipsizeText( ellipsizeText ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 125.f ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Split ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::EllipsizeEnd ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-03.png - * - * This example is similar to the one above but the ellipsized text has been set to "" so nothing is shown. - * - * \code - * const std::string text( "" - * "Loremipsumdolorsitametconsecteturadipisicingelit" - * "seddoeiusmodtemporincididuntutlaboreetdoloremagnaaliqua." - * "" ); - * const std::string ellipsizeText( "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New( "" ); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetEllipsizeText( ellipsizeText ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 125.f ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByWord ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Split ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::EllipsizeEnd ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-04.png - * - * This example shows how to fade the text out when it exceeds the boundaries of the text-view. - * - * \code - * const std::string text( "" - * "Lorem ipsum dolor sit amet,\n" - * "consectetur adipisicing elit,\n" - * "sed do eiusmod tempor incididunt\n" - * "ut labore et dolore magna aliqua." - * "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New(); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 100.f ); - * - * Toolkit::TextView::FadeBoundary fadeBoundary( PixelSize( 10 ), PixelSize( 10 ), PixelSize( 10 ), PixelSize( 10 ) ); - * textView.SetFadeBoundary( fadeBoundary ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Fade ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::Fade ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-05.png - * - * This example enables the scroll feature. The screen-shots show three different images of the same text in different scroll positions. - * - * \code - * const std::string text( "" - * "Lorem ipsum dolor sit amet, consectetur adipisicing elit,\n" - * "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." - * "" ); - * - * Toolkit::TextView textView = Toolkit::TextView::New(); - * textView.SetMarkupProcessingEnabled( true ); - * textView.SetText( text ); - * textView.SetParentOrigin( ParentOrigin::CENTER ); - * textView.SetSize( 300.f, 60.f ); - * - * textView.SetMultilinePolicy( Toolkit::TextView::SplitByNewLineChar ); - * textView.SetWidthExceedPolicy( Toolkit::TextView::Original ); - * textView.SetHeightExceedPolicy( Toolkit::TextView::Original ); - * textView.SetLineJustification( Toolkit::TextView::Center ); - * - * textView.SetScrollEnabled( true ); - * - * Stage::GetCurrent().Add( textView ); - * \endcode - * \image html text-view/text-view-example-06.png - * \image html text-view/text-view-example-07.png - * \image html text-view/text-view-example-08.png - * - * See \link markup-processor Markup Processor \endlink \ref example for more styling markup string examples. - * - * \subsection exceed_policies_combinations Implemented exceed policies combinations - * - * The following tables show which exceed policies are implemented for each multi-line policy. Each column has one width exceed policy (Original, Fade, Split, ShrinkToFit and EllipsizeEnd), - * each row has one height exceed policy (Original, Fade, ShrinkToFit and EllipsizeEnd). - * - * @note The Split value is not valid for the height exceed policy. - * - * \htmlonly - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
SplitByNewLineChar
Width exceed policies
OriginalFadeSplitShrinkToFitEllipsizeEnd
Height
exceed
policies
Original
Fade
ShrinkToFit
EllipsizeEnd
- * \endhtmlonly - * - * \n - * - * \htmlonly - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
SplitByWord
Width exceed policies
OriginalFadeSplitShrinkToFitEllipsizeEnd
Height
exceed
policies
Original
Fade
ShrinkToFit
EllipsizeEnd
- * \endhtmlonly - * - * \n - * - * \htmlonly - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
SplitByChar
Width exceed policies
OriginalFadeSplitShrinkToFitEllipsizeEnd
Height
exceed
policies
Original
Fade
ShrinkToFit
EllipsizeEnd
- * \endhtmlonly - */ - diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 6661aeb..07f1c1e 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali-toolkit Summary: The OpenGLES Canvas Core Library Toolkit -Version: 1.0.35 +Version: 1.0.38 Release: 1 Group: System/Libraries License: Apache-2.0 @@ -16,7 +16,6 @@ BuildRequires: pkgconfig(dlog) BuildRequires: boost-devel BuildRequires: pkgconfig(dali) BuildRequires: pkgconfig(dali-core) -BuildRequires: fribidi-devel %description The OpenGLES Canvas Core Library Toolkit - a set of controls that provide diff --git a/plugins/dali-script-v8/file.list b/plugins/dali-script-v8/file.list index d87322f..91b3661 100644 --- a/plugins/dali-script-v8/file.list +++ b/plugins/dali-script-v8/file.list @@ -12,14 +12,11 @@ script_v8_plugin_src_files = \ $(v8_plugin_dir)/actors/actor-wrapper.cpp \ $(v8_plugin_dir)/actors/actor-api.cpp \ $(v8_plugin_dir)/actors/layer-api.cpp \ - $(v8_plugin_dir)/actors/text-actor-api.cpp \ $(v8_plugin_dir)/actors/image-actor-api.cpp \ $(v8_plugin_dir)/actors/camera-actor-api.cpp \ $(v8_plugin_dir)/actors/mesh-actor-api.cpp \ $(v8_plugin_dir)/actors/renderable-actor-api.cpp \ $(v8_plugin_dir)/constants/constants-wrapper.cpp \ - $(v8_plugin_dir)/text/font-api.cpp \ - $(v8_plugin_dir)/text/font-wrapper.cpp \ $(v8_plugin_dir)/animation/animation-api.cpp \ $(v8_plugin_dir)/animation/animation-wrapper.cpp \ $(v8_plugin_dir)/animation/path-api.cpp \ diff --git a/plugins/dali-script-v8/src/actors/actor-api.cpp b/plugins/dali-script-v8/src/actors/actor-api.cpp index 7237547..926c5cd 100644 --- a/plugins/dali-script-v8/src/actors/actor-api.cpp +++ b/plugins/dali-script-v8/src/actors/actor-api.cpp @@ -19,7 +19,7 @@ #include "actor-api.h" // EXTERNAL INCLUDES -#include +#include // INTERNAL INCLUDES #include @@ -42,11 +42,11 @@ Actor GetActor( v8::Isolate* isolate, const v8::FunctionCallbackInfo& } //unanmed namespace -namespace TextViewApi +namespace TextLabelApi { Actor New( const v8::FunctionCallbackInfo< v8::Value >& args ) { - return Dali::Toolkit::TextView::New(); + return Dali::Toolkit::TextLabel::New(); } } @@ -486,7 +486,7 @@ void ActorApi::IsKeyboardFocusable( const v8::FunctionCallbackInfo& a * * @for Actor * @method getActorType - * @return {String} Actor, ImageActor, TextActor, MeshActor, Layer, CameraActor ... + * @return {String} Actor, ImageActor, MeshActor, Layer, CameraActor ... */ void ActorApi::GetActorType( const v8::FunctionCallbackInfo& args ) { diff --git a/plugins/dali-script-v8/src/actors/actor-api.h b/plugins/dali-script-v8/src/actors/actor-api.h index b1dfd4b..509c976 100644 --- a/plugins/dali-script-v8/src/actors/actor-api.h +++ b/plugins/dali-script-v8/src/actors/actor-api.h @@ -28,7 +28,7 @@ namespace Dali namespace V8Plugin { -namespace TextViewApi +namespace TextLabelApi { /** * Temporary TextView constructor diff --git a/plugins/dali-script-v8/src/actors/actor-wrapper.cpp b/plugins/dali-script-v8/src/actors/actor-wrapper.cpp index 7613178..112dfeb 100644 --- a/plugins/dali-script-v8/src/actors/actor-wrapper.cpp +++ b/plugins/dali-script-v8/src/actors/actor-wrapper.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -40,11 +39,10 @@ namespace V8Plugin v8::Persistent ActorWrapper::mActorTemplate; v8::Persistent ActorWrapper::mImageActorTemplate; -v8::Persistent ActorWrapper::mTextActorTemplate; v8::Persistent ActorWrapper::mMeshActorTemplate; v8::Persistent ActorWrapper::mCameraActorTemplate; v8::Persistent ActorWrapper::mLayerActorTemplate; -v8::Persistent ActorWrapper::mTextViewTemplate; +v8::Persistent ActorWrapper::mTextLabelTemplate; namespace { @@ -65,11 +63,10 @@ const ActorTemplate ActorTemplateLookup[]= { { &ActorWrapper::mActorTemplate }, // ACTOR { &ActorWrapper::mImageActorTemplate }, // IMAGE_ACTOR - { &ActorWrapper::mTextActorTemplate }, // TEXT_ACTOR { &ActorWrapper::mMeshActorTemplate }, // MESH_ACTOR { &ActorWrapper::mLayerActorTemplate }, // LAYER_ACTOR { &ActorWrapper::mCameraActorTemplate}, // CAMERA_ACTOR - { &ActorWrapper::mTextViewTemplate } + { &ActorWrapper::mTextLabelTemplate } }; /** @@ -80,10 +77,9 @@ enum ActorApiBitMask ACTOR_API = 1 << 0, RENDERABLE_ACTOR_API = 1 << 1, IMAGE_ACTOR_API = 1 << 2, - TEXT_ACTOR_API = 1 << 3, - MESH_ACTOR_API = 1 << 4, - LAYER_API = 1 << 5, - CAMERA_ACTOR_API = 1 << 6, + MESH_ACTOR_API = 1 << 3, + LAYER_API = 1 << 4, + CAMERA_ACTOR_API = 1 << 5, }; /** @@ -104,11 +100,10 @@ const ActorApiStruct ActorApiLookup[]= { {"Actor", ActorWrapper::ACTOR, ActorApi::New, ACTOR_API }, {"ImageActor", ActorWrapper::IMAGE_ACTOR, ImageActorApi::New, ACTOR_API | RENDERABLE_ACTOR_API | IMAGE_ACTOR_API }, - {"TextActor", ActorWrapper::TEXT_ACTOR, TextActorApi::New, ACTOR_API | RENDERABLE_ACTOR_API | TEXT_ACTOR_API }, {"MeshActor", ActorWrapper::MESH_ACTOR, MeshActorApi::New, ACTOR_API | RENDERABLE_ACTOR_API | MESH_ACTOR_API }, {"Layer", ActorWrapper::LAYER_ACTOR, LayerApi::New, ACTOR_API | LAYER_API }, {"CameraActor",ActorWrapper::CAMERA_ACTOR, CameraActorApi::New, ACTOR_API | CAMERA_ACTOR_API }, - {"TextView", ActorWrapper::TEXT_VIEW, TextViewApi::New, ACTOR_API }, + {"TextLabel", ActorWrapper::TEXT_LABEL, TextLabelApi::New, ACTOR_API }, }; @@ -148,7 +143,7 @@ Actor CreateActor( const v8::FunctionCallbackInfo< v8::Value >& args, else { // run the constructor for this type of actor so it can pull out - // custom parameters, e.g. new TextActor("hello world"); or ImageActor( MyImage ); + // custom parameters, e.g. new ImageActor( MyImage ); actor = (ActorApiLookup[actorType].constructor)( args ); } return actor; @@ -314,40 +309,6 @@ const ActorFunctions ActorFunctionTable[]= // ignore GetFadeInDuration use imageActor.fadeInDuration //{ "GetCurrentImageSize", ImageActorApi::GetCurrentImageSize, IMAGE_ACTOR_API }, - - /************************************** - * Text Actor API (in order of text-actor.h) - **************************************/ - //ignore SetText use textActor.text - { "SetToNaturalSize", TextActorApi::SetToNaturalSize, TEXT_ACTOR_API }, - // ignore GetFont use textActor.font - // ignore SetFont use textActor.font - // ignore SetGradient use textActor.gradientColor - // ignore GetGradient textActor.gradientColor - // ignore SetGradientStartPoint use textActor.gradientStartPoint - // ignore GetGradientStartPoint textActor.gradientStartPoint - // ignore SetGradientEndPoint use textActor.gradientEndPoint - // ignore GetGradientEndPoint textActor.gradientEndPoint - // @todo? SetTextStyle ( can use individual properties as a work around ) - // @todo? GetTextStyle ( can use individual properties as a work around ) - // ignore SetTextColor use textActor.textColor - // ignore GetTextColor use textActor.textColor - // ignore SetSmoothEdge use textActor.smoothEdge - // ignore SetOutline use textActor.outLineEnable, outlineColor, thicknessWidth - // ignore SetGlow use textActor.glowEnable, glowColor, glowIntensity - // ignore SetShadow use textActor.shadowEnable, shadowColor, shadowOffset, shadowSize - // ignore SetItalics use textActor.italicsAngle ? - // ignore GetItalics @todo add italics flag? or just stick with angle - // ignore GetItalicsAngle use textActor.italicsAngle - // ignore SetUnderline use textActor.underline - // ignore GetUnderline use textActor.underline - // ignore SetWeight use textActor.weight - // ignore GetWeight use textActor.weight - // ignore SetFontDetectionAutomatic use textActor.fontDetectionAutomatic - // ignore IsFontDetectionAutomatic use textActor.fontDetectionAutomatic - // ignore GetLoadingState text is loaded synchronously - // ignore TextAvailableSignal text is loaded synchronously - /************************************** * Mesh Actor API (in order of mesh-actor.h) **************************************/ @@ -489,7 +450,7 @@ void ActorWrapper::NewActor( const v8::FunctionCallbackInfo< v8::Value >& args) return; } - // find out the callee function name...e.g. TextActor, ImageActor, MeshActor + // find out the callee function name...e.g. ImageActor, MeshActor v8::Local callee = args.Callee(); v8::Local v8String = callee->GetName(); std::string typeName = V8Utils::v8StringToStdString( v8String ); diff --git a/plugins/dali-script-v8/src/actors/actor-wrapper.h b/plugins/dali-script-v8/src/actors/actor-wrapper.h index 76eee47..06b2e06 100644 --- a/plugins/dali-script-v8/src/actors/actor-wrapper.h +++ b/plugins/dali-script-v8/src/actors/actor-wrapper.h @@ -48,11 +48,10 @@ public: UNKNOWN_ACTOR = -1, ACTOR = 0, IMAGE_ACTOR =1, - TEXT_ACTOR =2, - MESH_ACTOR =3, - LAYER_ACTOR =4, - CAMERA_ACTOR =5, - TEXT_VIEW =6 + MESH_ACTOR =2, + LAYER_ACTOR =3, + CAMERA_ACTOR =4, + TEXT_LABEL =5 }; /** @@ -90,11 +89,10 @@ public: // The Actor ObjectTemplates. static v8::Persistent mActorTemplate; static v8::Persistent mImageActorTemplate; - static v8::Persistent mTextActorTemplate; static v8::Persistent mMeshActorTemplate; static v8::Persistent mCameraActorTemplate; static v8::Persistent mLayerActorTemplate; - static v8::Persistent mTextViewTemplate; + static v8::Persistent mTextLabelTemplate; /** * @return the wrapped actor diff --git a/plugins/dali-script-v8/src/actors/text-actor-api.cpp b/plugins/dali-script-v8/src/actors/text-actor-api.cpp deleted file mode 100644 index 483b345..0000000 --- a/plugins/dali-script-v8/src/actors/text-actor-api.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include "text-actor-api.h" - -// EXTERNAL INCLUDES -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include - - -namespace Dali -{ - -namespace V8Plugin -{ - -namespace //unnamed name space -{ - -struct TextActorParametersInternal -{ - TextActorParametersInternal() - : fontDetection( true ) - { - } - bool fontDetection; - Font font; -}; - - -TextActor GetTextActor( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - HandleWrapper* handleWrapper = HandleWrapper::Unwrap( isolate, args.This() ); - return TextActor::DownCast( handleWrapper->mHandle ); -} - - -void GetTextOptions( v8::Isolate* isolate, - v8::Local options, - TextActorParametersInternal& textParams ) -{ - // fontDetection: true / false ( default true) - // font: dali font object - v8::HandleScope handleScope( isolate ); - - if( options->IsObject() ) - { - v8::Local obj = options->ToObject(); - - v8::Local fontDetect = obj->Get( v8::String::NewFromUtf8( isolate, "fontDetection" ) ); - if( fontDetect->IsBoolean() ) - { - - textParams.fontDetection = fontDetect->ToBoolean()->Value(); - } - - v8::Local fontValue = obj->Get( v8::String::NewFromUtf8( isolate, "font" ) ); - if( fontValue->IsObject() ) - { - textParams.font = FontApi::GetFont( isolate, fontValue ); - } - - } -} - -} - -/** - * @constructor - * @for TextActor - * @method TextActor - * @param {String} text - * @param {Object} [textOptions] data - * Options text options struct - * @param {Boolean} [textOptions.fontDetection] - * if true the fontDetection is used to make sure the text is displayed. - * E.g. if the current font used by the text-actor does not support certain characters - * it will find a new font that does. Default = true. - * @param {Object} [textOptions.font] - * Dali font object - * @return {Object} TextActor - */ -Actor TextActorApi::New( const v8::FunctionCallbackInfo& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - // - // TextActor( text, options (optional) ) - // - // options = - // { - // font: font - // fontDetection: true / false ( default true) - // } - - // get the text (if passed in) - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - - TextActorParametersInternal params; - TextActor actor; - - GetTextOptions( isolate, args[1], params ); - - TextStyle style; - - if( params.font ) - { - style.SetFontName( params.font.GetName() ); - style.SetFontStyle( params.font.GetStyle() ); - style.SetFontPointSize( PointSize(params.font.GetPointSize())); - - } - TextActorParameters textActorParameters( style, params.fontDetection? TextActorParameters::FONT_DETECTION_OFF:TextActorParameters::FONT_DETECTION_ON ); - - actor = TextActor::New( text, textActorParameters ); - - return actor; - -} - -/** - * Set text to the natural size of the text string. - * - * After this method the text actor always uses the natural size of the text - * when SetText is called unless SetSize is called to override the size. - * - * @for TextActor - * @method setToNaturalSize - */ -void TextActorApi::SetToNaturalSize( const v8::FunctionCallbackInfo& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - TextActor textActor = GetTextActor( isolate, args ); - textActor.SetToNaturalSize(); -} - -} // namespace V8Plugin - -} // namespace Dali diff --git a/plugins/dali-script-v8/src/animation/animation-api.cpp b/plugins/dali-script-v8/src/animation/animation-api.cpp index 3fba14a..1a11440 100644 --- a/plugins/dali-script-v8/src/animation/animation-api.cpp +++ b/plugins/dali-script-v8/src/animation/animation-api.cpp @@ -19,12 +19,15 @@ #include "animation-api.h" #include "path-wrapper.h" +// EXTERNAL INCLUDES +#include // for strcmp +#include + + // INTERNAL INCLUDES #include -#include #include #include -#include namespace Dali { @@ -43,7 +46,6 @@ struct AlphaFuncStruct }; /** * Contains a list of alpha functions that can be used. - * We use a stl map as lookup to map a string name to the function */ const AlphaFuncStruct AlphaFunctionTable[]= { diff --git a/plugins/dali-script-v8/src/constants/constants-wrapper.cpp b/plugins/dali-script-v8/src/constants/constants-wrapper.cpp index 938e485..9815aa7 100644 --- a/plugins/dali-script-v8/src/constants/constants-wrapper.cpp +++ b/plugins/dali-script-v8/src/constants/constants-wrapper.cpp @@ -201,10 +201,6 @@ const IntegerPair EnumTable[] = { "CULL_BACK_FACE", CullBack }, { "CULL_FRONT_AND_BACK_FACE", CullFrontAndBack }, - { "USE_OWN_SIZE", USE_OWN_SIZE }, - { "SIZE_RELATIVE_TO_PARENT", SIZE_RELATIVE_TO_PARENT }, - { "SIZE_FIXED_OFFSET_FROM_PARENT", SIZE_FIXED_OFFSET_FROM_PARENT }, - { "CAMERA_FREE_LOOK" , Camera::FREE_LOOK }, { "CAMERA_LOOK_AT_TARGET" , Camera::LOOK_AT_TARGET }, { "CAMERA_PERSPECTIVE_PROJECTION" , Camera::PERSPECTIVE_PROJECTION }, diff --git a/plugins/dali-script-v8/src/dali-wrapper.cpp b/plugins/dali-script-v8/src/dali-wrapper.cpp index 5bce721..f674551 100644 --- a/plugins/dali-script-v8/src/dali-wrapper.cpp +++ b/plugins/dali-script-v8/src/dali-wrapper.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -60,7 +59,6 @@ const ApiFunction ConstructorFunctionTable[]= { { "Rotation", PropertyValueWrapper::NewRotation}, { "Matrix", PropertyValueWrapper::NewMatrix}, - { "Font", FontWrapper::NewFont }, { "Path", PathWrapper::NewPath }, { "PathConstraint", PathConstraintWrapper::NewPathConstraint }, { "Actor", ActorWrapper::NewActor }, @@ -222,10 +220,6 @@ void DaliWrapper::Initialize() v8::Local stageObject = StageWrapper::WrapStage( mIsolate, Stage::GetCurrent() ); daliObject->Set( v8::String::NewFromUtf8( mIsolate, "stage") , stageObject ); - // fontObject provides static font functionality like GetFontList... - v8::Local fontObject = FontWrapper::GetStaticFontObject( mIsolate ); - daliObject->Set( v8::String::NewFromUtf8( mIsolate, "font") , fontObject ); - // keyboard focus manager is a singleton v8::Local keyboardObject = KeyboardFocusManagerWrapper::WrapKeyboardFocusManager( mIsolate,Toolkit::KeyboardFocusManager::Get() ); daliObject->Set( v8::String::NewFromUtf8( mIsolate, "keyboardFocusManager") , keyboardObject ); diff --git a/plugins/dali-script-v8/src/object/property-value-wrapper.cpp b/plugins/dali-script-v8/src/object/property-value-wrapper.cpp index 5dccbee..61159e6 100644 --- a/plugins/dali-script-v8/src/object/property-value-wrapper.cpp +++ b/plugins/dali-script-v8/src/object/property-value-wrapper.cpp @@ -224,14 +224,14 @@ v8::Handle< v8::Value > GetV8ValueFrom( v8::Isolate* isolate, else if(field == "axis") { Dali::Vector3 axis; - float angle; + Radian angle; value.Get().ToAxisAngle(axis, angle); ret = PropertyValueWrapper::WrapDaliProperty( isolate , Dali::Property::Value( axis ) ); } else if(field == "angle") { Dali::Vector3 axis; - float angle; + Radian angle; value.Get().ToAxisAngle(axis, angle); ret = PropertyValueWrapper::WrapDaliProperty( isolate , Dali::Property::Value( angle ) ); } @@ -384,24 +384,24 @@ void SetFromV8Value(v8::Isolate* isolate, { Dali::Vector4 v4 = value.Get().EulerAngles(); v4.z = asFloat; - value = Dali::Quaternion(v4.x, v4.y, v4.z); + value = Dali::Quaternion( Radian(Degree(v4.x)), Radian(Degree(v4.y)), Radian(Degree(v4.z)) ); } else if(field == "pitch") { Dali::Vector4 v4 = value.Get().EulerAngles(); v4.x = asFloat; - value = Dali::Quaternion(v4.x, v4.y, v4.z); + value = Dali::Quaternion( Radian(Degree(v4.x)), Radian(Degree(v4.y)), Radian(Degree(v4.z)) ); } else if(field == "yaw") { Dali::Vector4 v4 = value.Get().EulerAngles(); v4.y = asFloat; - value = Dali::Quaternion(v4.x, v4.y, v4.z); + value = Dali::Quaternion( Radian(Degree(v4.x)), Radian(Degree(v4.y)), Radian(Degree(v4.z)) ); } else if(field == "axis") { Dali::Vector3 axis; - float angle; + Radian angle; value.Get().ToAxisAngle(axis, angle); if( v8Value->IsObject() ) @@ -426,9 +426,9 @@ void SetFromV8Value(v8::Isolate* isolate, else if(field == "angle") { Dali::Vector3 axis; - float angle; - value.Get().ToAxisAngle(axis, angle); - value = Dali::Quaternion(asFloat, axis); + Radian angle; + value.Get().ToAxisAngle( axis, angle ); + value = Dali::Quaternion( Radian( Degree( asFloat ) ), axis ); } else { @@ -734,9 +734,9 @@ Dali::Property::Value PropertyValueWrapper::ExtractPropertyValue( v8::Isolate* i } else if(array.GetType() == Dali::Property::VECTOR3) { - // v3 treated as euler + // v3 treated as euler in degrees Dali::Vector3 v = array.Get(); - daliPropertyValue = Dali::Quaternion(v[0], v[1], v[2]); + daliPropertyValue = Dali::Quaternion( Radian(Degree(v[0])), Radian(Degree(v[1])), Radian(Degree(v[2])) ); } break; } @@ -785,24 +785,23 @@ void PropertyValueWrapper::NewRotation( const v8::FunctionCallbackInfo< v8::Valu bool foundAllArguments(false); V8Utils::ReadFloatArguments( foundAllArguments, v, 4, args, 0.f ); - int len = args.Length(); + int length = args.Length(); // if length = 4 create AngleAxis, else create Quaternion - if(len > 3) + if( length > 3 ) { - Dali::AngleAxis axis( Dali::Degree(v[0] ), Dali::Vector3(v[1], v[2], v[3]) ); - object = WrapDaliProperty( isolate , Dali::Property::Value( axis ) ); + Dali::AngleAxis axis( Degree( v[0] ), Vector3(v[1], v[2], v[3]) ); + object = WrapDaliProperty( isolate, Dali::Property::Value( axis ) ); } - else if(len > 2) + else if( length > 2 ) { - Dali::Quaternion quaternion( v[0], v[1], v[2] ); - object = WrapDaliProperty( isolate , Dali::Property::Value( quaternion ) ); + object = WrapDaliProperty( isolate, Dali::Property::Value( Dali::Quaternion( Radian( Degree(v[0]) ), Radian( Degree(v[1]) ), Radian( Degree(v[2]) ) ) ) ); } else { - Dali::Quaternion quaternion( Dali::Quaternion(0.f, Dali::Vector4::YAXIS)); - object = WrapDaliProperty( isolate , Dali::Property::Value( quaternion ) ); + Dali::Quaternion quaternion( Dali::Quaternion( Dali::ANGLE_0, Dali::Vector3::YAXIS)); + object = WrapDaliProperty( isolate, Dali::Property::Value( quaternion ) ); } args.GetReturnValue().Set( object ); diff --git a/plugins/dali-script-v8/src/shader-effects/shader-effect-api.cpp b/plugins/dali-script-v8/src/shader-effects/shader-effect-api.cpp index d7bd2a5..4d65e64 100644 --- a/plugins/dali-script-v8/src/shader-effects/shader-effect-api.cpp +++ b/plugins/dali-script-v8/src/shader-effects/shader-effect-api.cpp @@ -47,7 +47,6 @@ struct GeometryTypePair const GeometryTypePair GeometryTypeTable[]= { {"image", GEOMETRY_TYPE_IMAGE }, - {"text", GEOMETRY_TYPE_TEXT }, {"mesh", GEOMETRY_TYPE_UNTEXTURED_MESH }, {"textured-mesh", GEOMETRY_TYPE_TEXTURED_MESH }, }; diff --git a/plugins/dali-script-v8/src/signals/signal-manager.cpp b/plugins/dali-script-v8/src/signals/signal-manager.cpp index 55d4a0e..d8359e2 100644 --- a/plugins/dali-script-v8/src/signals/signal-manager.cpp +++ b/plugins/dali-script-v8/src/signals/signal-manager.cpp @@ -18,6 +18,19 @@ // CLASS HEADER #include "signal-manager.h" +// EXTERNAL INCLUDES +#include // for strcmp +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + // INTERNAL INCLUDES #include #include @@ -29,16 +42,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/plugins/dali-script-v8/src/text/font-api.cpp b/plugins/dali-script-v8/src/text/font-api.cpp deleted file mode 100644 index 385f58d..0000000 --- a/plugins/dali-script-v8/src/text/font-api.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include "font-api.h" - -// INTERNAL INCLUDES -#include -#include -#include - -namespace Dali -{ - -namespace V8Plugin -{ - -namespace // un named namespace -{ - - - - -} //un named namespace - -/*************************************** - * IMAGE FUNCTIONS - * - ****************************************/ -Font FontApi::GetFont( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::HandleScope handleScope( isolate ); - - v8::Local object = args.This(); - v8::Local field = v8::Local::Cast( object->GetInternalField(0) ); - void* ptr = field->Value(); - - FontWrapper* wrapper = static_cast< FontWrapper *>(ptr); - return wrapper->GetFont(); -} -Font FontApi::GetFont( v8::Isolate* isolate, v8::Local& value ) -{ - v8::HandleScope handleScope( isolate ); - v8::Local object = value->ToObject(); - v8::Local field = v8::Local::Cast( object->GetInternalField(0) ); - void* ptr = field->Value(); - - FontWrapper* wrapper = static_cast< FontWrapper *>(ptr); - return wrapper->GetFont(); -} - -struct FontParams -{ - typedef enum - { - NO_SIZE_SET, - USE_POINT_SIZE, - USE_PIXEL_SIZE, - USE_CAP_SIZE, - } SizeType; - - - FontParams() - :pointSize( 0 ), - pixelSize( 0 ), - capsSize( 0 ), - sizeType( FontParams::NO_SIZE_SET ) - { - } - - std::string family; - std::string style; - PointSize pointSize; - PixelSize pixelSize; - CapsHeight capsSize; - SizeType sizeType; - - -}; - - -void ReadFontParameters( v8::Isolate* isolate, - v8::Local options, - FontParams& fontParams ) -{ - // foont options is an optional parameter passed in which holds - // optional settings - // var fontOptions = { - // family: "arial", - // style: "bold", - // // one of the following - // pixelSize: xx - // pointSize: xx - // capsHeight:xx // height of a capital letter above the baseline for a particular typeface. - // - // }; - v8::HandleScope handleScope( isolate ); - if( !options->IsObject() ) - { - DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 0 ( font parameters)" ); - return; - } - v8::Local obj = options->ToObject(); - - v8::Local familyValue = obj->Get( v8::String::NewFromUtf8( isolate, "family" ) ); - if( familyValue->IsString() ) - { - fontParams.family = V8Utils::v8StringToStdString( familyValue ); - } - - v8::Local styleValue = obj->Get( v8::String::NewFromUtf8( isolate, "style" ) ); - if( styleValue->IsString() ) - { - fontParams.style = V8Utils::v8StringToStdString( styleValue ); - } - - v8::Local pixelSize = obj->Get( v8::String::NewFromUtf8( isolate, "pixelSize" ) ); - v8::Local pointSize = obj->Get( v8::String::NewFromUtf8( isolate, "pointSize" ) ); - v8::Local capsHeight = obj->Get( v8::String::NewFromUtf8( isolate, "capsHeight" ) ); - - if( pixelSize->IsUint32() ) - { - fontParams.pixelSize.value = pixelSize->ToUint32()->Value(); - fontParams.sizeType = FontParams::USE_PIXEL_SIZE; - } - else if( pointSize->IsUint32() ) - { - fontParams.pointSize.value = pointSize->ToUint32()->Value(); - fontParams.sizeType = FontParams::USE_POINT_SIZE; - } - else if( capsHeight->IsUint32() ) - { - fontParams.capsSize.value = capsHeight->ToUint32()->Value(); - fontParams.sizeType = FontParams::USE_CAP_SIZE; - } - -} - -Font FontApi::New( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - // if no parameters just create a default font - if ( args.Length() == 0) - { - return Font::New(); - } - FontParams params; - - ReadFontParameters( isolate, args[0], params ); - - FontParameters fontParams; - // construct a dali font parameters object - switch( params.sizeType) - { - case FontParams::USE_PIXEL_SIZE: - { - fontParams = FontParameters( params.family, params.style, params.pixelSize ); - break; - } - case FontParams::USE_POINT_SIZE: - { - fontParams = FontParameters( params.family, params.style, params.pointSize ); - break; - } - case FontParams::USE_CAP_SIZE: - { - fontParams = FontParameters( params.family, params.style, params.capsSize ); - break; - } - default: - { - fontParams = FontParameters( params.family, params.style, PointSize(0.f)); - break; - } - } - return Font::New( fontParams ); - -} - - -void FontApi::GetFamilyForText( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - - bool foundString; - std::string text = V8Utils::GetStringParameter( PARAMETER_0, foundString, isolate, args ); - if( !foundString ) - { - DALI_SCRIPT_EXCEPTION( isolate, "bad parameter 0 ( text )" ); - return; - } - std::string family = Font::GetFamilyForText( text ); - - args.GetReturnValue().Set( v8::String::NewFromUtf8( isolate, family.c_str()) ); - -} -void FontApi::GetLineHeightFromCapsHeight( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - FontParams params; - ReadFontParameters( isolate, args[0], params ); - if( params.sizeType != FontParams::USE_CAP_SIZE ) - { - DALI_SCRIPT_EXCEPTION( isolate, "caps height not found" ); - return; - } - - PixelSize size = Font::GetLineHeightFromCapsHeight( params.family, params.style, params.capsSize); - args.GetReturnValue().Set( v8::Integer::New( isolate, size.value ) ); -} - -void FontApi::GetInstalledFonts( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - bool found( false ); - std::vector fontList; - - std::string mode = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - - if( mode == "LIST_APPLICATION_FONTS" ) - { - fontList = Font::GetInstalledFonts( Font::LIST_APPLICATION_FONTS ); - } - else if( mode == "LIST_ALL_FONTS") - { - fontList = Font::GetInstalledFonts( Font::LIST_ALL_FONTS ); - } - else // default - { - fontList = Font::GetInstalledFonts( Font::LIST_SYSTEM_FONTS ); - } - // create a javascript array - v8::Local array = v8::Array::New(isolate, fontList.size() ); - for( std::size_t i = 0; i < fontList.size(); i++) - { - const char* fontName = fontList[i].c_str(); - array->Set(v8::Integer::New(args.GetIsolate(), i), v8::String::NewFromUtf8( isolate,fontName)); - } - - args.GetReturnValue().Set( array ); -} - -void FontApi::MeasureTextWidth( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - //float MeasureTextWidth(const std::string& text, float textHeightPx) const; - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "text not found" ); - return; - } - int height = V8Utils::GetIntegerParameter( PARAMETER_1, found, isolate, args, 0 ); - if( !found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "missing text height" ); - return; - } - float width = font.MeasureTextWidth( text, height ); - - args.GetReturnValue().Set( v8::Integer::New( isolate, width ) ); - -} -void FontApi::MeasureTextHeight( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - //float MeasureTextHeight(const std::string& text, float textHeightPx) const; - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "text not found" ); - return; - } - int width= V8Utils::GetIntegerParameter( PARAMETER_1, found, isolate, args, 0 ); - if( !found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "missing text height" ); - return; - } - float height = font.MeasureTextHeight( text, width ); - - args.GetReturnValue().Set( v8::Integer::New( isolate, height ) ); -} -void FontApi::MeasureText( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "text not found" ); - return; - } - - Vector3 vec3 = font.MeasureText( text ); - Dali::Property::Value value( vec3 ); - v8::Local object = PropertyValueWrapper::WrapDaliProperty( isolate, value); - args.GetReturnValue().Set( object ); - -} -void FontApi::AllGlyphsSupported( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "text not found" ); - return; - } - - bool supported = font.AllGlyphsSupported( text ); - args.GetReturnValue().Set( v8::Boolean::New( isolate, supported) ); - -} - -// This one function is use to create a property map, instead of the many individual property -// getters used by the C++ Dali API. -// propertyMap -// { -// name: -// style: -// pointSize: -// pixelSize: -// lineHeight: -// ascender: -// underlineThickness: -// underlinePosition: -// isDefaultSystemFont: -// isDefaultSystemSize: -// } - -void FontApi::GetProperties( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - v8::Local keyObject = v8::Object::New( isolate ); - - keyObject->Set( v8::String::NewFromUtf8( isolate, "family" ), v8::String::NewFromUtf8( isolate, font.GetName().c_str() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "style" ), v8::String::NewFromUtf8( isolate, font.GetStyle().c_str() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "pointSize" ), v8::Integer::New( isolate, font.GetPointSize() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "pixelSize" ), v8::Integer::New( isolate, font.GetPixelSize() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "lineHeight" ), v8::Integer::New( isolate, font.GetLineHeight() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "ascender" ), v8::Integer::New( isolate, font.GetAscender() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "underlineThickness" ), v8::Integer::New( isolate, font.GetUnderlineThickness() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "underlinePosition" ), v8::Integer::New( isolate, font.GetUnderlinePosition()) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "isDefaultSystemFont" ), v8::Boolean::New( isolate, font.IsDefaultSystemFont() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "isDefaultSystemSize" ), v8::Boolean::New( isolate, font.IsDefaultSystemSize() ) ); - - args.GetReturnValue().Set( keyObject ); - -} - -void FontApi::GetMetrics( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - Font font = GetFont( isolate, args ); - - bool found( false ); - std::string text = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args ); - - if(! found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "character not found" ); - return; - } - - Text textObject( text ); - - Font::Metrics metric = font.GetMetrics( textObject[0] ); - - v8::Local keyObject = v8::Object::New( isolate ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "advance" ), v8::Integer::New( isolate, metric.GetAdvance() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "bearing" ), v8::Integer::New( isolate, metric.GetBearing() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "width" ), v8::Integer::New( isolate, metric.GetWidth() ) ); - keyObject->Set( v8::String::NewFromUtf8( isolate, "height" ), v8::Integer::New( isolate, metric.GetHeight() ) ); - - args.GetReturnValue().Set( keyObject ); - -} - - -void FontApi::PointsToPixels( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - bool found(false); - int pointSize= V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 ); - if( !found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "missing pointSize" ); - return; - } - args.GetReturnValue().Set( v8::Integer::New( isolate, Font::PointsToPixels(pointSize) ) ); - -} -void FontApi::PixelsToPoints( const v8::FunctionCallbackInfo< v8::Value >& args ) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate ); - - bool found(false); - int pixelSize= V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 ); - if( !found ) - { - DALI_SCRIPT_EXCEPTION( isolate, "missing pixelSize" ); - return; - } - args.GetReturnValue().Set( v8::Integer::New( isolate, Font::PixelsToPoints(pixelSize) ) ); -} - - - -} // namespace V8Plugin - -} // namespace Dali diff --git a/plugins/dali-script-v8/src/text/font-api.h b/plugins/dali-script-v8/src/text/font-api.h deleted file mode 100644 index 129c240..0000000 --- a/plugins/dali-script-v8/src/text/font-api.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef __DALI_V8PLUGIN_FONT_API_H__ -#define __DALI_V8PLUGIN_FONT_API_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 -#include - - -namespace Dali -{ - -namespace V8Plugin -{ - -namespace FontApi -{ - Font GetFont( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args ); - Font GetFont( v8::Isolate* isolate, v8::Local& value ); - - Font GetFontFromParams( int paramIndex, - bool& found, - v8::Isolate* isolate, - const v8::FunctionCallbackInfo< v8::Value >& args ); - - /** - * Constructor - */ - Font New( const v8::FunctionCallbackInfo< v8::Value >& args ); - - /** - * Font API see image.h for a description - */ - void GetFamilyForText( const v8::FunctionCallbackInfo< v8::Value >& args ); - void GetLineHeightFromCapsHeight( const v8::FunctionCallbackInfo< v8::Value >& args ); - void GetInstalledFonts( const v8::FunctionCallbackInfo< v8::Value >& args ); - void MeasureTextWidth( const v8::FunctionCallbackInfo< v8::Value >& args ); - void MeasureTextHeight( const v8::FunctionCallbackInfo< v8::Value >& args ); - void MeasureText( const v8::FunctionCallbackInfo< v8::Value >& args ); - void AllGlyphsSupported( const v8::FunctionCallbackInfo< v8::Value >& args ); - void GetProperties( const v8::FunctionCallbackInfo< v8::Value >& args ); - void GetMetrics( const v8::FunctionCallbackInfo< v8::Value >& args ); - void PointsToPixels( const v8::FunctionCallbackInfo< v8::Value >& args ); - void PixelsToPoints( const v8::FunctionCallbackInfo< v8::Value >& args ); - -}; // namespace FontApi - -} // namespace V8Plugin - -} // namespace Dali - -#endif // header __DALI_V8PLUGIN_FONT_API_H__ diff --git a/plugins/dali-script-v8/src/text/font-wrapper.cpp b/plugins/dali-script-v8/src/text/font-wrapper.cpp deleted file mode 100644 index 9760f51..0000000 --- a/plugins/dali-script-v8/src/text/font-wrapper.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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. - * - */ - -// CLASS HEADER -#include "font-wrapper.h" - -// INTERNAL INCLUDES -#include -#include -#include -#include -#include - -namespace Dali -{ - -namespace V8Plugin -{ - -namespace // un-named name space -{ - -/** - * Contains a list of all functions that can be called on the font object - */ -const ApiFunction FontFunctionTable[]= -{ - /************************************** - * Font API (in order of font.h) - **************************************/ - { "MeasureTextWidth", FontApi::MeasureTextWidth }, - { "MeasureTextHeight", FontApi::MeasureTextHeight }, - { "MeasureText", FontApi::MeasureText }, - { "AllGlyphsSupported", FontApi::AllGlyphsSupported }, - { "GetProperties", FontApi::GetProperties }, // replace all getters - { "GetMetrics", FontApi::GetMetrics }, -}; - -const unsigned int FontFunctionTableCount = sizeof(FontFunctionTable)/sizeof(FontFunctionTable[0]); - -/** - * Contains a list of all functions that can be called - */ -const ApiFunction StaticFontFunctionTable[]= -{ - /************************************** - * Static font functions, called without a font object - **************************************/ - { "GetFamilyForText", FontApi::GetFamilyForText }, - { "GetLineHeightFromCapsHeight", FontApi::GetLineHeightFromCapsHeight }, - { "GetInstalledFonts", FontApi::GetInstalledFonts }, - { "PointsToPixels", FontApi::PointsToPixels }, - { "PixelsToPoints", FontApi::PixelsToPoints }, -}; - -const unsigned int StaticFontFunctionTableCount = sizeof(StaticFontFunctionTable)/sizeof(FontFunctionTable[0]); - -} //un-named space - - -FontWrapper::FontWrapper( const Dali::Font& font, GarbageCollectorInterface& gc ) -: BaseWrappedObject( BaseWrappedObject::FONT , gc ) -{ - mFont = font; -} - -v8::Handle FontWrapper::WrapFont(v8::Isolate* isolate, const Dali::Font& font ) -{ - v8::EscapableHandleScope handleScope( isolate ); - v8::Local objectTemplate; - - objectTemplate = MakeFontTemplate( isolate ); - - // create an instance of the template - v8::Local localObject = objectTemplate->NewInstance(); - - // create the Font wrapper - FontWrapper* pointer = new FontWrapper( font, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() ); - - // assign the JavaScript object to the wrapper. - pointer->SetJavascriptObject( isolate, localObject ); - - printf("Created Font!\n"); - return handleScope.Escape( localObject ); -} - - -v8::Handle FontWrapper::MakeFontTemplate( v8::Isolate* isolate ) -{ - v8::EscapableHandleScope handleScope( isolate ); - - v8::Local objTemplate = v8::ObjectTemplate::New(); - - objTemplate->SetInternalFieldCount( BaseWrappedObject::FIELD_COUNT ); - - // add our function properties - ObjectTemplateHelper::InstallFunctions( isolate, objTemplate, FontFunctionTable, FontFunctionTableCount ); - - return handleScope.Escape( objTemplate ); -} - -void FontWrapper::NewFont( const v8::FunctionCallbackInfo< v8::Value >& args) -{ - v8::Isolate* isolate = args.GetIsolate(); - v8::HandleScope handleScope( isolate); - - if(!args.IsConstructCall()) - { - DALI_SCRIPT_EXCEPTION( isolate, "Font constructor called without 'new'"); - return; - } - - // attribs can be passed by value - Dali::Font font = FontApi::New( args ); - if( !font ) - { - DALI_SCRIPT_EXCEPTION( isolate, "bad font parameters\n"); - return; - } - - v8::Local localObject = WrapFont( isolate, font ); - args.GetReturnValue().Set( localObject ); -} - -Font FontWrapper::GetFont() -{ - return mFont; -} - -v8::Handle FontWrapper::GetStaticFontObject(v8::Isolate* isolate) -{ - v8::EscapableHandleScope handleScope( isolate ); - - v8::Local objTemplate = v8::ObjectTemplate::New(); - - // add our functions properties - ObjectTemplateHelper::InstallFunctions( isolate, objTemplate, StaticFontFunctionTable, StaticFontFunctionTableCount ); - - v8::Local localObject = objTemplate->NewInstance(); - - return handleScope.Escape( localObject ); - - } - - -} // namespace V8Plugin - -} // namespace Dali diff --git a/plugins/dali-script-v8/src/text/font-wrapper.h b/plugins/dali-script-v8/src/text/font-wrapper.h deleted file mode 100644 index 328416a..0000000 --- a/plugins/dali-script-v8/src/text/font-wrapper.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __DALI_V8PLUGIN_FONT_WRAPPER_H__ -#define __DALI_V8PLUGIN_FONT_WRAPPER_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 -#include - -// INTERNAL INCLUDES -#include - -namespace Dali -{ - -namespace V8Plugin -{ - - -/** - * An Font wrapper. - * Provides access to Font specific functionality and V8 memory handling. - */ -class FontWrapper : public BaseWrappedObject -{ - -public: - - FontWrapper( const Font& font, - GarbageCollectorInterface& gc ); - - virtual ~FontWrapper() - { - }; - - /** - * @brief Creates a new Font wrapped inside a Javascript Object. - * @note: the actor type ie 'FontFont' is expected to be the name of the callee function. - * @param[in] args v8 function call arguments interpreted - */ - static void NewFont( const v8::FunctionCallbackInfo< v8::Value >& args); - - /** - * Wraps a font - */ - static v8::Handle WrapFont(v8::Isolate* isolate, const Dali::Font& ); - - Font GetFont(); - - static v8::Handle GetStaticFontObject(v8::Isolate* isolate); - -private: - - Font mFont; - static v8::Handle MakeFontTemplate( v8::Isolate* isolate ); - -}; - -} // namespace V8Plugin - -} // namespace Dali - -#endif // __DALI_V8PLUGIN_FONT_WRAPPER_H__ diff --git a/plugins/dali-script-v8/src/toolkit/builder/builder-api.cpp b/plugins/dali-script-v8/src/toolkit/builder/builder-api.cpp index 7feb259..3c499a4 100644 --- a/plugins/dali-script-v8/src/toolkit/builder/builder-api.cpp +++ b/plugins/dali-script-v8/src/toolkit/builder/builder-api.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include @@ -293,11 +292,6 @@ void BuilderApi::Create( const v8::FunctionCallbackInfo< v8::Value >& args ) v8::Local image = ImageWrapper::WrapImage(isolate, Image::DownCast(handle) ); args.GetReturnValue().Set( image ); } - if( typeName == "Font ") - { - v8::Local font = FontWrapper::WrapFont(isolate, Font::DownCast(handle) ); - args.GetReturnValue().Set( font ); - } if( typeName == "Shader") { v8::Local shader = ShaderEffectWrapper::WrapShaderEffect(isolate, ShaderEffect::DownCast( handle ));