# List of test case sources (Only these get parsed for test cases)
SET(TC_SOURCES
utc-Dali-PushButton.cpp
+ utc-Dali-Text-CharacterSetConversion.cpp
+ utc-Dali-Text-Segmentation.cpp
+ utc-Dali-Text-MultiLanguage.cpp
)
# Append list of test harness files (Won't get parsed for test cases)
DALI_TEST_CHECK( button.IsSelected() ) ;
DALI_TEST_CHECK( button.GetProperty< bool >( Button::Property::SELECTED ) );
- // Button::PROPERTY_NORMAL_STATE_ACTOR
- {
- button.SetButtonImage( ResourceImage::New( "IMAGE_PATH_1") );
- DALI_TEST_EQUALS( "IMAGE_PATH_1", button.GetProperty( Button::Property::NORMAL_STATE_ACTOR ).GetValue( "image" ).GetValue( "filename" ).Get< std::string >(), TEST_LOCATION );
-
- Property::Map map;
- map[ "type" ] = "ImageActor";
-
- button.SetProperty( Button::Property::NORMAL_STATE_ACTOR, map );
- DALI_TEST_EQUALS( "ImageActor", button.GetProperty( Button::Property::NORMAL_STATE_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
- }
-
- // Button::PROPERTY_SELECTED_STATE_ACTOR
- {
- button.SetSelectedImage( ResourceImage::New( "IMAGE_PATH_2") );
- DALI_TEST_EQUALS( "IMAGE_PATH_2", button.GetProperty( Button::Property::SELECTED_STATE_ACTOR ).GetValue( "image" ).GetValue( "filename" ).Get< std::string >(), TEST_LOCATION );
-
- Property::Map map;
- map[ "type" ] = "Actor";
-
- button.SetProperty( Button::Property::SELECTED_STATE_ACTOR, map );
- DALI_TEST_EQUALS( "Actor", button.GetProperty( Button::Property::SELECTED_STATE_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
- DALI_TEST_CHECK( "ImageActor" != button.GetProperty( Button::Property::SELECTED_STATE_ACTOR ).GetValue( "type" ).Get< std::string >() );
- }
-
- // Button::PROPERTY_DISABLED_STATE_ACTOR
- {
- button.SetDisabledImage( ResourceImage::New( "IMAGE_PATH_3") );
- DALI_TEST_EQUALS( "IMAGE_PATH_3", button.GetProperty( Button::Property::DISABLED_STATE_ACTOR ).GetValue( "image" ).GetValue( "filename" ).Get< std::string >(), TEST_LOCATION );
-
- Property::Map map;
- map[ "type" ] = "Actor";
-
- button.SetProperty( Button::Property::DISABLED_STATE_ACTOR, map );
- DALI_TEST_EQUALS( "Actor", button.GetProperty( Button::Property::DISABLED_STATE_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
- }
-
- // Button::PROPERTY_LABEL_ACTOR
- {
- button.SetLabel( "LABEL_TEXT_CUSTOM" );
- DALI_TEST_EQUALS( "TextLabel", button.GetProperty( Button::Property::LABEL_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
-
- Property::Map map;
- map[ "type" ] = "Actor";
-
- button.SetProperty( Button::Property::LABEL_ACTOR, map );
- DALI_TEST_EQUALS( "Actor", button.GetProperty( Button::Property::LABEL_ACTOR ).GetValue( "type" ).Get< std::string >(), TEST_LOCATION );
- }
END_TEST;
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions for scripts with different number of bytes per character.
+// Latin 1 byte per character, Arabic 2 bytes per character, Devanagari 3 bytes per character and emojis 4 bytes per character.
+//
+// uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length );
+// uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters );
+// uint32_t Utf8ToUtf32( const uint8_t* const utf8, uint32_t length, uint32_t* utf32 );
+// uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, uint8_t* utf8 );
+// void Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, std::string& utf8 );
+//
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct GetNumberOfUtf8CharactersData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< input text.
+ unsigned int numberOfCharacters; ///< The expected number of characters.
+};
+
+bool GetNumberOfUtf8CharactersTest( const GetNumberOfUtf8CharactersData& data )
+{
+ return GetNumberOfUtf8Characters( reinterpret_cast<const uint8_t*>( data.text.c_str() ), data.text.size() ) == data.numberOfCharacters;
+}
+
+//////////////////////////////////////////////////////////
+
+struct GetNumberOfUtf8BytesData
+{
+ std::string description; ///< Description of the test.
+ unsigned int* utf32; ///< input text in utf32.
+ unsigned int numberOfCharacters; ///< The number of characters.
+ unsigned int numberOfBytes; ///< The expected number of bytes in utf8.
+};
+
+bool GetNumberOfUtf8BytesTest( const GetNumberOfUtf8BytesData& data )
+{
+ return GetNumberOfUtf8Bytes( data.utf32, data.numberOfCharacters ) == data.numberOfBytes;
+}
+
+//////////////////////////////////////////////////////////
+
+struct Utf8ToUtf32Data
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< input text.
+ unsigned int* utf32; ///< The expected text (array of bytes with text encoded in utf32).
+};
+
+
+bool Utf8ToUtf32Test( const Utf8ToUtf32Data& data )
+{
+ Vector<uint32_t> utf32;
+ utf32.Resize( data.text.size() );
+
+ const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+ data.text.size(),
+ utf32.Begin() );
+
+ for( unsigned int index = 0u; index < numberOfCharacters; ++index )
+ {
+ if( data.utf32[index] != utf32[index] )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+
+struct Utf32ToUtf8Data
+{
+ std::string description; ///< Description of the test.
+ unsigned int* utf32; ///< The input text (array of bytes with text encoded in utf32).
+ unsigned int numberOfCharacters; ///< The number of characters.
+ std::string text; ///< The expected text.
+};
+
+bool Utf32ToUtf8Test( const Utf32ToUtf8Data& data )
+{
+ std::string text;
+
+ Utf32ToUtf8( data.utf32, data.numberOfCharacters, text );
+
+ return text == data.text;
+}
+
+//////////////////////////////////////////////////////////
+
+int UtcDaliTextCharacterSetConversionGetNumberOfUtf8Characters(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCharacterSetConversionGetNumberOfUtf8Characters");
+
+ const GetNumberOfUtf8CharactersData data[] =
+ {
+ {
+ "Latin script",
+ "Hello World",
+ 11u,
+ },
+ {
+ "Arabic script",
+ "مرحبا بالعالم",
+ 13u,
+ },
+ {
+ "Devanagari script",
+ "हैलो वर्ल्ड",
+ 11u,
+ },
+ {
+ "Emojis",
+ "\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84",
+ 7u,
+ },
+ };
+ const unsigned int numberOfTests = 4u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !GetNumberOfUtf8CharactersTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCharacterSetConversionGetNumberOfUtf8Bytes(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCharacterSetConversionGetNumberOfUtf8Bytes");
+
+ unsigned int utf32_01[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 }; // Hello World
+ unsigned int utf32_02[] = { 0x645, 0x631, 0x62D, 0x628, 0x627, 0x20, 0x628, 0x627, 0x644, 0x639, 0x627, 0x644, 0x645 }; // مرحبا بالعالم
+ unsigned int utf32_03[] = { 0x939, 0x948, 0x932, 0x94B, 0x20, 0x935, 0x930, 0x94D, 0x932, 0x94D, 0x921 }; // हैलो वर्ल्ड
+ unsigned int utf32_04[] = { 0x1F601, 0x20, 0x1F602, 0x20, 0x1F603, 0x20, 0x1F604 }; // Emojis
+
+ const GetNumberOfUtf8BytesData data[] =
+ {
+ {
+ "Latin script",
+ utf32_01,
+ 11u,
+ 11u,
+ },
+ {
+ "Arabic script",
+ utf32_02,
+ 13u,
+ 25u,
+ },
+ {
+ "Devanagari script",
+ utf32_03,
+ 11u,
+ 31u,
+ },
+ {
+ "Emojis",
+ utf32_04,
+ 7u,
+ 19u,
+ },
+ };
+ const unsigned int numberOfTests = 4u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !GetNumberOfUtf8BytesTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCharacterSetConversionUtf8ToUtf32(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCharacterSetConversionGetNumberOfUtf8Bytes");
+
+ unsigned int utf32_01[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 }; // Hello World
+ unsigned int utf32_02[] = { 0x645, 0x631, 0x62D, 0x628, 0x627, 0x20, 0x628, 0x627, 0x644, 0x639, 0x627, 0x644, 0x645 }; // مرحبا بالعالم
+ unsigned int utf32_03[] = { 0x939, 0x948, 0x932, 0x94B, 0x20, 0x935, 0x930, 0x94D, 0x932, 0x94D, 0x921 }; // हैलो वर्ल्ड
+ unsigned int utf32_04[] = { 0x1F601, 0x20, 0x1F602, 0x20, 0x1F603, 0x20, 0x1F604 }; // Emojis
+
+ const Utf8ToUtf32Data data[] =
+ {
+ {
+ "Latin script",
+ "Hello World",
+ utf32_01,
+ },
+ {
+ "Arabic script",
+ "مرحبا بالعالم",
+ utf32_02,
+ },
+ {
+ "Devanagari script",
+ "हैलो वर्ल्ड",
+ utf32_03,
+ },
+ {
+ "Emojis",
+ "\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84",
+ utf32_04,
+ },
+ };
+ const unsigned int numberOfTests = 4u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !Utf8ToUtf32Test( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextCharacterSetConversionUtf32ToUtf8(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextCharacterSetConversionUtf32ToUtf8");
+
+ unsigned int utf32_01[] = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 }; // Hello World
+ unsigned int utf32_02[] = { 0x645, 0x631, 0x62D, 0x628, 0x627, 0x20, 0x628, 0x627, 0x644, 0x639, 0x627, 0x644, 0x645 }; // مرحبا بالعالم
+ unsigned int utf32_03[] = { 0x939, 0x948, 0x932, 0x94B, 0x20, 0x935, 0x930, 0x94D, 0x932, 0x94D, 0x921 }; // हैलो वर्ल्ड
+ unsigned int utf32_04[] = { 0x1F601, 0x20, 0x1F602, 0x20, 0x1F603, 0x20, 0x1F604 }; // Emojis
+
+ struct Utf32ToUtf8Data data[] =
+ {
+ {
+ "Latin script",
+ utf32_01,
+ 11u,
+ "Hello World",
+ },
+ {
+ "Arabic script",
+ utf32_02,
+ 13u,
+ "مرحبا بالعالم",
+ },
+ {
+ "Devanagari script",
+ utf32_03,
+ 11u,
+ "हैलो वर्ल्ड",
+ },
+ {
+ "Emojis",
+ utf32_04,
+ 7u,
+ "\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84",
+ },
+ };
+
+ const unsigned int numberOfTests = 4u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !Utf32ToUtf8Test( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions with different scripts.
+// Constructor, destructor and MultilanguageSupport::Get()
+// void MultilanguageSupport::SetScripts( const Vector<Character>& text, const Vector<LineBreakInfo>& lineBreakInfo, Vector<ScriptRun>& scripts );
+// void MultilanguageSupport::ValidateFonts( const Vector<Character>& text, const Vector<ScriptRun>& scripts, Vector<FontRun>& fonts );
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct ScriptsData
+{
+ std::string description; ///< Description of the experiment.
+ std::string text; ///< Input text.
+ Vector<ScriptRun> scriptRuns; ///< Expected script runs.
+};
+
+struct ValidateFontsData
+{
+ std::string description; ///< Description of the experiment.
+ std::string text; ///< Input text.
+};
+
+//////////////////////////////////////////////////////////
+
+bool ScriptsTest( const ScriptsData& data )
+{
+ MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+
+ // 1) Convert to utf32
+ Vector<Character> utf32;
+ utf32.Resize( data.text.size() );
+
+ const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+ data.text.size(),
+ &utf32[0u] );
+ utf32.Resize( numberOfCharacters );
+
+ // 2) Set the line break info.
+ Vector<LineBreakInfo> lineBreakInfo;
+ lineBreakInfo.Resize( numberOfCharacters );
+
+ SetLineBreakInfo( utf32, lineBreakInfo );
+
+ // 3) Set the script info.
+ Vector<ScriptRun> scripts;
+ multilanguageSupport.SetScripts( utf32,
+ lineBreakInfo,
+ scripts );
+
+ // 4) Compare the results.
+
+ if( scripts.Count() != data.scriptRuns.Count() )
+ {
+ tet_infoline("ScriptsTest: different number of scripts.");
+ return false;
+ }
+
+ for( unsigned int index = 0u; index < scripts.Count(); ++index )
+ {
+ const ScriptRun& scriptRun1 = scripts[index];
+ const ScriptRun& scriptRun2 = data.scriptRuns[index];
+
+ if( scriptRun1.characterRun.characterIndex != scriptRun2.characterRun.characterIndex )
+ {
+ tet_infoline("ScriptsTest: different character index.");
+ return false;
+ }
+
+ if( scriptRun1.characterRun.numberOfCharacters != scriptRun2.characterRun.numberOfCharacters )
+ {
+ tet_infoline("ScriptsTest: different number of characters.");
+ return false;
+ }
+
+ if( scriptRun1.script != scriptRun2.script )
+ {
+ tet_infoline("ScriptsTest: different script.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateFontTest( const ValidateFontsData& data )
+{
+ MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+
+ // 1) Convert to utf32
+ Vector<Character> utf32;
+ utf32.Resize( data.text.size() );
+
+ const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+ data.text.size(),
+ &utf32[0u] );
+ utf32.Resize( numberOfCharacters );
+
+ // 2) Set the line break info.
+ Vector<LineBreakInfo> lineBreakInfo;
+ lineBreakInfo.Resize( numberOfCharacters );
+
+ SetLineBreakInfo( utf32, lineBreakInfo );
+
+ // 3) Set the script info.
+ Vector<ScriptRun> scripts;
+ multilanguageSupport.SetScripts( utf32,
+ lineBreakInfo,
+ scripts );
+
+ Vector<FontRun> fonts;
+ // 4) Validate the fonts
+ multilanguageSupport.ValidateFonts( utf32,
+ scripts,
+ fonts );
+
+ return true;
+}
+
+} // namespace
+
+int UtcDaliTextMultiLanguageConstructor(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextMultiLanguageConstructor");
+
+ MultilanguageSupport multilanguageSupport;
+ DALI_TEST_CHECK( !multilanguageSupport );
+
+ MultilanguageSupport multilanguageSupport1 = MultilanguageSupport::Get();
+ DALI_TEST_CHECK( multilanguageSupport1 );
+
+ // To increase coverage.
+ MultilanguageSupport multilanguageSupport2 = MultilanguageSupport::Get();
+ DALI_TEST_CHECK( multilanguageSupport2 );
+
+ DALI_TEST_CHECK( multilanguageSupport1 == multilanguageSupport2 );
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextMultiLanguageSetScripts(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextMultiLanguageSetScripts" );
+
+ // Void text.
+ Vector<ScriptRun> scriptRuns00;
+
+ // Hello world.
+ Vector<ScriptRun> scriptRuns01;
+ ScriptRun scriptRun0100 =
+ {
+ 0u,
+ 11u,
+ TextAbstraction::LATIN
+ };
+ scriptRuns01.PushBack( scriptRun0100 );
+
+ const ScriptsData data[] =
+ {
+ {
+ "void text",
+ "",
+ scriptRuns00,
+ },
+ {
+ "Easy latin script",
+ "Hello world",
+ scriptRuns01,
+ },
+ };
+ const unsigned int numberOfTests = 2u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !ScriptsTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextMultiLanguageValidateFonts01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextMultiLanguageValidateFonts");
+
+ const ValidateFontsData data[] =
+ {
+ {
+ "void text",
+ "",
+ },
+ {
+ "Easy latin script",
+ "Hello world",
+ },
+ };
+ const unsigned int numberOfTests = 2u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !ValidateFontTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions with different scripts.
+// void SetLineBreakInfo( const Vector<Character>& text, Vector<LineBreakInfo>& lineBreakInfo );
+// void SetWordBreakInfo( const Vector<Character>& text, Vector<WordBreakInfo>& wordBreakInfo );
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct BreakInfoData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< input text.
+ std::string breakInfo; ///< The expected break info.
+};
+
+bool LineBreakInfoTest( const BreakInfoData& data )
+{
+ // 1) Convert to utf32
+ Vector<Character> utf32;
+ utf32.Resize( data.text.size() );
+
+ const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+ data.text.size(),
+ &utf32[0u] );
+ utf32.Resize( numberOfCharacters );
+
+ // 2) Set the line break info.
+ Vector<LineBreakInfo> lineBreakInfo;
+ lineBreakInfo.Resize( numberOfCharacters );
+
+ SetLineBreakInfo( utf32, lineBreakInfo );
+
+ // 3) compare the results
+ std::ostringstream breakInfo;
+
+ for( unsigned int index = 0u; index < numberOfCharacters; ++index )
+ {
+ breakInfo << static_cast<unsigned int>( lineBreakInfo[index] );
+ }
+
+ return data.breakInfo == breakInfo.str();
+}
+
+bool WordBreakInfoTest( const BreakInfoData& data )
+{
+ // 1) Convert to utf32
+ Vector<Character> utf32;
+ utf32.Resize( data.text.size() );
+
+ const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+ data.text.size(),
+ &utf32[0u] );
+ utf32.Resize( numberOfCharacters );
+
+ // 2) Set the word break info.
+ Vector<WordBreakInfo> wordBreakInfo;
+ wordBreakInfo.Resize( numberOfCharacters );
+
+ SetWordBreakInfo( utf32, wordBreakInfo );
+
+ // 3) compare the results
+ std::ostringstream breakInfo;
+
+ for( unsigned int index = 0u; index < numberOfCharacters; ++index )
+ {
+ breakInfo << static_cast<unsigned int>( wordBreakInfo[index] );
+ }
+
+ return data.breakInfo == breakInfo.str();
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+
+int UtcDaliTextSegnemtationSetLineBreakInfo(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextSegnemtationSetLineBreakInfo");
+
+ struct BreakInfoData data[] =
+ {
+ {
+ "Zero characters",
+ "",
+ "",
+ },
+ {
+ "Latin script",
+ "Hello world",
+ "22222122220",
+ },
+ {
+ "Latin script with \n",
+ "Hello\nworld",
+ "22222022220",
+ },
+ {
+ "Japanese script",
+ "こんにちは世界",
+ "1111110",
+ },
+ {
+ "Japanese script with \n",
+ "こんにちは\n世界",
+ "11112010",
+ },
+ {
+ "Chinese script",
+ "你好世界",
+ "1110",
+ },
+ {
+ "Chinese script with \n",
+ "你好\n世界",
+ "12010",
+ }
+ };
+ const unsigned int numberOfTests = 7u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !LineBreakInfoTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextSegnemtationSetWordBreakInfo(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextSegnemtationSetWordBreakInfo");
+
+ struct BreakInfoData data[] =
+ {
+ {
+ "Zero characters",
+ "",
+ "",
+ },
+ {
+ "Latin script",
+ "Hello world",
+ "11110011110",
+ },
+ {
+ "Latin script with \n",
+ "Hello\nworld",
+ "11110011110",
+ },
+ {
+ "Japanese script",
+ "こんにちは世界",
+ "0000000",
+ },
+ {
+ "Japanese script with \n",
+ "こんにちは\n世界",
+ "00000000",
+ },
+ {
+ "Chinese script",
+ "你好世界",
+ "0000",
+ },
+ {
+ "Chinese script with \n",
+ "你好\n世界",
+ "00000",
+ }
+ };
+ const unsigned int numberOfTests = 7u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !WordBreakInfoTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
utc-Dali-Builder.cpp
utc-Dali-CheckBoxButton.cpp
utc-Dali-CubeTransitionEffect.cpp
+ utc-Dali-EffectsView.cpp
utc-Dali-GaussianBlurView.cpp
utc-Dali-JsonParser.cpp
utc-Dali-KeyInputFocusManager.cpp
utc-Dali-ItemLayout.cpp
utc-Dali-ItemView.cpp
utc-Dali-KeyboardFocusManager.cpp
+ utc-Dali-Magnifier.cpp
utc-Dali-NinePatchMaskEffect.cpp
utc-Dali-Popup.cpp
utc-Dali-PushButton.cpp
DALI_TEST_CHECK( 1u == taskList3.GetTaskCount() );
END_TEST;
}
+
+int UtcDaliBloomCopyAndAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ BloomView view = Toolkit::BloomView::New();
+ DALI_TEST_CHECK( view );
+
+ BloomView copy( view );
+ DALI_TEST_CHECK( view == copy );
+
+ BloomView assign;
+ DALI_TEST_CHECK( ! assign );
+
+ assign = copy;
+ DALI_TEST_CHECK( assign == view );
+
+ END_TEST;
+}
+
+int UtcDaliBloomTypeRegistry(void)
+{
+ ToolkitTestApplication application;
+
+ TypeRegistry typeRegistry = TypeRegistry::Get();
+ DALI_TEST_CHECK( typeRegistry );
+
+ TypeInfo typeInfo = typeRegistry.GetTypeInfo( "BloomView" );
+ DALI_TEST_CHECK( typeInfo );
+
+ BaseHandle handle = typeInfo.CreateInstance();
+ DALI_TEST_CHECK( handle );
+
+ BloomView view = BloomView::DownCast( handle );
+ DALI_TEST_CHECK( view );
+
+ END_TEST;
+}
+
+int UtcDaliBloomOnSizeSet(void)
+{
+ ToolkitTestApplication application;
+
+ BloomView view = Toolkit::BloomView::New();
+
+ Stage::GetCurrent().Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ Vector3 size( 200.0f, 300.0f, 200.0f );
+ view.SetSize( size );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetCurrentSize(), size, TEST_LOCATION );
+
+ END_TEST;
+}
Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 );
BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 150, Vector2( 5.f, 10.f ));
+ DALI_TEST_CHECK(emitter);
Actor root = emitter.GetRootActor();
Stage::GetCurrent().Add( root );
+ root.SetPosition( Vector3::ZERO );
+ root.SetParentOrigin( ParentOrigin::CENTER );
+ root.SetAnchorPoint( AnchorPoint::CENTER );
TestGlAbstraction& gl = application.GetGlAbstraction();
Wait(application);
DALI_TEST_CHECK( gl.GetUniformValue<float>( "uDynamicScale", scaleValue ) );
DALI_TEST_EQUALS( scaleValue, 0.5f, TEST_LOCATION );
+
END_TEST;
}
Image shapeImage = CreateSolidColorImage( application, Color::GREEN, 5, 5 );
BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 150, Vector2( 5.f, 10.f ));
+ DALI_TEST_CHECK(emitter);
Actor root = emitter.GetRootActor();
Stage::GetCurrent().Add( root );
+ root.SetPosition( Vector3::ZERO );
+ root.SetParentOrigin( ParentOrigin::CENTER );
+ root.SetAnchorPoint( AnchorPoint::CENTER );
TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
Wait(application);
BubbleEmitter emitter = BubbleEmitter::New( Vector2(50.f,50.f),shapeImage, 90, Vector2( 5.f, 10.f ));
Actor root = emitter.GetRootActor();
Stage::GetCurrent().Add( root );
+ root.SetPosition( Vector3::ZERO );
+ root.SetParentOrigin( ParentOrigin::CENTER );
+ root.SetAnchorPoint( AnchorPoint::CENTER );
Actor bubbleMesh = root.GetChildAt( 0 );
Renderer renderer = bubbleMesh.GetRendererAt( 0 );
DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uStartEndPosition[0]", startEndPosValue ) );
DALI_TEST_EQUALS( startEndPosValue, Vector4::ZERO, TEST_LOCATION );
+
END_TEST;
}
#include <dali-toolkit/devel-api/builder/builder.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#define STRINGIFY(A)#A
+
using namespace Dali;
using namespace Toolkit;
END_TEST;
}
+
+
+int UtcDaliBuilderAnimationP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{"
+ " \"constants\":"
+ " {"
+ " \"ALPHA_FUNCTION\":\"EASE_IN_OUT\""
+ " },"
+ " \"paths\":"
+ " {"
+ " \"path0\":"
+ " {"
+ " \"points\":[ [-150, -50, 0], [0.0,70.0,0.0], [190.0,-150.0,0.0] ],"
+ " \"curvature\":0.35"
+ " }"
+ " },"
+ " \"animations\": {"
+ " \"animate\": {"
+ " \"loop\": true,"
+ " \"end-action\": \"BAKE\","
+ " \"disconnect-action\": \"BAKE\","
+ " \"properties\":"
+ " [{"
+ " \"actor\": \"greeting\","
+ " \"property\": \"position\","
+ " \"value\": [300, 300, -1000],"
+ " \"alpha-function\": \"{ALPHA_FUNCTION}\","
+ " \"relative\": true,"
+ " \"time-period\": {"
+ " \"delay\": 0,"
+ " \"duration\": 3"
+ " }"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"visible\","
+ " \"alpha-function\": \"LINEAR\","
+ " \"value\": true"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"size-width\","
+ " \"alpha-function\": \"REVERSE\","
+ " \"value\": 10.0"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"EASE_IN\","
+ " \"value\": [10.0,20.0,30.0]"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"EASE_OUT\","
+ " \"value\": [0.0, 0.0, 0.0, 1.0]"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"EASE_IN_OUT\","
+ " \"value\": [0.0, 0.0, 0.0, 1.0]"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"EASE_IN_SINE\","
+ " \"value\": [0.0, 0.0, 0.0, 1.0]"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"EASE_OUT_SINE\","
+ " \"value\": [0.0, 0.0, 0.0, 1.0]"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"EASE_IN_OUT_SINE\","
+ " \"value\": [0.0, 0.0, 0.0, 1.0]"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"BOUNCE\","
+ " \"value\": [0.0, 0.0, 0.0, 1.0]"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"SIN\","
+ " \"value\": [0.0, 0.0, 0.0, 1.0]"
+ " },"
+ " {"
+ " \"actor\": \"greeting\","
+ " \"property\": \"orientation\","
+ " \"alpha-function\": \"EASE_OUT_BACK\","
+ " \"value\": [0.0, 0.0, 0.0, 1.0]"
+ " }"
+ " ]"
+ " },"
+ " \"path-animation\": {"
+ " \"duration\": 3.0,"
+ " \"end-action\": \"DISCARD\","
+ " \"disconnect-action\": \"BAKE_FINAL\","
+ " \"properties\": [{"
+ " \"actor\": \"greeting\","
+ " \"path\":\"path0\","
+ " \"forward\":[1,0,0],"
+ " \"alpha-function\": \"EASE_IN_OUT\","
+ " \"time-period\": {"
+ " \"delay\": 0,"
+ " \"duration\": 3"
+ " }"
+ " }]"
+ " }"
+ " },"
+ " \"stage\": [{"
+ " \"name\": \"greeting\","
+ " \"type\": \"TextLabel\","
+ " \"text\": \"Touch me\","
+ " \"styles\": [\"basic-text\"],"
+ " \"position\": [0, -120, 0],"
+ " \"size\": [200, 200, 1],"
+ " \"orientation\": [0, 0, 30],"
+ " \"signals\": [{"
+ " \"name\": \"touched\","
+ " \"action\": \"play\","
+ " \"animation\": \"animate\""
+ " }]"
+ " }]"
+ "}");
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+ builder.AddActors( Stage::GetCurrent().GetRootLayer() );
+
+ Animation anim = builder.CreateAnimation("animate");
+
+ DALI_TEST_CHECK( anim );
+
+ Property::Map map;
+ map["ALPHA_FUNCTION"] = "EASE_IN_SQUARE";
+ anim = builder.CreateAnimation("animate", map);
+
+ DALI_TEST_CHECK( anim );
+
+ anim = builder.CreateAnimation("path-animation");
+
+ DALI_TEST_CHECK( anim );
+
+ // trigger play
+ // Emit touch event and check that our quit method is called
+ Integration::TouchEvent touchEvent;
+ touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+ application.ProcessEvent( touchEvent );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+
+ END_TEST;
+}
+
+int UtcDaliBuilderAnimationN(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{"
+ " \"constants\":"
+ " {"
+ " \"TEXT\": \"Touch Me\","
+ " \"NAME\": \"greeting\" "
+ " },"
+ " \"paths\":"
+ " {"
+ " \"path0\":"
+ " {"
+ " \"points\":[ [-150, -50, 0], [0.0,70.0,0.0], [190.0,-150.0,0.0] ],"
+ " \"curvature\":0.35"
+ " }"
+ " },"
+ " \"animations\": {"
+ " \"animate\": {"
+ " \"loop\": true,"
+ " \"end-action\": \"BAKE\","
+ " \"disconnect-action\": \"BAKE\","
+ " \"properties\":"
+ " [{"
+ " \"actor\": \"{NAME}\","
+ " \"property\": \"positioninvalid\","
+ " \"value\": [300, 300, -1000],"
+ " \"alpha-function\": \"EASE_IN_OUT\","
+ " \"relative\": true,"
+ " \"time-period\": {"
+ " \"delay\": 0,"
+ " \"duration\": 3"
+ " }"
+ " }"
+ " ]"
+ " },"
+ " \"animate2\": {"
+ " \"loop\": true,"
+ " \"end-action\": \"BAKE\","
+ " \"disconnect-action\": \"BAKE\","
+ " \"properties\":"
+ " [{"
+ " \"actor\": \"{NAME}\","
+ " \"property\": \"positioninvalid\","
+ " \"value\": [300, 300, -1000],"
+ " \"alpha-function\": \"EGGS_OVER_EASY\","
+ " \"relative\": true,"
+ " \"time-period\": {"
+ " \"delay\": 0,"
+ " \"duration\": 3"
+ " }"
+ " }"
+ " ]"
+ " },"
+ " \"path-animation\": {"
+ " \"duration\": 3.0,"
+ " \"end-action\": \"DISCARD\","
+ " \"disconnect-action\": \"BAKE_FINAL\","
+ " \"properties\": [{"
+ " \"actor\": \"greeting\","
+ " \"path\":\"pathDoesntExist\","
+ " \"forward\":[1,0,0],"
+ " \"alpha-function\": \"EASE_IN_OUT\","
+ " \"time-period\": {"
+ " \"delay\": 0,"
+ " \"duration\": 3"
+ " }"
+ " }]"
+ " }"
+ " },"
+ " \"stage\": [{"
+ " \"name\": \"greeting\","
+ " \"type\": \"TextLabel\","
+ " \"text\": \"Touch me\","
+ " \"styles\": [\"basic-text\"],"
+ " \"position\": [0, -120, 0],"
+ " \"size\": [200, 200, 1],"
+ " \"orientation\": [0, 0, 30],"
+ " \"signals\": [{"
+ " \"name\": \"touched\","
+ " \"action\": \"play\","
+ " \"animation\": \"animate\""
+ " }]"
+ " },"
+ " {"
+ " \"name\": \"greeting2\","
+ " \"type\": \"TextLabel\","
+ " \"text\": \"Touch me\""
+ " }]"
+ "}");
+
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+ builder.AddActors( Stage::GetCurrent().GetRootLayer() );
+
+ Animation anim = builder.CreateAnimation("animate");
+
+ // log warning line coverage
+ anim = builder.CreateAnimation("path-animation");
+ DALI_TEST_CHECK(anim);
+
+ anim = builder.CreateAnimation("animate");
+ DALI_TEST_CHECK(anim);
+
+ anim = builder.CreateAnimation("animate2");
+ DALI_TEST_CHECK(anim);
+
+ // create referencing a different actor aka animation templates
+ Property::Map map;
+ map["NAME"] = "greeting2";
+ anim = builder.CreateAnimation("animate2", map);
+ DALI_TEST_CHECK(anim);
+
+ // alternative actor to use for FindChildByName
+ anim = builder.CreateAnimation("animate2", Dali::Stage::GetCurrent().GetRootLayer());
+ DALI_TEST_CHECK(anim);
+
+ // alternative actor to use for FindChildByName
+ anim = builder.CreateAnimation("animate2", map, Dali::Stage::GetCurrent().GetRootLayer());
+ DALI_TEST_CHECK(anim);
+
+
+ END_TEST;
+
+}
+
+int UtcDaliBuilderConstantsP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{"
+ "\"constants\":"
+ "{"
+ " \"IMAGE_PATH\": \"apath\","
+ " \"WIDTH\": 22.3,"
+ " \"ANCHOR\": \"TOP_LEFT\","
+ " \"PADDING\": [1,2,3,4]"
+ "},"
+ "\"stage\":"
+ "[{"
+ " \"type\": \"ImageActor\","
+ " \"name\": \"{NAME}\","
+ " \"size\": [100,100,1],"
+ " \"parent-origin\": \"TOP_LEFT\","
+ " \"anchor-point\": \"{ANCHOR}\","
+ " \"padding\": \"{PADDING}\","
+ " \"image\": { \"filename\": \"dir/{IMAGE_PATH}\" },"
+ " \"size-width\": \"{WIDTH}\","
+ " \"signals\": [{"
+ " \"name\": \"touched\","
+ " \"action\": \"quit\""
+ " }]"
+ "}]"
+ "}"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ builder.AddConstant( "NAME", "image" );
+
+ Property::Map map = builder.GetConstants();
+
+ Dali::Property::Value* pValue = map.Find( "NAME" );
+
+ DALI_TEST_CHECK( pValue );
+
+ pValue = map.Find( "IMAGE_PATH" );
+
+ DALI_TEST_CHECK( pValue );
+
+ Dali::Property::Value value = builder.GetConstant( "WIDTH" );
+
+ DALI_TEST_CHECK( value.GetType() != Property::NONE );
+
+ builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+ DALI_TEST_CHECK( builder );
+
+ Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("image");
+ DALI_TEST_CHECK( actor );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderTemplatesAndStylesP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ "\"constants\":"
+ "{"
+ " \"SIZE\": [10,20,30]"
+ "},"
+ "\"styles\":\n"
+ "{\n"
+ " \"image-style\": \n"
+ " {\n"
+ " \"color\": [1,0,0,1],\n"
+ " \"actors\": {\n"
+ " \"child-image\": {\n"
+ " \"color\": [0,1,0,1]\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "},\n"
+ "\"templates\":\n"
+ "{\n"
+ " \"image-tree\": { \n"
+ " \"type\": \"ImageActor\",\n"
+ " \"styles\": [\"image-style\"],\n"
+ " \"name\": \"image\",\n"
+ " \"size\": \"{SIZE}\",\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"quit\"\n"
+ " }],\n"
+ " \"actors\": [\n"
+ " {\n"
+ " \"type\":\"ImageActor\",\n"
+ " \"name\":\"child-image\" \n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ "},\n"
+ "\"stage\":"
+ "[{"
+ " \"type\": \"image-tree\","
+ " \"size\": [100,100,1]"
+ "}]"
+ "}\n"
+ );
+
+ std::string stylejson(
+ "{\n"
+ " \"color\": [1,0,0,1],\n"
+ " \"actors\": {\n"
+ " \"child-image\": {\n"
+ " \"color\": [0,1,0,1]\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ );
+
+ std::string templatejson(
+ "{ \n"
+ " \"type\": \"ImageActor\",\n"
+ " \"styles\": [\"image-style\"],\n"
+ " \"name\": \"image\",\n"
+ " \"size\": \"{SIZE}\",\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"quit\"\n"
+ " }],\n"
+ " \"actors\": [\n"
+ " {\n"
+ " \"type\":\"ImageActor\",\n"
+ " \"name\":\"child-image\" \n"
+ " }\n"
+ " ]\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ ImageActor actor = ImageActor::DownCast( builder.Create( "image-tree" ) );
+ DALI_TEST_CHECK( actor );
+
+ Dali::Property::Map map;
+ map["SIZE"] = Vector3(100,100,1);
+ actor = ImageActor::DownCast( builder.Create( "image-tree", map ) );
+ DALI_TEST_CHECK( actor );
+
+ // create from json snippet
+ actor = ImageActor::DownCast( builder.CreateFromJson( templatejson ) );
+ DALI_TEST_CHECK( actor );
+
+
+ // NB: already applied in create
+ DALI_TEST_CHECK( builder.ApplyStyle( "image-style", actor ) );
+
+ // apply from json snippet
+ DALI_TEST_CHECK( builder.ApplyFromJson( actor, stylejson ) );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderRenderTasksP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ "\"render-tasks\":\n"
+ "{\n"
+ " \"task0\": {\n"
+ " \"source-actor\": \"image\",\n"
+ " \"camera-actor\": \"camera\" \n"
+ " }\n"
+ "},\n"
+ "\"stage\":\n"
+ "[\n"
+ " { \n"
+ " \"type\": \"CameraActor\",\n"
+ " \"name\": \"image\"\n"
+ " }, \n"
+ " { \n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"image\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"quit\"\n"
+ " }],\n"
+ " \"actors\": [\n"
+ " {\n"
+ " \"type\":\"ImageActor\",\n"
+ " \"name\":\"child-image\" \n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ "]\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ unsigned int count = Stage::GetCurrent().GetRenderTaskList().GetTaskCount();
+
+ // coverage
+ builder.CreateRenderTask( "task0" );
+
+ DALI_TEST_CHECK( count <
+ Stage::GetCurrent().GetRenderTaskList().GetTaskCount() );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderChildActionP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"stage\":\n"
+ " [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"actor\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"parent-origin\": \"TOP_LEFT\",\n"
+ " \"anchor-point\": \"TOP_LEFT\",\n"
+ " \"actors\": [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"sub-actor\"\n"
+ " }],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"hide\",\n"
+ " \"actor\": \"actor\",\n"
+ " \"child-actor\": \"sub-actor\"\n"
+ " }]\n"
+ " }]\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+ builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit touch event and check that our quit method is called
+ Integration::TouchEvent touchEvent;
+ touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+ application.ProcessEvent( touchEvent );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("sub-actor");
+ DALI_TEST_CHECK( actor );
+
+ DALI_TEST_CHECK( !actor.IsVisible() );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderSetPropertyActionP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"stage\":\n"
+ " [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"actor\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"parent-origin\": \"TOP_LEFT\",\n"
+ " \"anchor-point\": \"TOP_LEFT\",\n"
+ " \"actors\": [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"sub-actor\"\n"
+ " }],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"set\",\n"
+ " \"actor\": \"sub-actor\",\n"
+ " \"property\": \"visible\",\n"
+ " \"value\": false\n"
+ " }]\n"
+ " }]\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+ builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit touch event and check that our quit method is called
+ Integration::TouchEvent touchEvent;
+ touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+ application.ProcessEvent( touchEvent );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("sub-actor");
+ DALI_TEST_CHECK( actor );
+
+ DALI_TEST_CHECK( !actor.IsVisible() );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderGenericActionP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"stage\":\n"
+ " [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"actor\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"parent-origin\": \"TOP_LEFT\",\n"
+ " \"anchor-point\": \"TOP_LEFT\",\n"
+ " \"actors\": [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"sub-actor\"\n"
+ " }],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"hide\"\n"
+ " }]\n"
+ " }]\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+ builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit touch event and check that our quit method is called
+ Integration::TouchEvent touchEvent;
+ touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+ application.ProcessEvent( touchEvent );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("actor");
+ DALI_TEST_CHECK( actor );
+
+ DALI_TEST_CHECK( !actor.IsVisible() );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderPropertyNotificationP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"stage\":\n"
+ " [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"actor\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"parent-origin\": \"TOP_LEFT\",\n"
+ " \"anchor-point\": \"TOP_LEFT\",\n"
+ " \"actors\": [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"sub-actor\"\n"
+ " }],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"hide\"\n"
+ " }],\n"
+ " \"notifications\": [{\n"
+ " \"property\": \"visible\",\n"
+ " \"condition\": \"False\",\n"
+ " \"action\": \"show\"\n"
+ " }]\n"
+ " }]\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+ builder.AddActors ( Stage::GetCurrent().GetRootLayer() );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit touch event and check that our quit method is called
+ Integration::TouchEvent touchEvent;
+ touchEvent.points.push_back( TouchPoint ( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+ application.ProcessEvent( touchEvent );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("actor");
+ DALI_TEST_CHECK( actor );
+
+ DALI_TEST_CHECK( actor.IsVisible() );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderCustomPropertyP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ "\"templates\":\n"
+ "{\n"
+ " \"image-tree\": { \n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"image\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"quit\"\n"
+ " }],\n"
+ " \"custom-properties\": {\n"
+ " \"newproperty\": true\n"
+ " },\n"
+ " \"actors\": [\n"
+ " {\n"
+ " \"type\":\"ImageActor\",\n"
+ " \"name\":\"child-image\" \n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ "}\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ ImageActor actor = ImageActor::DownCast( builder.Create( "image-tree" ) );
+ DALI_TEST_CHECK( actor );
+
+ // NB: already applied in create
+ Property::Index index = actor.GetPropertyIndex("newproperty");
+ DALI_TEST_CHECK( Property::INVALID_INDEX != index );
+ Property::Value value = actor.GetProperty(index);
+ DALI_TEST_CHECK( value.Get<bool>() == true );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderShaderEffectP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"stage\": [\n"
+ " {\n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"Image1\",\n"
+ " \"position\": [\n"
+ " 0.40461349487305,\n"
+ " 0.9150390625,\n"
+ " 0.0\n"
+ " ],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"size\": [200, 200, 0],\n"
+ " \"effect\": \"Ripple2D\",\n"
+ " \"image\": {\n"
+ " \"filename\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\",\n"
+ " \"width\": 200,\n"
+ " \"height\": 80,\n"
+ " \"load-policy\": \"IMMEDIATE\",\n"
+ " \"release-policy\": \"NEVER\"\n"
+ " },\n"
+ " \"signals\": [\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"play\",\n"
+ " \"animation\": \"Animation_1\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ],\n"
+ " \"paths\": {},\n"
+ " \"animations\": {\n"
+ " \"Animation_1\": {\n"
+ " \"loop\":true,\n"
+ " \"properties\": [\n"
+ " {\n"
+ " \"actor\": \"Image1\",\n"
+ " \"property\": \"uTime\",\n"
+ " \"value\": 10.0,\n"
+ " \"alpha-function\": \"LINEAR\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 10.0\n"
+ " },\n"
+ " \"gui-builder-timeline-color\": \"#8dc0da\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " },\n"
+ " \"shader-effects\": {\n"
+ " \"Ripple2D\": {\n"
+ " \"program\": {\n"
+ " \"vertexPrefix\": \"\",\n"
+ " \"vertex\": \"void main(void)\\n{\\n gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
+ " \"fragmentPrefix\": \"\",\n"
+ " \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n highp float len = length(pos);\\n highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+ " \"geometry-type\": \"GEOMETRY_TYPE_IMAGE\"\n"
+ " },\n"
+ " \"geometry-hints\": \"HINT_NONE\",\n"
+ " \"grid-density\": 0,\n"
+ " \"loop\": true,\n"
+ " \"uAmplitude\": 0.02,\n"
+ " \"uTime\": 0.0\n"
+ " }\n"
+ " }\n"
+ "}\n"
+
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ ShaderEffect effect = builder.GetShaderEffect("Ripple2D");
+
+ // coverage
+ DALI_TEST_CHECK( effect );
+
+ END_TEST;
+}
+
+
+int UtcDaliBuilderLoadFromStringN(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "asdfsadf dsf asdf asdf {"
+ "\"stage\":"
+ "[{"
+ "\"type\": \"Actor\","
+ "\"size\": [100,100,1],"
+ "\"parent-origin\": \"TOP_LEFT\","
+ "\"anchor-point\": \"TOP_LEFT\","
+ "\"signals\": [{"
+ "\"name\": \"touched\","
+ "\"action\": \"quit\""
+ "}]"
+ "}]"
+ "}"
+ );
+ Builder builder = Builder::New();
+
+ bool assert1 = false;
+
+ try
+ {
+ builder.LoadFromString( json );
+ }
+ catch( Dali::DaliException& e )
+ {
+ DALI_TEST_PRINT_ASSERT( e );
+ DALI_TEST_EQUALS(e.condition, "!\"Cannot parse JSON\"", TEST_LOCATION);
+ assert1 = true;
+ }
+
+ DALI_TEST_CHECK( assert1 );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderShaderEffect2P(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ "\"templates\":\n"
+ "{\n"
+ " \"image-tree\": { \n"
+ " \"type\": \"ImageActor\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"position\": [\n"
+ " 0.40461349487305,\n"
+ " 0.9150390625,\n"
+ " 0.0\n"
+ " ],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"quit\"\n"
+ " }],\n"
+ " \"actors\": [\n"
+ " {\n"
+ " \"type\":\"ImageActor\",\n"
+ " \"name\":\"child-image\" \n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ "},\n"
+ " \"stage\": [\n"
+ " {\n"
+ " \"type\": \"image-tree\",\n"
+ " \"name\": \"Image1\",\n"
+ " \"effect\": \"Ripple2D\",\n"
+ " \"image\": \"offscreen\""
+ " }\n"
+ " ],\n"
+ " \"shader-effects\": {\n"
+ " \"Ripple2D\": {\n"
+ " \"program\": {\n"
+ " \"vertexPrefix\": \"\",\n"
+ " \"vertex\": \"void main(void)\\n{\\n gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
+ " \"fragmentPrefix\": \"\",\n"
+ " \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n highp float len = length(pos);\\n highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+ " \"geometry-type\": \"GEOMETRY_TYPE_IMAGE\"\n"
+ " },\n"
+ " \"geometry-hints\": \"HINT_NONE\",\n"
+ " \"grid-density\": 0,\n"
+ " \"loop\": true,\n"
+ " \"uAmplitude\": 0.02,\n"
+ " \"uTime\": 0.0\n"
+ " }\n"
+ " },\n"
+ " \"frame-buffer-images\": {\n"
+ " \"offscreen\": {\n"
+ " \"type\": \"FrameBufferImage\","
+ " \"pixel-format\":\"RGBA8888\","
+ " \"width\": 400,"
+ " \"height\": 400"
+ " }"
+ " }"
+ "}\n"
+
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ // coverage
+ DALI_TEST_CHECK( true );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderAddActorsP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"arbitarysection\":\n"
+ " [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"actor\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"parent-origin\": \"TOP_LEFT\",\n"
+ " \"anchor-point\": \"TOP_LEFT\",\n"
+ " \"actors\": [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"sub-actor\",\n"
+ " \"visible\": false\n"
+ " }],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"hide\",\n"
+ " \"actor\": \"actor\",\n"
+ " \"child-actor\": \"sub-actor\"\n"
+ " }]\n"
+ " }]\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+ builder.AddActors ( "arbitarysection", Stage::GetCurrent().GetRootLayer() );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("sub-actor");
+ DALI_TEST_CHECK( actor );
+
+ DALI_TEST_CHECK( !actor.IsVisible() );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderFrameBufferP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"constants\":\n"
+ " {\n"
+ " \"FB_WIDTH\": 200.0,\n"
+ " \"FB_HEIGHT\": 200.0,\n"
+ " \"FB_SIZE\": [200,200],\n"
+ " \"FB_ASPECT_RATIO\": 1\n"
+ " },\n"
+ " \"stage\": [\n"
+ " {\n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"fbOnStage\",\n"
+ " \"position\": [\n"
+ " 0.40461349487305,\n"
+ " 0.9150390625,\n"
+ " 0.0\n"
+ " ],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"size\": [300, 300, 0],\n"
+ " \"image\": \"fb0\",\n"
+ " \"clear-color\": [1,0,0,1]\n"
+ " },\n"
+ " {\n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"Image1\",\n"
+ " \"size\": [200, 200, 0],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"effect\": \"Ripple2D\",\n"
+ " \"image\": {\n"
+ " \"filename\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\",\n"
+ " \"width\": 200,\n"
+ " \"height\": 80,\n"
+ " \"load-policy\": \"IMMEDIATE\",\n"
+ " \"release-policy\": \"NEVER\"\n"
+ " },\n"
+ " \"signals\": [\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"play\",\n"
+ " \"animation\": \"Animation_1\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"type\":\"CameraActor\",\n"
+ " \"name\":\"fbCam\",\n"
+ " \"aspect-ratio\": \"{FB_ASPECT_RATIO}\",\n"
+ " \"projection-mode\": \"PERSPECTIVE_PROJECTION\",\n"
+ " \"field-of-view\": 0.785,\n"
+ " \"invert-y-axis\": true\n"
+ " }\n"
+ " ],\n"
+ " \"frame-buffer-images\":\n"
+ " {\n"
+ " \"fb0\":\n"
+ " {\n"
+ " \"type\": \"FrameBufferImage\",\n"
+ " \"width\": { \"type-cast\":\"float\", \"value\":\"{FB_WIDTH}\" },\n"
+ " \"height\": { \"type-cast\":\"float\", \"value\":\"{FB_HEIGHT}\" }\n"
+ " }\n"
+ " },\n"
+ " \"render-tasks\":\n"
+ " {\n"
+ " \"stage\":\n"
+ " [\n"
+ " {\n"
+ " \"source-actor\": \"fbOnStage\"\n"
+ " },\n"
+ " {\n"
+ " \"source-actor\": \"Image1\",\n"
+ " \"target-frame-buffer\": \"fb0\",\n"
+ " \"viewport-size\":\"{FB_SIZE}\",\n"
+ " \"camera-actor\":\"fbCam\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"paths\": {},\n"
+ " \"animations\": {\n"
+ " \"Animation_1\": {\n"
+ " \"loop\":true,\n"
+ " \"properties\": [\n"
+ " {\n"
+ " \"actor\": \"Image1\",\n"
+ " \"property\": \"uTime\",\n"
+ " \"value\": 10.0,\n"
+ " \"alpha-function\": \"LINEAR\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 10.0\n"
+ " },\n"
+ " \"gui-builder-timeline-color\": \"#8dc0da\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " },\n"
+ " \"shader-effects\": {\n"
+ " \"Ripple2D\": {\n"
+ " \"program\": {\n"
+ " \"vertexPrefix\": \"\",\n"
+ " \"vertex\": \"void main(void)\\n{\\n gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
+ " \"fragmentPrefix\": \"\",\n"
+ " \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n highp float len = length(pos);\\n highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+ " \"geometry-type\": \"GEOMETRY_TYPE_IMAGE\"\n"
+ " },\n"
+ " \"geometry-hints\": \"HINT_NONE\",\n"
+ " \"grid-density\": 0,\n"
+ " \"loop\": true,\n"
+ " \"uAmplitude\": 0.02,\n"
+ " \"uTime\": 0.0\n"
+ " }\n"
+ " }\n"
+ "}\n");
+
+ Builder builder = Builder::New();
+
+ // frame buffer coverage
+ builder.LoadFromString( json );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Dali::FrameBufferImage frameBuffer = builder.GetFrameBufferImage( "fb0" );
+ DALI_TEST_CHECK( frameBuffer );
+
+ Dali::FrameBufferImage frameBuffer2 = builder.GetFrameBufferImage( "fb0" );
+ DALI_TEST_CHECK( frameBuffer2 );
+ DALI_TEST_CHECK( frameBuffer == frameBuffer2 );
+
+ DALI_TEST_CHECK( true );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderPathConstraintsP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"constants\":\n"
+ " {\n"
+ " \"FB_WIDTH\": 200.0,\n"
+ " \"FB_HEIGHT\": 200.0,\n"
+ " \"FB_SIZE\": [200,200],\n"
+ " \"FB_ASPECT_RATIO\": 1\n"
+ " },\n"
+ " \"stage\": [\n"
+ " {\n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"Image1\",\n"
+ " \"size\": [200, 200, 0],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"effect\": \"Ripple2D\",\n"
+ " \"image\": {\n"
+ " \"filename\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\",\n"
+ " \"width\": 200,\n"
+ " \"height\": 80,\n"
+ " \"load-policy\": \"IMMEDIATE\",\n"
+ " \"release-policy\": \"NEVER\"\n"
+ " },\n"
+ " \"signals\": [\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"play\",\n"
+ " \"animation\": \"path-animation\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"applyConstraint\",\n"
+ " \"constrainer\": \"constrainer0\",\n"
+ " \"properties\":\n"
+ " [\n"
+ " {\n"
+ " \"source\": \"Image1\",\n"
+ " \"sourceProperty\": \"position-x\",\n"
+ " \"target\": \"Image1\",\n"
+ " \"targetProperty\": \"color-red\",\n"
+ " \"range\": [-300,300]\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"applyConstraint\",\n"
+ " \"constrainer\": \"constrainer1\",\n"
+ " \"properties\":\n"
+ " [\n"
+ " {\n"
+ " \"source\": \"Image1\",\n"
+ " \"sourceProperty\": \"position-x\",\n"
+ " \"target\": \"Image1\",\n"
+ " \"targetProperty\": \"color-blue\",\n"
+ " \"range\": [-300,300]\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ],\n"
+ " \"paths\":\n"
+ " {\n"
+ " \"path0\":\n"
+ " {\n"
+ " \"points\":[ [-150, -50, 0], [0.0,70.0,0.0], [190.0,-150.0,0.0] ],\n"
+ " \"curvature\":0.35\n"
+ " }\n"
+ " },\n"
+ " \"constrainers\":\n"
+ " {\n"
+ " \"constrainer0\":\n"
+ " {\n"
+ " \"type\": \"PathConstrainer\",\n"
+ " \"points\": [ [0, 0, 0], [0,0,0], [0,0,0] ],\n"
+ " \"control-points\": [ [0, 0, 0], [0,0,0], [0,0,0] ]\n"
+ " },\n"
+ " \"constrainer1\":\n"
+ " {\n"
+ " \"type\": \"LinearConstrainer\",\n"
+ " \"value\": [ 0, 0, 0 ]\n"
+ " }\n"
+ " },\n"
+ " \"animations\": {\n"
+ " \"path-animation\": {\n"
+ " \"duration\": 3.0,\n"
+ " \"properties\":\n"
+ " [{\n"
+ " \"actor\": \"Image1\",\n"
+ " \"path\":\"path0\",\n"
+ " \"forward\":[1,0,0],\n"
+ " \"alpha-function\": \"EASE_IN_OUT\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 3\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"actor\": \"Image1\",\n"
+ " \"property\": \"uTime\",\n"
+ " \"value\": 10.0,\n"
+ " \"alpha-function\": \"LINEAR\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 10.0\n"
+ " },\n"
+ " \"gui-builder-timeline-color\": \"#8dc0da\"\n"
+ " }]\n"
+ " },\n"
+ " \"Animation_1\": {\n"
+ " \"loop\":true,\n"
+ " \"properties\": [\n"
+ " {\n"
+ " \"actor\": \"Image1\",\n"
+ " \"property\": \"uTime\",\n"
+ " \"value\": 10.0,\n"
+ " \"alpha-function\": \"LINEAR\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 10.0\n"
+ " },\n"
+ " \"gui-builder-timeline-color\": \"#8dc0da\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " },\n"
+ " \"shader-effects\": {\n"
+ " \"Ripple2D\": {\n"
+ " \"program\": {\n"
+ " \"vertexPrefix\": \"\",\n"
+ " \"vertex\": \"void main(void)\\n{\\n gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
+ " \"fragmentPrefix\": \"\",\n"
+ " \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n highp float len = length(pos);\\n highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+ " \"geometry-type\": \"GEOMETRY_TYPE_IMAGE\"\n"
+ " },\n"
+ " \"geometry-hints\": \"HINT_NONE\",\n"
+ " \"grid-density\": 0,\n"
+ " \"loop\": true,\n"
+ " \"uAmplitude\": 0.02,\n"
+ " \"uTime\": 0.0\n"
+ " }\n"
+ " }\n"
+ "}\n");
+
+ Builder builder = Builder::New();
+
+ // frame buffer coverage
+ builder.LoadFromString( json );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Dali::Path path = builder.GetPath( "path0" );
+ DALI_TEST_CHECK( path );
+
+ Dali::Path path2 = builder.GetPath( "path0" );
+ DALI_TEST_CHECK( path2 );
+ DALI_TEST_CHECK( path == path2 );
+
+ Dali::PathConstrainer constrainer0 = builder.GetPathConstrainer( "constrainer0" );
+ DALI_TEST_CHECK( constrainer0 );
+
+ Dali::PathConstrainer constrainer0_2 = builder.GetPathConstrainer( "constrainer0" );
+ DALI_TEST_CHECK( constrainer0_2 );
+ DALI_TEST_CHECK( constrainer0 == constrainer0_2 );
+
+ Dali::LinearConstrainer constrainer1 = builder.GetLinearConstrainer( "constrainer1" );
+ DALI_TEST_CHECK( constrainer1 );
+
+ Dali::LinearConstrainer constrainer1_2 = builder.GetLinearConstrainer( "constrainer1" );
+ DALI_TEST_CHECK( constrainer1 == constrainer1_2 );
+
+ END_TEST;
+}
Property::Map imageMap;
imageMap[ "filename" ] = "TestImage";
- Property::Map map;
- map[ "image" ] = imageMap;
- control.SetProperty( Control::Property::BACKGROUND_IMAGE, map );
+ control.SetProperty( Control::Property::BACKGROUND_IMAGE, imageMap );
DALI_TEST_CHECK( control.GetChildCount() > 0 );
DALI_TEST_EQUALS( control.GetBackgroundColor(), Color::RED, TEST_LOCATION );
DALI_TEST_EQUALS( control.GetProperty( Control::Property::BACKGROUND_COLOR ).Get< Vector4 >(), Color::RED, TEST_LOCATION );
Property::Value propValue = control.GetProperty( Control::Property::BACKGROUND_IMAGE );
- DALI_TEST_CHECK( propValue.HasKey( "image" ) );
- DALI_TEST_CHECK( propValue.GetValue( "image" ).HasKey( "filename" ) );
- DALI_TEST_CHECK( propValue.GetValue( "image" ).GetValue( "filename" ).Get< std::string>() == "TestImage" );
+ Property::Map* resultMap = propValue.GetMap();
+ DALI_TEST_CHECK( resultMap->Find( "filename" ) );
+ DALI_TEST_CHECK( resultMap->Find( "filename" )->Get< std::string>() == "TestImage" );
Property::Map emptyMap;
control.SetProperty( Control::Property::BACKGROUND_IMAGE, emptyMap );
--- /dev/null
+/*
+ * 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 <iostream>
+#include <stdlib.h>
+#include <sstream>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/effects-view/effects-view.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void dali_effectsview_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void dali_effectsview_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+int UtcDaliEffectsViewNew(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ DALI_TEST_CHECK( !view );
+
+ view = EffectsView::New();
+ DALI_TEST_CHECK( view );
+
+ Stage::GetCurrent().Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewCopyAndAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ DALI_TEST_CHECK( view );
+
+ EffectsView copy( view );
+ DALI_TEST_CHECK( copy == view );
+
+ EffectsView assign;
+ DALI_TEST_CHECK( !assign );
+ assign = view;
+ DALI_TEST_CHECK( assign == view );
+
+ // Self assignment
+ assign = assign;
+ DALI_TEST_CHECK( assign );
+ DALI_TEST_CHECK( assign == view );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewDownCast(void)
+{
+ ToolkitTestApplication application;
+
+ BaseHandle view = EffectsView::New();
+ DALI_TEST_CHECK( EffectsView::DownCast( view ) );
+
+ BaseHandle empty;
+ DALI_TEST_CHECK( ! EffectsView::DownCast( empty ) );
+
+ BaseHandle another = Actor::New();
+ DALI_TEST_CHECK( ! EffectsView::DownCast( another ) );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetGetTypeP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ DALI_TEST_CHECK( view.GetType() == EffectsView::INVALID_TYPE );
+
+ view.SetType( EffectsView::DROP_SHADOW );
+ DALI_TEST_CHECK( view.GetType() == EffectsView::DROP_SHADOW );
+
+ view.SetType( EffectsView::EMBOSS );
+ DALI_TEST_CHECK( view.GetType() == EffectsView::EMBOSS );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetTypeN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ view.SetType( EffectsView::DROP_SHADOW );
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetTypeN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ EffectsView::EffectType type = view.GetType();
+ (void) type;
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewEnableP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ Stage stage = Stage::GetCurrent();
+ DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
+
+ view.Enable();
+ DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() > 1 );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewEnableN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ view.Enable();
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewDisableP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ Stage stage = Stage::GetCurrent();
+ DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
+
+ view.Enable();
+ DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() > 1 );
+
+ view.Disable();
+ DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewDisableN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ view.Disable();
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewRefreshP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ try
+ {
+ view.Refresh();
+ DALI_TEST_CHECK( true );
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( false ); // Should not get here!
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewRefreshN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ view.Refresh();
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetPixelFormatP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ try
+ {
+ view.SetPixelFormat( Pixel::RGBA8888 );
+ DALI_TEST_CHECK( true );
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( false ); // Should not get here!
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetPixelFormatN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ view.SetPixelFormat( Pixel::RGBA8888 );
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetGetOutputImage(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ FrameBufferImage image = FrameBufferImage::New();
+ DALI_TEST_CHECK( image );
+
+ view.SetOutputImage( image );
+ DALI_TEST_CHECK( view.GetOutputImage() == image );
+
+ // Replace with another image
+ FrameBufferImage image2 = FrameBufferImage::New();
+ DALI_TEST_CHECK( image2 );
+ view.SetOutputImage( image2 );
+ DALI_TEST_CHECK( view.GetOutputImage() == image2 );
+
+ // Remove output image
+ view.SetOutputImage( FrameBufferImage() );
+ DALI_TEST_CHECK( ! view.GetOutputImage() );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetOutputImageN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ view.SetOutputImage( FrameBufferImage::New() );
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetOutputImageN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ FrameBufferImage image = view.GetOutputImage();
+ (void)image;
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectSizePropertyIndexP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectSizePropertyIndex() );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectSizePropertyIndexN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ Property::Index index = view.GetEffectSizePropertyIndex();
+ (void)index;
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectStrengthPropertyIndexP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectStrengthPropertyIndex() );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectStrengthPropertyIndexN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ Property::Index index = view.GetEffectStrengthPropertyIndex();
+ (void)index;
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectOffsetPropertyIndexP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectOffsetPropertyIndex() );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectOffsetPropertyIndexN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ Property::Index index = view.GetEffectOffsetPropertyIndex();
+ (void)index;
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectColorPropertyIndexP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectColorPropertyIndex() );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetEffectColorPropertyIndexN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ Property::Index index = view.GetEffectColorPropertyIndex();
+ (void)index;
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetSetBackgroundColor(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ view.SetBackgroundColor( Color::RED );
+ DALI_TEST_CHECK( Color::RED == view.GetBackgroundColor() );
+
+ view.SetBackgroundColor( Color::YELLOW );
+ DALI_TEST_CHECK( Color::YELLOW == view.GetBackgroundColor() );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetBackgroundColorN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ view.SetBackgroundColor( Color::RED );
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewGetBackgroundColorN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ Vector4 color = view.GetBackgroundColor();
+ (void)color;
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetRefreshOnDemandP(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view = EffectsView::New();
+ FrameBufferImage image = FrameBufferImage::New();
+ view.SetOutputImage( image );
+ view.Enable();
+
+ Stage stage = Stage::GetCurrent();
+ stage.Add( view );
+
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
+ DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
+
+ view.SetRefreshOnDemand( true );
+ DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ONCE );
+ DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ONCE );
+
+ view.SetRefreshOnDemand( false );
+ DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
+ DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSetRefreshOnDemandN(void)
+{
+ ToolkitTestApplication application;
+
+ EffectsView view;
+ try
+ {
+ view.SetRefreshOnDemand( false );
+ DALI_TEST_CHECK( false ); // Should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewSizeSet(void)
+{
+ ToolkitTestApplication application;
+ Stage stage = Stage::GetCurrent();
+
+ {
+ EffectsView view = EffectsView::New();
+ view.SetSize( 200.0f, 200.0f, 200.0f );
+ stage.Add( view );
+ view.Enable();
+ application.SendNotification();
+ application.Render();
+ view.Disable();
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetCurrentSize(), Vector3( 200.0f, 200.0f, 200.0f ), TEST_LOCATION );
+ }
+
+ {
+ EffectsView view = EffectsView::New();
+ view.SetOutputImage( FrameBufferImage::New( 200, 200 ) );
+ view.SetType( EffectsView::EMBOSS );
+ view.SetSize( 200.0f, 200.0f, 200.0f );
+ stage.Add( view );
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetCurrentSize(), Vector3( 200.0f, 200.0f, 200.0f ), TEST_LOCATION );
+ }
+
+ {
+ EffectsView view = EffectsView::New();
+ view.SetType( EffectsView::DROP_SHADOW );
+ view.SetSize( 200.0f, 200.0f, 200.0f );
+ stage.Add( view );
+ application.SendNotification();
+ application.Render();
+
+ stage.Remove( view );
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetCurrentSize(), Vector3( 200.0f, 200.0f, 200.0f ), TEST_LOCATION );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliEffectsViewTypeRegistry(void)
+{
+ ToolkitTestApplication application;
+
+ TypeRegistry typeRegistry = TypeRegistry::Get();
+ DALI_TEST_CHECK( typeRegistry );
+
+ TypeInfo typeInfo = typeRegistry.GetTypeInfo( "EffectsView" );
+ DALI_TEST_CHECK( typeInfo );
+
+ BaseHandle handle = typeInfo.CreateInstance();
+ DALI_TEST_CHECK( handle );
+
+ EffectsView view = EffectsView::DownCast( handle );
+ DALI_TEST_CHECK( view );
+
+ END_TEST;
+}
namespace
{
+
const unsigned int TOTAL_ITEM_NUMBER = 100;
const char* TEST_IMAGE_FILE_NAME = "gallery_image_01.jpg";
+const int RENDER_FRAME_INTERVAL = 16; ///< Duration of each frame in ms. (at approx 60FPS)
+
static bool gObjectCreatedCallBackCalled;
+static bool gOnLayoutActivatedCalled; ///< Whether the LayoutActivated signal was invoked.
static void TestCallback(BaseHandle handle)
{
gObjectCreatedCallBackCalled = true;
}
+static void OnLayoutActivated()
+{
+ gOnLayoutActivatedCalled = true;
+}
+
+/*
+ * Simulate time passed by.
+ *
+ * @note this will always process at least 1 frame (1/60 sec)
+ *
+ * @param application Test application instance
+ * @param duration Time to pass in milliseconds.
+ * @return The actual time passed in milliseconds
+ */
+int Wait(ToolkitTestApplication& application, int duration = 0)
+{
+ int time = 0;
+
+ for(int i = 0; i <= ( duration / RENDER_FRAME_INTERVAL); i++)
+ {
+ application.SendNotification();
+ application.Render(RENDER_FRAME_INTERVAL);
+ time += RENDER_FRAME_INTERVAL;
+ }
+
+ return time;
+}
// Implementation of ItemFactory for providing actors to ItemView
class TestItemFactory : public ItemFactory
DALI_TEST_CHECK( factory.GetExtension() == NULL );
END_TEST;
}
+
+int UtcDaliItemViewLayoutActivatedSignalP(void)
+{
+ ToolkitTestApplication application;
+
+ // Create the ItemView actor
+ TestItemFactory factory;
+ ItemView view = ItemView::New(factory);
+
+ // Create a grid layout and add it to ItemView
+ ItemLayoutPtr gridLayout = DefaultItemLayout::New( DefaultItemLayout::GRID );
+ view.AddLayout(*gridLayout);
+
+ Stage::GetCurrent().Add( view );
+
+ // Connect the layout activated signal
+ view.LayoutActivatedSignal().Connect( &OnLayoutActivated );
+
+ gOnLayoutActivatedCalled = false;
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Activate the grid layout so that the items will be created and added to ItemView
+ Vector3 stageSize(Dali::Stage::GetCurrent().GetSize());
+ view.ActivateLayout(0, stageSize, 0.1f);
+
+ // Wait for 0.1 second
+ Wait(application, 100);
+
+ DALI_TEST_EQUALS( gOnLayoutActivatedCalled, true, TEST_LOCATION );
+
+ END_TEST;
+}
--- /dev/null
+/*
+ * 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 <iostream>
+#include <stdlib.h>
+#include <sstream>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/magnifier/magnifier.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void dali_magnifier_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void dali_magnifier_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+int UtcDaliMagnifierNew(void)
+{
+ ToolkitTestApplication application;
+
+ Magnifier magnifier;
+ DALI_TEST_CHECK( !magnifier );
+
+ magnifier = Magnifier::New();
+ DALI_TEST_CHECK( magnifier );
+
+ Stage::GetCurrent().Add( magnifier );
+
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierCopyAndAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ Magnifier view = Magnifier::New();
+ DALI_TEST_CHECK( view );
+
+ Magnifier copy( view );
+ DALI_TEST_CHECK( copy == view );
+
+ Magnifier assign;
+ DALI_TEST_CHECK( !assign );
+ assign = view;
+ DALI_TEST_CHECK( assign == view );
+
+ // Self assignment
+ assign = assign;
+ DALI_TEST_CHECK( assign );
+ DALI_TEST_CHECK( assign == view );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierDownCast(void)
+{
+ ToolkitTestApplication application;
+
+ BaseHandle view = Magnifier::New();
+ DALI_TEST_CHECK( Magnifier::DownCast( view ) );
+
+ BaseHandle empty;
+ DALI_TEST_CHECK( ! Magnifier::DownCast( empty ) );
+
+ BaseHandle another = Actor::New();
+ DALI_TEST_CHECK( ! Magnifier::DownCast( another ) );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierTypeRegistry(void)
+{
+ ToolkitTestApplication application;
+
+ TypeRegistry typeRegistry = TypeRegistry::Get();
+ DALI_TEST_CHECK( typeRegistry );
+
+ TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Magnifier" );
+ DALI_TEST_CHECK( typeInfo );
+
+ BaseHandle handle = typeInfo.CreateInstance();
+ DALI_TEST_CHECK( handle );
+
+ Magnifier view = Magnifier::DownCast( handle );
+ DALI_TEST_CHECK( view );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierSetSourceActorP(void)
+{
+ ToolkitTestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+
+ Magnifier view = Magnifier::New();
+ stage.Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ DALI_TEST_CHECK( renderTaskList.GetTaskCount() > 1 );
+
+ Actor actor = Actor::New();
+ stage.Add( actor );
+ DALI_TEST_CHECK( stage.GetRenderTaskList().GetTask( 1 ).GetSourceActor() != actor );
+
+ view.SetSourceActor( actor );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( stage.GetRenderTaskList().GetTask( 1 ).GetSourceActor(), actor, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierSetSourceActorN(void)
+{
+ ToolkitTestApplication application;
+
+ Magnifier view;
+
+ try
+ {
+ view.SetSourceActor( Actor::New() );
+ DALI_TEST_CHECK( false ); // should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierFrameVisibility(void)
+{
+ ToolkitTestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+
+ Magnifier view = Magnifier::New();
+ stage.Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), true, TEST_LOCATION );
+
+ view.SetProperty( Magnifier::Property::FRAME_VISIBILITY, false );
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), false, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), false, TEST_LOCATION );
+
+ view.SetProperty( Magnifier::Property::FRAME_VISIBILITY, true );
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), true, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierMagnificationFactor(void)
+{
+ ToolkitTestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+
+ Magnifier view = Magnifier::New();
+ stage.Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ float magnificationFactor( 200.0f );
+
+ DALI_TEST_CHECK( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >() != magnificationFactor );
+
+ view.SetProperty( Magnifier::Property::MAGNIFICATION_FACTOR, magnificationFactor );
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >(), magnificationFactor, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >(), magnificationFactor, TEST_LOCATION );
+
+ view.SetProperty( Magnifier::Property::MAGNIFICATION_FACTOR, 1.0f );
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >(), 1.0f, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >(), 1.0f, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierSourcePosition(void)
+{
+ ToolkitTestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+
+ Magnifier view = Magnifier::New();
+ stage.Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ Vector3 position( 100.0f, 200.0f, 300.0f );
+
+ DALI_TEST_CHECK( view.GetProperty( Magnifier::Property::SOURCE_POSITION ).Get< Vector3 >() != position );
+
+ view.SetProperty( Magnifier::Property::SOURCE_POSITION, position );
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::SOURCE_POSITION ).Get< Vector3 >(), position, TEST_LOCATION );
+
+ view.SetProperty( Magnifier::Property::SOURCE_POSITION, Vector3::ONE );
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::SOURCE_POSITION ).Get< Vector3 >(), Vector3::ONE, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierOnSizeSet(void)
+{
+ ToolkitTestApplication application;
+
+ Magnifier view = Magnifier::New();
+
+ Stage::GetCurrent().Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ Vector3 size( 200.0f, 300.0f, 200.0f );
+ view.SetSize( size );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetCurrentSize(), size, TEST_LOCATION );
+
+ END_TEST;
+}
#include <iostream>
#include <stdlib.h>
+#include <sstream>
#include <dali-toolkit-test-suite-utils.h>
#include <dali-toolkit/dali-toolkit.h>
Property::Map layoutRowsGet = tableView.GetProperty(TableView::Property::LAYOUT_ROWS).Get<Property::Map>();
DALI_TEST_EQUALS( layoutRowsGet.GetKey(1).compare(layoutRows.GetKey(0)), 0, TEST_LOCATION );
- DALI_TEST_CHECK( layoutRowsGet.GetValue(1).GetValue( "policy" ).Get<std::string>().compare(layoutRows.GetValue(0).GetValue( "policy" ).Get<std::string>()) == 0 );
- DALI_TEST_EQUALS( layoutRowsGet.GetValue(1).GetValue( "value" ).Get<float>(), layoutRows.GetValue(0).GetValue( "value" ).Get<float>(), TEST_LOCATION );
+ Property::Map* childMap =layoutRowsGet.GetValue(1).GetMap();
+ DALI_TEST_CHECK( childMap->Find( "policy" )->Get<std::string>().compare("fixed") == 0 );
+ DALI_TEST_EQUALS( childMap->Find( "value" )->Get<float>(), 30.f, TEST_LOCATION );
+ childMap =layoutRowsGet.GetValue(3).GetMap();
DALI_TEST_CHECK( layoutRowsGet.GetKey(3).compare(layoutRows.GetKey(1)) == 0 );
- DALI_TEST_CHECK( layoutRowsGet.GetValue(3).GetValue( "policy" ).Get<std::string>().compare(layoutRows.GetValue(1).GetValue( "policy" ).Get<std::string>()) == 0 );
- DALI_TEST_EQUALS( layoutRowsGet.GetValue(3).GetValue( "value" ).Get<float>(), layoutRows.GetValue(1).GetValue( "value" ).Get<float>(), TEST_LOCATION );
+ DALI_TEST_CHECK( childMap->Find( "policy" )->Get<std::string>().compare("relative") == 0 );
+ DALI_TEST_EQUALS( childMap->Find( "value" )->Get<float>(), 0.2f, TEST_LOCATION );
// Test "layout-columns" property
DALI_TEST_CHECK( tableView.GetPropertyIndex( PROPERTY_NAME_LAYOUT_COLUMNS ) == TableView::Property::LAYOUT_COLUMNS );
Property::Map layoutColumnsGet = tableView.GetProperty(TableView::Property::LAYOUT_COLUMNS).Get<Property::Map>();
DALI_TEST_CHECK( layoutColumnsGet.GetKey(2).compare(layoutColumns.GetKey(0)) == 0 );
- DALI_TEST_CHECK( layoutColumnsGet.GetValue(2).GetValue( "policy" ).Get<std::string>().compare(layoutColumns.GetValue(0).GetValue( "policy" ).Get<std::string>()) == 0 );
- DALI_TEST_EQUALS( layoutColumnsGet.GetValue(2).GetValue( "value" ).Get<float>(),layoutColumns.GetValue(0).GetValue( "value" ).Get<float>(), TEST_LOCATION );
-
+ childMap =layoutColumnsGet.GetValue(2).GetMap();
+ DALI_TEST_CHECK( childMap->Find( "policy" )->Get<std::string>().compare("relative") == 0 );
+ DALI_TEST_EQUALS( childMap->Find( "value" )->Get<float>(), 0.2f, TEST_LOCATION );
+ childMap =layoutColumnsGet.GetValue(3).GetMap();
DALI_TEST_CHECK( layoutColumnsGet.GetKey(3).compare(layoutColumns.GetKey(1)) == 0 );
- DALI_TEST_CHECK( layoutColumnsGet.GetValue(3).GetValue( "policy" ).Get<std::string>().compare(layoutColumns.GetValue(1).GetValue( "policy" ).Get<std::string>()) == 0 );
- DALI_TEST_EQUALS( layoutColumnsGet.GetValue(3).GetValue( "value" ).Get<float>(),layoutColumns.GetValue(1).GetValue( "value" ).Get<float>(), TEST_LOCATION );
+ DALI_TEST_CHECK( childMap->Find( "policy" )->Get<std::string>().compare("fixed") == 0 );
+ DALI_TEST_EQUALS( childMap->Find( "value" )->Get<float>(),30.f, TEST_LOCATION );
END_TEST;
}
// Create a 10x10 table-view
TableView tableView = TableView::New(10,10);
- Constraint constraint = Constraint::New<Vector3>( tableView, Actor::Property::SIZE, Constraint100() );
- constraint.Apply();
+ Stage::GetCurrent().Add( tableView );
+ tableView.SetSize( Dali::Vector2( 100.0f, 100.0f ) );
+
DALI_TEST_CHECK( tableView );
// Create a child actor with the custom properties
Actor child1 = Actor::New();
- child1.RegisterProperty( TableView::CELL_INDICES_PROPERTY_NAME, Vector2( 3, 4 ) );
+ child1.RegisterProperty( "cell-index", Vector2( 3, 4 ), Property::READ_WRITE );
tableView.Add( child1 );
// Check for actors at actual positions.
DALI_TEST_CHECK( tableView.GetChildAt(TableView::CellPosition(3,4)) == child1);
Actor child2 = Actor::New();
float rowSpan = 3.f;
float columnSpan = 2.f;
- child2.RegisterProperty( TableView::CELL_INDICES_PROPERTY_NAME, Vector2( 6, 1 ) );
- child2.RegisterProperty( TableView::ROW_SPAN_PROPERTY_NAME, rowSpan );
- child2.RegisterProperty( TableView::COLUMN_SPAN_PROPERTY_NAME, columnSpan );
+ child2.RegisterProperty( "cell-index", Vector2( 6, 1 ), Property::READ_WRITE );
+ child2.RegisterProperty( "row-span", rowSpan, Property::READ_WRITE );
+ child2.RegisterProperty( "column-span", columnSpan, Property::READ_WRITE );
tableView.Add( child2 );
// Check for actors at actual positions.
for( int i=0; i<rowSpan; i++ )
}
}
+ // Create a third child actor with the cell alignment properties
+ Actor child3 = Actor::New();
+ child3.SetSize( 5.f,5.f );
+ child3.RegisterProperty( "cell-horizontal-alignment", "center", Property::READ_WRITE );
+ child3.RegisterProperty( "cell-vertical-alignment", "bottom", Property::READ_WRITE );
+ tableView.Add( child3 );
+
+ // store the actor in the first available cell
+ DALI_TEST_CHECK( tableView.GetChildAt(TableView::CellPosition(0,0)) == child3)
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( child3.GetCurrentAnchorPoint(), AnchorPoint::TOP_LEFT, TEST_LOCATION );
+ DALI_TEST_EQUALS( child3.GetCurrentParentOrigin(), ParentOrigin::TOP_LEFT, TEST_LOCATION );
+ DALI_TEST_EQUALS( child3.GetCurrentPosition(), Vector3(2.5f, 5.0f, 0.0f), TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliTableViewGetChildAtN(void)
+{
+ ToolkitTestApplication application;
+
+ TableView tableView = TableView::New(10,10);
+
+ Actor actor = tableView.GetChildAt( TableView::CellPosition( 200, 200 ) );
+ DALI_TEST_CHECK( !actor );
+
+ END_TEST;
+}
+
+int UtcDaliTableViewAddChildN(void)
+{
+ ToolkitTestApplication application;
+
+ TableView tableView = TableView::New(10,10);
+ DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 ) ) );
+ DALI_TEST_CHECK( ! tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 ) ) );
+
+ END_TEST;
+}
+
+int UtcDaliTableViewInsertRowAtZero(void)
+{
+ ToolkitTestApplication application;
+
+ TableView tableView = TableView::New(10,10);
+ DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 , 10, 10 ) ) );
+ tableView.InsertRow(0);
+
+ DALI_TEST_CHECK( tableView.GetRows() == 11 );
+
+ END_TEST;
+}
+
+int UtcDaliTableViewDeleteRowAtZero(void)
+{
+ ToolkitTestApplication application;
+
+ TableView tableView = TableView::New(10,10);
+ DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 , 10, 10 ) ) );
+ tableView.DeleteRow(0);
+
+ DALI_TEST_CHECK( tableView.GetRows() == 9 );
+
+ END_TEST;
+}
+
+int UtcDaliTableViewInsertColumnAtZero(void)
+{
+ ToolkitTestApplication application;
+
+ TableView tableView = TableView::New(10,10);
+ DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 , 10, 10 ) ) );
+ tableView.InsertColumn(0);
+
+ DALI_TEST_CHECK( tableView.GetColumns() == 11 );
+
+ END_TEST;
+}
+
+int UtcDaliTableViewDeleteColumnAtZero(void)
+{
+ ToolkitTestApplication application;
+
+ TableView tableView = TableView::New(10,10);
+ DALI_TEST_CHECK( tableView.AddChild( Actor::New(), TableView::CellPosition( 0, 0 , 10, 10 ) ) );
+ tableView.DeleteColumn(0);
+
+ DALI_TEST_CHECK( tableView.GetColumns() == 9 );
+
+ END_TEST;
+}
+
+int UtcDaliTableViewTypeRegistry(void)
+{
+ ToolkitTestApplication application;
+
+ TypeRegistry typeRegistry = TypeRegistry::Get();
+ DALI_TEST_CHECK( typeRegistry );
+
+ TypeInfo typeInfo = typeRegistry.GetTypeInfo( "TableView" );
+ DALI_TEST_CHECK( typeInfo );
+
+ BaseHandle handle = typeInfo.CreateInstance();
+ DALI_TEST_CHECK( handle );
+
+ TableView view = TableView::DownCast( handle );
+ DALI_TEST_CHECK( view );
+
+ END_TEST;
+}
+
+int UtcDaliTableViewKeyboardFocus(void)
+{
+ ToolkitTestApplication application;
+
+ TableView tableView = TableView::New(4,4);
+ tableView.SetKeyboardFocusable( true );
+ tableView.SetName( "TableView");
+
+ for ( int row = 0; row < 4; ++row )
+ {
+ for ( int col = 0; col < 4; ++col )
+ {
+ Control control = Control::New();
+ std::ostringstream str;
+ str << row << "-" << col;
+ control.SetName( str.str() );
+ control.SetKeyboardFocusable( true );
+ tableView.AddChild( control, TableView::CellPosition( row, col ) );
+ }
+ }
+
+ Stage::GetCurrent().Add( tableView );
+
+ application.SendNotification();
+ application.Render();
+
+ Actor firstFocusActor = Toolkit::Internal::GetImplementation( tableView ).GetNextKeyboardFocusableActor( Actor(), Control::KeyboardFocus::RIGHT, true );
+ DALI_TEST_CHECK( firstFocusActor );
+ DALI_TEST_CHECK( firstFocusActor.GetName() == "0-0" );
+
+ KeyboardFocusManager manager = KeyboardFocusManager::Get();
+ manager.SetFocusGroupLoop( true );
+ manager.SetCurrentFocusActor( firstFocusActor );
+
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-0" );
+ manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+ manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-2" );
+ manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-3" );
+ manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-0" );
+
+ manager.MoveFocus( Control::KeyboardFocus::LEFT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-3" );
+ manager.MoveFocus( Control::KeyboardFocus::LEFT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-2" );
+ manager.MoveFocus( Control::KeyboardFocus::LEFT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+ manager.MoveFocus( Control::KeyboardFocus::LEFT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-0" );
+ manager.MoveFocus( Control::KeyboardFocus::LEFT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "3-3" );
+
+ manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-0" );
+ manager.MoveFocus( Control::KeyboardFocus::RIGHT );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+
+ manager.MoveFocus( Control::KeyboardFocus::DOWN );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1" );
+ manager.MoveFocus( Control::KeyboardFocus::DOWN );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-1" );
+ manager.MoveFocus( Control::KeyboardFocus::DOWN );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "3-1" );
+ manager.MoveFocus( Control::KeyboardFocus::DOWN );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+
+ manager.MoveFocus( Control::KeyboardFocus::UP );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "3-1" );
+ manager.MoveFocus( Control::KeyboardFocus::UP );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "2-1" );
+ manager.MoveFocus( Control::KeyboardFocus::UP );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "1-1" );
+ manager.MoveFocus( Control::KeyboardFocus::UP );
+ DALI_TEST_CHECK( manager.GetCurrentFocusActor().GetName() == "0-1" );
+
END_TEST;
}
#include <iostream>
#include <stdlib.h>
#include <dali/integration-api/events/key-event-integ.h>
+#include <dali/integration-api/events/tap-gesture-event.h>
#include <dali-toolkit-test-suite-utils.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/styling/style-manager.h>
namespace
{
-const char* const PROPERTY_NAME_RENDERING_BACKEND = "rendering-backend";
-const char* const PROPERTY_NAME_PLACEHOLDER_TEXT = "placeholder-text";
-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_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";
+const char* const PROPERTY_NAME_RENDERING_BACKEND = "rendering-backend";
+const char* const PROPERTY_NAME_TEXT = "text";
+const char* const PROPERTY_NAME_PLACEHOLDER_TEXT = "placeholder-text";
+const char* const PROPERTY_NAME_PLACEHOLDER_TEXT_FOCUSED = "placeholder-text-focused";
+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_MAX_LENGTH = "max-length";
+const char* const PROPERTY_NAME_EXCEED_POLICY = "exceed-policy";
+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_PLACEHOLDER_TEXT_COLOR = "placeholder-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_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_GRAB_HANDLE_PRESSED_IMAGE = "grab-handle-pressed-image";
+const char* const PROPERTY_NAME_SCROLL_THRESHOLD = "scroll-threshold";
+const char* const PROPERTY_NAME_SCROLL_SPEED = "scroll-speed";
+const char* const PROPERTY_NAME_SELECTION_HANDLE_IMAGE_LEFT = "selection-handle-image-left";
+const char* const PROPERTY_NAME_SELECTION_HANDLE_IMAGE_RIGHT = "selection-handle-image-right";
+const char* const PROPERTY_NAME_SELECTION_HANDLE_PRESSED_IMAGE_LEFT = "selection-handle-pressed-image-left";
+const char* const PROPERTY_NAME_SELECTION_HANDLE_PRESSED_IMAGE_RIGHT = "selection-handle-pressed-image-right";
+const char* const PROPERTY_NAME_SELECTION_HIGHLIGHT_COLOR = "selection-highlight-color";
+const char* const PROPERTY_NAME_DECORATION_BOUNDING_BOX = "decoration-bounding-box";
+const char* const PROPERTY_NAME_INPUT_METHOD_SETTINGS = "input-method-settings";
+
+const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
+
+const Vector4 PLACEHOLDER_TEXT_COLOR( 0.8f, 0.8f, 0.8f, 0.8f );
+const Dali::Vector4 LIGHT_BLUE( (0xb2 / 255.0f), (0xeb / 255.0f), (0xf2 / 255.0f), 0.5f ); // The text highlight color.
+
+const unsigned int CURSOR_BLINK_INTERVAL = 500u; // Cursor blink interval
+const float TO_MILLISECONDS = 1000.f;
+const float TO_SECONDS = 1.f / TO_MILLISECONDS;
+
+const float SCROLL_THRESHOLD = 10.f;
+const float SCROLL_SPEED = 300.f;
static bool gTextChangedCallBackCalled;
static bool gMaxCharactersCallBackCalled;
gMaxCharactersCallBackCalled = true;
}
+// Generate a TapGestureEvent to send to Core.
+Integration::TapGestureEvent GenerateTap(
+ Gesture::State state,
+ unsigned int numberOfTaps,
+ unsigned int numberOfTouches,
+ Vector2 point)
+{
+ Integration::TapGestureEvent tap( state );
+
+ tap.numberOfTaps = numberOfTaps;
+ tap.numberOfTouches = numberOfTouches;
+ tap.point = point;
+
+ return tap;
+}
+
+// Generate a KeyEvent to send to Core.
+Integration::KeyEvent GenerateKey( const std::string& keyName,
+ const std::string& keyString,
+ int keyCode,
+ int keyModifier,
+ unsigned long timeStamp,
+ const Integration::KeyEvent::State& keyState )
+{
+ return Integration::KeyEvent( keyName,
+ keyString,
+ keyCode,
+ keyModifier,
+ timeStamp,
+ keyState );
+}
+
} // namespace
int UtcDaliToolkitTextFieldConstructorP(void)
END_TEST;
}
-int UtcDaliTextFieldGetPropertyN(void)
-{
- ToolkitTestApplication application;
- tet_infoline(" UtcDaliToolkitTextFieldGetPropertyN");
- TextField field = TextField::New();
- DALI_TEST_CHECK( field );
-
- bool assert = false;
- try
- {
- Property::Value value = field.GetProperty<bool>( 0 );
- }
- catch ( ... )
- {
- assert = true;
- }
- if ( assert )
- {
- tet_result(TET_PASS);
- }
- else
- {
- tet_result(TET_FAIL);
- }
- END_TEST;
-}
-
// Positive test case for a method
int UtcDaliTextFieldGetPropertyP(void)
{
// 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_TEXT ) == TextField::Property::TEXT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER_TEXT ) == TextField::Property::PLACEHOLDER_TEXT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER_TEXT_FOCUSED ) == TextField::Property::PLACEHOLDER_TEXT_FOCUSED );
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_MAX_LENGTH ) == TextField::Property::MAX_LENGTH );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_EXCEED_POLICY ) == TextField::Property::EXCEED_POLICY );
+ 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 );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_TEXT_COLOR ) == TextField::Property::TEXT_COLOR );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER_TEXT_COLOR ) == TextField::Property::PLACEHOLDER_TEXT_COLOR );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SHADOW_OFFSET ) == TextField::Property::SHADOW_OFFSET );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SHADOW_COLOR ) == TextField::Property::SHADOW_COLOR );
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_GRAB_HANDLE_PRESSED_IMAGE ) == TextField::Property::GRAB_HANDLE_PRESSED_IMAGE );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SCROLL_THRESHOLD ) == TextField::Property::SCROLL_THRESHOLD );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SCROLL_SPEED ) == TextField::Property::SCROLL_SPEED );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HANDLE_IMAGE_LEFT ) == TextField::Property::SELECTION_HANDLE_IMAGE_LEFT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HANDLE_IMAGE_RIGHT ) == TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HANDLE_PRESSED_IMAGE_LEFT ) == TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HANDLE_PRESSED_IMAGE_RIGHT ) == TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HIGHLIGHT_COLOR ) == TextField::Property::SELECTION_HIGHLIGHT_COLOR );
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 );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_METHOD_SETTINGS ) == TextField::Property::INPUT_METHOD_SETTINGS );
END_TEST;
}
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- // Check exceed policy
- field.SetProperty( TextField::Property::EXCEED_POLICY, TextField::EXCEED_POLICY_CLIP );
+ // Check defaults.
+ DALI_TEST_EQUALS( field.GetProperty<unsigned int>( TextField::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::PLACEHOLDER_TEXT ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::PLACEHOLDER_TEXT_FOCUSED ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::FONT_FAMILY ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::FONT_STYLE ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::POINT_SIZE ), 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<int>( TextField::Property::MAX_LENGTH ), 50u, TEST_LOCATION );
DALI_TEST_EQUALS( field.GetProperty<int>( 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<std::string>( TextField::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector2>( TextField::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PLACEHOLDER_TEXT_COLOR ), PLACEHOLDER_TEXT_COLOR, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLACK, TEST_LOCATION );
DALI_TEST_EQUALS( field.GetProperty<bool>( TextField::Property::ENABLE_CURSOR_BLINK ), true, TEST_LOCATION );
- field.SetProperty( TextField::Property::PRIMARY_CURSOR_COLOR, Color::RED );
- DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::RED, TEST_LOCATION );
- field.SetProperty( TextField::Property::SECONDARY_CURSOR_COLOR, Color::BLUE );
- DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLUE, TEST_LOCATION );
- field.SetProperty( TextField::Property::CURSOR_BLINK_DURATION, 10.0f );
- DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_DURATION ), 10.0f, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_INTERVAL ), CURSOR_BLINK_INTERVAL * TO_SECONDS, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_DURATION ), 0.f, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::SCROLL_THRESHOLD ), SCROLL_THRESHOLD, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::SCROLL_SPEED ), SCROLL_SPEED, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SELECTION_HIGHLIGHT_COLOR ), LIGHT_BLUE, TEST_LOCATION );
- // Blink interval
- field.SetProperty( TextField::Property::CURSOR_BLINK_INTERVAL, 1.0f );
- DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_INTERVAL ), 1.0f, TEST_LOCATION );
+ // Check the render backend property.
+ field.SetProperty( TextField::Property::RENDERING_BACKEND, Text::RENDERING_BASIC );
+ DALI_TEST_EQUALS( field.GetProperty<unsigned int>( TextField::Property::RENDERING_BACKEND ), Text::RENDERING_BASIC, TEST_LOCATION );
- // Decoration bounding box
- field.SetProperty( TextField::Property::DECORATION_BOUNDING_BOX, Rect<int>( 0, 0, 1, 1 ) );
- DALI_TEST_EQUALS( field.GetProperty<Rect <int > >( TextField::Property::DECORATION_BOUNDING_BOX ), Rect<int>( 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<std::string>( TextField::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION );
- field.SetProperty( TextField::Property::VERTICAL_ALIGNMENT, "CENTER" );
- DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::VERTICAL_ALIGNMENT ), "CENTER", TEST_LOCATION );
-
- // Set text
+ // Check text property.
field.SetProperty( TextField::Property::TEXT, "Setting Text" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string("Setting Text"), TEST_LOCATION );
+
+ // Check placeholder text properties.
+ field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "Setting Placeholder Text" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::PLACEHOLDER_TEXT ), std::string("Setting Placeholder Text"), TEST_LOCATION );
- // Set placeholder text (currently not implemented)
- field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "Setting Text" );
+ field.SetProperty( TextField::Property::PLACEHOLDER_TEXT_FOCUSED, "Setting Placeholder Text Focused" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::PLACEHOLDER_TEXT_FOCUSED ), std::string("Setting Placeholder Text Focused"), TEST_LOCATION );
- // Set Grab Handle image
- field.SetProperty( TextField::Property::GRAB_HANDLE_IMAGE, "" );
+ // Check font properties.
+ field.SetProperty( TextField::Property::FONT_FAMILY, "Setting font family" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::FONT_FAMILY ), std::string("Setting font family"), TEST_LOCATION );
+ field.SetProperty( TextField::Property::FONT_STYLE, "Setting font style" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::FONT_STYLE ), std::string("Setting font style"), TEST_LOCATION );
+ field.SetProperty( TextField::Property::POINT_SIZE, 10.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::POINT_SIZE ), 10.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
// Check that the MAX_LENGTH property can be correctly set
const int maxNumberOfCharacters = 20;
field.SetProperty( TextField::Property::MAX_LENGTH, maxNumberOfCharacters );
DALI_TEST_EQUALS( field.GetProperty<int>( TextField::Property::MAX_LENGTH ), maxNumberOfCharacters, TEST_LOCATION );
- END_TEST;
-}
+ // Check exceed policy
+ // Set a different exceed policy is not implemented.
-// Negative test case for a method
-int UtcDaliTextFieldSetPropertyN(void)
-{
- ToolkitTestApplication application;
- tet_infoline(" UtcDaliToolkitTextFieldSetPropertyN");
- TextField field = TextField::New();
- DALI_TEST_CHECK( field );
+ // Check that the Alignment properties can be correctly set
+ field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "END" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::HORIZONTAL_ALIGNMENT ), "END", TEST_LOCATION );
+ field.SetProperty( TextField::Property::VERTICAL_ALIGNMENT, "CENTER" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::VERTICAL_ALIGNMENT ), "CENTER", TEST_LOCATION );
+
+ // Check text's color property
+ field.SetProperty( TextField::Property::TEXT_COLOR, Color::WHITE );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::TEXT_COLOR ), Color::WHITE, TEST_LOCATION );
+
+ // Check placeholder text's color property.
+ field.SetProperty( TextField::Property::PLACEHOLDER_TEXT_COLOR, Color::RED );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PLACEHOLDER_TEXT_COLOR ), Color::RED, TEST_LOCATION );
+
+ // Check shadow properties.
+ field.SetProperty( TextField::Property::SHADOW_OFFSET, Vector2( 1.f, 1.f ) );
+ DALI_TEST_EQUALS( field.GetProperty<Vector2>( TextField::Property::SHADOW_OFFSET ), Vector2( 1.f, 1.f ), TEST_LOCATION );
+ field.SetProperty( TextField::Property::SHADOW_COLOR, Color::GREEN );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SHADOW_COLOR ), Color::GREEN, TEST_LOCATION );
+
+ // Check cursor properties
+ field.SetProperty( TextField::Property::PRIMARY_CURSOR_COLOR, Color::RED );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::RED, TEST_LOCATION );
+ field.SetProperty( TextField::Property::SECONDARY_CURSOR_COLOR, Color::BLUE );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLUE, TEST_LOCATION );
+
+ field.SetProperty( TextField::Property::ENABLE_CURSOR_BLINK, false );
+ DALI_TEST_EQUALS( field.GetProperty<bool>( TextField::Property::ENABLE_CURSOR_BLINK ), false, TEST_LOCATION );
+ field.SetProperty( TextField::Property::CURSOR_BLINK_INTERVAL, 1.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_INTERVAL ), 1.f, TEST_LOCATION );
+ field.SetProperty( TextField::Property::CURSOR_BLINK_DURATION, 10.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_DURATION ), 10.f, TEST_LOCATION );
+
+ // Check scroll properties.
+ field.SetProperty( TextField::Property::SCROLL_THRESHOLD, 1.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::SCROLL_THRESHOLD ), 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ field.SetProperty( TextField::Property::SCROLL_SPEED, 100.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::SCROLL_SPEED ), 100.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ // Check handle images
+ field.SetProperty( TextField::Property::GRAB_HANDLE_IMAGE, "image1" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::GRAB_HANDLE_IMAGE ), "image1", TEST_LOCATION );
+ field.SetProperty( TextField::Property::GRAB_HANDLE_PRESSED_IMAGE, "image2" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::GRAB_HANDLE_PRESSED_IMAGE ), "image2", TEST_LOCATION );
+ field.SetProperty( TextField::Property::SELECTION_HANDLE_IMAGE_LEFT, "image3" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SELECTION_HANDLE_IMAGE_LEFT ), "image3", TEST_LOCATION );
+ field.SetProperty( TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT, "image4" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT ), "image4", TEST_LOCATION );
+ field.SetProperty( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT, "image5" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT ), "image5", TEST_LOCATION );
+ field.SetProperty( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT, "image6" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT ), "image6", TEST_LOCATION );
+
+ // Check the highlight color
+ field.SetProperty( TextField::Property::SELECTION_HIGHLIGHT_COLOR, Color::GREEN );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SELECTION_HIGHLIGHT_COLOR ), Color::GREEN, TEST_LOCATION );
+
+ // Decoration bounding box
+ field.SetProperty( TextField::Property::DECORATION_BOUNDING_BOX, Rect<int>( 0, 0, 1, 1 ) );
+ DALI_TEST_EQUALS( field.GetProperty<Rect <int > >( TextField::Property::DECORATION_BOUNDING_BOX ), Rect<int>( 0, 0, 1, 1 ), TEST_LOCATION );
- bool assert = false;
- try
- {
- field.SetProperty( 0, true );
- }
- catch ( ... )
- {
- assert = true;
- }
- if ( assert )
- {
- tet_result(TET_PASS);
- }
- else
- {
- tet_result(TET_FAIL);
- }
END_TEST;
}
field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "BEGIN" );
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ Stage::GetCurrent().Add( field );
+
try
{
// Render some text with the basic backend
DALI_TEST_CHECK( field );
field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
+
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ Stage::GetCurrent().Add( field );
+
try
{
// Render some text with the shared atlas backend
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- Stage::GetCurrent().Add(field);
+ Stage::GetCurrent().Add( field );
field.TextChangedSignal().Connect(&TestTextChangedCallback);
field.SetKeyInputFocus();
- Dali::Integration::KeyEvent keyevent;
- keyevent.keyName = "D";
- keyevent.keyString = "D";
- keyevent.keyCode = 0;
- keyevent.keyModifier = 0;
- keyevent.time = 0;
- keyevent.state = Integration::KeyEvent::Down;
-
gTextChangedCallBackCalled = false;
- application.ProcessEvent( keyevent );
+ application.ProcessEvent( GenerateKey( "D", "D", 0, 0, 0, Integration::KeyEvent::Down ) );
DALI_TEST_CHECK( gTextChangedCallBackCalled );
END_TEST;
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- Stage::GetCurrent().Add(field);
+ Stage::GetCurrent().Add( field );
field.TextChangedSignal().Connect(&TestTextChangedCallback);
gTextChangedCallBackCalled = false;
field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "ABC" ); // Setting placeholder, not TEXT
- DALI_TEST_CHECK( ! gTextChangedCallBackCalled );
+ DALI_TEST_CHECK( !gTextChangedCallBackCalled );
END_TEST;
}
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- Stage::GetCurrent().Add(field);
+ Stage::GetCurrent().Add( field );
const int maxNumberOfCharacters = 1;
field.SetProperty( TextField::Property::MAX_LENGTH, maxNumberOfCharacters );
gMaxCharactersCallBackCalled = false;
field.MaxLengthReachedSignal().Connect(&TestMaxLengthReachedCallback);
- Dali::Integration::KeyEvent keyevent;
- keyevent.keyName = "a";
- keyevent.keyString = "a";
- keyevent.keyCode = 0;
- keyevent.keyModifier = 0;
- keyevent.time = 0;
- keyevent.state = Integration::KeyEvent::Down;
-
- application.ProcessEvent( keyevent );
-
- application.ProcessEvent( keyevent );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
DALI_TEST_CHECK( gMaxCharactersCallBackCalled );
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- Stage::GetCurrent().Add(field);
+ Stage::GetCurrent().Add( field );
const int maxNumberOfCharacters = 3;
field.SetProperty( TextField::Property::MAX_LENGTH, maxNumberOfCharacters );
gMaxCharactersCallBackCalled = false;
field.MaxLengthReachedSignal().Connect(&TestMaxLengthReachedCallback);
- Dali::Integration::KeyEvent keyevent;
- keyevent.keyName = "a";
- keyevent.keyString = "a";
- keyevent.keyCode = 0;
- keyevent.keyModifier = 0;
- keyevent.time = 0;
- keyevent.state = Integration::KeyEvent::Down;
-
- application.ProcessEvent( keyevent );
- application.ProcessEvent( keyevent );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
DALI_TEST_CHECK( !gMaxCharactersCallBackCalled );
END_TEST;
}
+
+int utcDaliTextFieldEvent01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldEvent01");
+
+ // Creates a tap event. After creating a tap event the text field should
+ // have the focus and add text with key events should be possible.
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ Stage::GetCurrent().Add( field );
+
+ field.SetSize( 300.f, 50.f );
+ field.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ field.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Add a key event but as the text field has not the focus it should do nothing.
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string(""), TEST_LOCATION );
+
+ // Create a tap event to touch the text field.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 150.0f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 150.0f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Now the text field has the focus, so it can handle the key events.
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string("aa"), TEST_LOCATION );
+
+ // Create a second text field and send key events to it.
+ TextField field2 = TextField::New();
+
+ field2.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ field2.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+ field2.SetSize( 100.f, 100.f );
+ field2.SetPosition( 100.f, 100.f );
+
+ Stage::GetCurrent().Add( field2 );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Create a tap event on the second text field.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 150.0f, 125.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 150.0f, 125.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // The second text field has the focus. It should handle the key events.
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Check the text has been added to the second text field.
+ DALI_TEST_EQUALS( field2.GetProperty<std::string>( TextField::Property::TEXT ), std::string("aa"), TEST_LOCATION );
+
+ END_TEST;
+}
+
+int utcDaliTextFieldEvent02(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldEvent02");
+
+ // Checks if the right number of actors are created.
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ Stage::GetCurrent().Add( field );
+
+ field.SetSize( 300.f, 50.f );
+ field.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ field.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Check there are the expected number of children ( active layer, offscreen root actor, and the offscreen image actor
+ DALI_TEST_EQUALS( field.GetChildCount(), 3u, TEST_LOCATION );
+
+ Actor layer = field.GetChildAt( 0u );
+ DALI_TEST_CHECK( layer.IsLayer() );
+
+ Actor offscreenRoot = field.GetChildAt( 1u );
+ DALI_TEST_CHECK( offscreenRoot.IsLayer() );
+ DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 1u, TEST_LOCATION ); // The camera actor.
+
+ Actor offscreenImage = field.GetChildAt( 2u );
+ ImageActor imageActor = ImageActor::DownCast( offscreenImage );
+ DALI_TEST_CHECK( imageActor );
+
+ // Create a tap event to touch the text field.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 150.0f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 150.0f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( layer.GetChildCount(), 1u, TEST_LOCATION ); // The cursor.
+ DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 1u, TEST_LOCATION ); // The camera actor.
+
+ // Now the text field has the focus, so it can handle the key events.
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Checks the cursor and the renderer have been created.
+ DALI_TEST_EQUALS( layer.GetChildCount(), 1u, TEST_LOCATION ); // The cursor.
+ DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 2u, TEST_LOCATION ); // The camera actor and the renderer
+
+ ImageActor cursor = ImageActor::DownCast( layer.GetChildAt( 0u ) );
+ DALI_TEST_CHECK( cursor );
+
+ CameraActor camera = CameraActor::DownCast( offscreenRoot.GetChildAt( 0u ) );
+ DALI_TEST_CHECK( camera );
+
+ RenderableActor renderer = RenderableActor::DownCast( offscreenRoot.GetChildAt( 1u ) );
+ DALI_TEST_CHECK( renderer );
+
+ // Move the cursor and check the position changes.
+ Vector3 position1 = cursor.GetCurrentPosition();
+
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector3 position2 = cursor.GetCurrentPosition();
+
+ DALI_TEST_CHECK( position2.x < position1.x );
+
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector3 position3 = cursor.GetCurrentPosition();
+
+ DALI_TEST_EQUALS( position1, position3, TEST_LOCATION ); // Should be in the same position1.
+
+ // Send some taps and check the cursor positions.
+
+ // Try to tap at the beginning.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 3.f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 3.f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Cursor position should be the same than position1.
+ Vector3 position4 = cursor.GetCurrentPosition();
+
+ DALI_TEST_EQUALS( position2, position4, TEST_LOCATION ); // Should be in the same position2.
+
+ // Try to tap at the end.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 13.f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 13.0f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Cursor position should be the same than position1.
+ Vector3 position5 = cursor.GetCurrentPosition();
+
+ DALI_TEST_EQUALS( position1, position5, TEST_LOCATION ); // Should be in the same position1.
+
+ // Remove some text.
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Cursor position should be the same than position2.
+ Vector3 position6 = cursor.GetCurrentPosition();
+
+ DALI_TEST_EQUALS( Vector3( 0.f, position2.y, position2.z ), position6, TEST_LOCATION ); // TODO Should be in the same position2.
+
+ // Should not be renderer.
+ DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 1u, TEST_LOCATION ); // The camera actor only.
+
+ END_TEST;
+}
+
+int utcDaliTextFieldEvent03(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldEvent03");
+
+ // Checks if the highlight actor is created.
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ Stage::GetCurrent().Add( field );
+
+ field.SetProperty( TextField::Property::TEXT, "This is a long text for the size of the text-field." );
+ field.SetSize( 30.f, 50.f );
+ field.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ field.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Tap first to get the focus.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 3.f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 3.f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Double tap to select a word.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 2u, 1u, Vector2( 3.f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 2u, 1u, Vector2( 3.f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // The offscreen root actor should have three actors: the camera, a renderer and the highlight actor.
+ Actor offscreenRoot = field.GetChildAt( 1u );
+ DALI_TEST_CHECK( offscreenRoot.IsLayer() );
+
+ CameraActor camera = CameraActor::DownCast( offscreenRoot.GetChildAt( 0u ) );
+ DALI_TEST_CHECK( camera );
+
+ RenderableActor renderer = RenderableActor::DownCast( offscreenRoot.GetChildAt( 1u ) );
+ DALI_TEST_CHECK( renderer );
+
+ MeshActor highlight = MeshActor::DownCast( offscreenRoot.GetChildAt( 2u ) );
+ DALI_TEST_CHECK( highlight );
+
+ END_TEST;
+}
const char* const PROPERTY_NAME_UNDERLINE_COLOR = "underline-color";
const char* const PROPERTY_NAME_UNDERLINE_HEIGHT = "underline-height";
+const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
+
} // namespace
int UtcDaliToolkitTextLabelConstructorP(void)
END_TEST;
}
-int UtcDaliToolkitTextLabelGetPropertyN(void)
-{
- ToolkitTestApplication application;
- tet_infoline(" UtcDaliToolkitTextLabelGetPropertyN");
- TextLabel label = TextLabel::New("Test Text");
- DALI_TEST_CHECK( label );
-
- bool assert = false;
- try
- {
- Property::Value value = label.GetProperty<bool>( 0 );
- }
- catch ( ... )
- {
- assert = true;
- }
- if ( assert )
- {
- tet_result(TET_PASS);
- }
- else
- {
- tet_result(TET_FAIL);
- }
- END_TEST;
-}
-
// Positive test case for a method
int UtcDaliToolkitTextLabelGetPropertyP(void)
{
DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE_COLOR ) == TextLabel::Property::UNDERLINE_COLOR );
DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE_HEIGHT) == TextLabel::Property::UNDERLINE_HEIGHT );
- // Check label defaults are correct
- DALI_TEST_EQUALS( label.GetProperty<int>( TextLabel::Property::RENDERING_BACKEND ), Text::RENDERING_SHARED_ATLAS, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::UNDERLINE_ENABLED ), false, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 0.0f, TEST_LOCATION );
- END_TEST;
-}
-
-int UtcDaliToolkitTextLabelSetPropertyN(void)
-{
- ToolkitTestApplication application;
- tet_infoline(" UtcDaliToolkitTextLabelSetPropertyN");
- TextLabel label = TextLabel::New("Test Text");
- DALI_TEST_CHECK( label );
-
- bool assert = false;
- try
- {
- label.SetProperty( 0, true );
- }
- catch ( ... )
- {
- assert = true;
- }
- if ( assert )
- {
- tet_result(TET_PASS);
- }
- else
- {
- tet_result(TET_FAIL);
- }
END_TEST;
}
{
ToolkitTestApplication application;
tet_infoline(" UtcDaliToolkitTextLabelSetPropertyP");
- TextLabel label = TextLabel::New("Test Text");
+ TextLabel label = TextLabel::New();
DALI_TEST_CHECK( label );
+ // Check defaults
+ DALI_TEST_EQUALS( label.GetProperty<unsigned int>( TextLabel::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_FAMILY ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_STYLE ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::POINT_SIZE ), 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::MULTI_LINE ), false, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::UNDERLINE_ENABLED ), false, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::UNDERLINE_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 0.0f, TEST_LOCATION );
+
+ label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Text::RENDERING_BASIC );
+ DALI_TEST_EQUALS( label.GetProperty<unsigned int>( TextLabel::Property::RENDERING_BACKEND ), Text::RENDERING_BASIC, TEST_LOCATION );
+
// Check that text can be correctly reset
label.SetProperty( TextLabel::Property::TEXT, "Setting Text" );
- DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), "Setting Text", TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), std::string("Setting Text"), TEST_LOCATION );
+
+ // Check font properties.
+ label.SetProperty( TextLabel::Property::FONT_FAMILY, "Setting font family" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_FAMILY ), std::string("Setting font family"), TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::FONT_STYLE, "Setting font style" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_STYLE ), std::string("Setting font style"), TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::POINT_SIZE, 10.f );
+ DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::POINT_SIZE ), 10.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ // Toggle multi-line
+ label.SetProperty( TextLabel::Property::MULTI_LINE, true );
+ DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::MULTI_LINE ), true, TEST_LOCATION );
// Check that the Alignment properties can be correctly set
- label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "BEGIN" );
- DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION );
- label.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "TOP" );
- DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "CENTER", TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::VERTICAL_ALIGNMENT ), "CENTER", TEST_LOCATION );
+
+ // Check that text color can be properly set
+ label.SetProperty( TextLabel::Property::TEXT_COLOR, Color::BLUE );
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::TEXT_COLOR ), Color::BLUE, TEST_LOCATION );
+ // The underline color is changed as well.
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::UNDERLINE_COLOR ), Color::BLUE, TEST_LOCATION );
// Check that shadow parameters can be correctly set
label.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 3.0f, 3.0f ) );
label.SetProperty( TextLabel::Property::UNDERLINE_HEIGHT, 1.0f );
DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 1.0f, TEST_LOCATION );
- // Check that text color can be properly set
- label.SetProperty( TextLabel::Property::TEXT_COLOR, Color::BLUE );
- DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::TEXT_COLOR ), Color::BLUE, TEST_LOCATION );
+ TextLabel label2 = TextLabel::New( "New text" );
+ DALI_TEST_CHECK( label2 );
+ DALI_TEST_EQUALS( label2.GetProperty<std::string>( TextLabel::Property::TEXT ), std::string("New text"), TEST_LOCATION );
- // Toggle multi-line
- label.SetProperty( TextLabel::Property::MULTI_LINE, true );
- DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::MULTI_LINE ), true, TEST_LOCATION );
END_TEST;
}
TextLabel label = TextLabel::New("Test Text");
DALI_TEST_CHECK( label );
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ Stage::GetCurrent().Add( label );
+
label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "BEGIN" );
label.SetProperty( TextLabel::Property::MULTI_LINE, true );
TextLabel label = TextLabel::New("Test Text");
DALI_TEST_CHECK( label );
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ Stage::GetCurrent().Add( 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_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
END_TEST;
}
+int UtcDaliToolkitTextLabelLanguagesP(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliToolkitTextLabelLanguagesP");
+ TextLabel label = TextLabel::New();
+ DALI_TEST_CHECK( label );
+
+ Stage::GetCurrent().Add( label );
+
+ const std::string scripts( " привет мир, γειά σου Κόσμε, Hello world, مرحبا بالعالم, שלום עולם, "
+ "բարեւ աշխարհը, მსოფლიოში, 안녕하세요, 你好世界, ひらがな, カタカナ, "
+ "ওহে বিশ্ব, မင်္ဂလာပါကမ္ဘာလောက, हैलो वर्ल्ड, હેલો વર્લ્ડ, ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ ਦੁਨਿਆ, ಹಲೋ ವರ್ಲ್ಡ್, "
+ "ഹലോ വേൾഡ്, ଓଡ଼ିଆ, හෙලෝ වර්ල්ඩ්, ஹலோ உலகம், హలో వరల్డ్, "
+ "ສະບາຍດີໂລກ, สวัสดีโลก, ជំរាបសួរពិភពលោក, "
+ "\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84." ); // these characters on the last line are emojis.
+
+ label.SetProperty( TextLabel::Property::TEXT, scripts );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), scripts, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
+}
DALI_TEST_CHECK( !textSelectionPopup );
- textSelectionPopup = TextSelectionPopup::New();
+ textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL );
DALI_TEST_CHECK( textSelectionPopup );
END_TEST;
ToolkitTestApplication application;
TextSelectionPopup textSelectionPopup;
- textSelectionPopup = TextSelectionPopup::New();
+ textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL );
TextSelectionPopup copy( textSelectionPopup );
DALI_TEST_CHECK( copy == textSelectionPopup );
{
ToolkitTestApplication application;
TextSelectionPopup textSelectionPopup;
- textSelectionPopup = TextSelectionPopup::New();
+ textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL );
TextSelectionPopup copy;
copy = textSelectionPopup;
{
ToolkitTestApplication application;
TextSelectionPopup textSelectionPopup;
- textSelectionPopup = TextSelectionPopup::New();
+ textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL );
TextSelectionPopup cast = TextSelectionPopup::DownCast( textSelectionPopup );
[enable_debug=$enableval],
[enable_debug=no])
+AC_ARG_ENABLE([i18n],
+ [AC_HELP_STRING([--enable-i18n],
+ [Turns on internationalisation])],
+ [enable_i18n=$enableval],
+ [enable_i18n=no])
+
# option to build JavaScript plugin
# configure settings and output
# --enable-javascript // enable_javascript = yes
DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -fvisibility=hidden -DHIDE_DALI_INTERNALS"
fi
-
-
+if test "x$enable_i18n" = "xyes"; then
+ DALI_TOOLKIT_CFLAGS="$DALI_TOOLKIT_CFLAGS -DDGETTEXT_ENABLED "
+fi
# Tizen Profile options
AC_ARG_ENABLE([profile],
develapitransitioneffectsdir = $(develapidir)/transition-effects
develapistylingdir = $(develapidir)/styling
develapitoolbardir = $(develapicontrolsdir)/tool-bar
+develapitextselectionpopupdir = $(develapicontrolsdir)/text-controls
# devel headers
develapibloomview_HEADERS = $(devel_api_bloom_view_header_files)
develapisuperblurview_HEADERS = $(devel_api_super_blur_view_header_files)
develapitoolbar_HEADERS = $(devel_api_tool_bar_header_files)
develapitransitioneffects_HEADERS = $(devel_api_transition_effects_header_files)
+develapitextselectionpopup_HEADERS = $(devel_api_text_selection_popup_header_files)
# public api source
publicapidir = $(topleveldir)/public-api
// Magnifier
///////////////////////////////////////////////////////////////////////////////////////////////////
-const std::string Magnifier::SOURCE_POSITION_PROPERTY_NAME( "source-position" );
-
Magnifier::Magnifier()
{
}
GetImpl(*this).SetSourceActor( actor );
}
-void Magnifier::SetSourcePosition(Vector3 position)
-{
- GetImpl(*this).SetSourcePosition( position );
-}
-
-bool Magnifier::GetFrameVisibility() const
-{
- return GetImpl(*this).GetFrameVisibility();
-}
-
-void Magnifier::SetFrameVisibility(bool visible)
-{
- GetImpl(*this).SetFrameVisibility(visible);
-}
-
-float Magnifier::GetMagnificationFactor() const
-{
- return GetImpl(*this).GetMagnificationFactor();
-}
-
-void Magnifier::SetMagnificationFactor(float value)
-{
- GetImpl(*this).SetMagnificationFactor( value );
-}
-
-
} // namespace Toolkit
} // namespace Dali
{
public:
- // Custom properties
+ /**
+ * @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
+
+ ANIMATABLE_PROPERTY_START_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX,
+ ANIMATABLE_PROPERTY_END_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1000 ///< Reserve animatable property indices
+ };
- static const std::string SOURCE_POSITION_PROPERTY_NAME; ///< Property, name "source-position", type Vector3
+ /**
+ * @brief An enumeration of properties belonging to the Magnifier class.
+ */
+ struct Property
+ {
+ enum
+ {
+ // Event side properties
+ FRAME_VISIBILITY = PROPERTY_START_INDEX, ///< name "frame-visibility", Whether a frame is visible or not, type boolean
+ MAGNIFICATION_FACTOR, ///< name "magnification-factor", Larger value means greater magnification, type float
+
+ // Animatable properties
+ SOURCE_POSITION = ANIMATABLE_PROPERTY_START_INDEX, ///< name "source-position", The position of the source, type Vector3
+ };
+ };
public:
*/
void SetSourceActor(Actor actor);
- /**
- * Set the source camera position to render in magnifier
- * @param[in] position The target position from which to render source.
- */
- void SetSourcePosition(Vector3 position);
-
- /**
- * Returns whether the frame is visible or not.
- * @return true if frame is visible, false if not.
- */
- bool GetFrameVisibility() const;
-
- /**
- * Sets whether the frame part of the magnifier should be visible
- * or not.
- * @param[in] visible true to display frame, false to hide frame.
- */
- void SetFrameVisibility(bool visible);
-
- /**
- * Get the magnification factor of the magnifier
- * The larger the value the larger the contents magnified.
- * A value of 1.0f indications 1x magnification.
- * @return Magnification factor is returned
- */
- float GetMagnificationFactor() const;
-
- /**
- * Set the magnification factor of the magnifier
- * The larger the value the larger the contents magnified.
- * A value of 1.0f indications 1x magnification.
- * @param[in] value Magnification factor.
- */
- void SetMagnificationFactor(float value);
-
public: // Not intended for application developers
/**
--- /dev/null
+#ifndef __DALI_TOOLKIT_TEXT_SELECTION_POPUP_CALLBACK_INTERFACE_H__
+#define __DALI_TOOLKIT_TEXT_SELECTION_POPUP_CALLBACK_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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+/**
+ * @brief Interface used to receive the TextSelectionPopup's button callbacks.
+ */
+class TextSelectionPopupCallbackInterface
+{
+public:
+ /**
+ * @brief Virtual destructor.
+ */
+ virtual ~TextSelectionPopupCallbackInterface()
+ {}
+
+ /**
+ * @brief Called when a button is touched.
+ *
+ * @param[in] button The button identifier.
+ */
+ virtual void TextPopupButtonTouched( TextSelectionPopup::Buttons button ) = 0;
+};
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+
+#endif // __DALI_TOOLKIT_TEXT_SELECTION_POPUP_CALLBACK_INTERFACE_H__
namespace Toolkit
{
-TextSelectionPopup TextSelectionPopup::New()
+TextSelectionPopup TextSelectionPopup::New( Buttons enabledButtons,
+ TextSelectionPopupCallbackInterface* callbackInterface )
{
- return Internal::TextSelectionPopup::New();
+ return Internal::TextSelectionPopup::New( enabledButtons,
+ callbackInterface );
}
TextSelectionPopup::TextSelectionPopup()
namespace Toolkit
{
+class TextSelectionPopupCallbackInterface;
+
namespace Internal DALI_INTERNAL
{
class TextSelectionPopup;
{
public:
+ enum Buttons
+ {
+ CUT = 1u << 0,
+ COPY = 1u << 1,
+ PASTE = 1u << 2,
+ SELECT = 1u << 3,
+ SELECT_ALL = 1u << 4,
+ CLIPBOARD = 1u << 5,
+ NONE = 1u << 6,
+ };
+
/**
* @brief The start and end property ranges for this control.
*/
};
/**
- * @brief An enumeration of properties belonging to the TextLabel class.
+ * @brief An enumeration of properties belonging to the TextSelectionPopup 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_MAX_SIZE = PROPERTY_START_INDEX, ///< name "popup-max-size", maximum size the Popup can be, type VECTOR2
+ POPUP_MIN_SIZE, ///< name "popup-min-size", minimum size the Popup can be, type VECTOR2
+ OPTION_MAX_SIZE, ///< name "option-max-size", maximum size an option can be, type VECTOR2
+ OPTION_MIN_SIZE, ///< name "option-min-size", minimum size an option can be, type VECTOR2
+ OPTION_DIVIDER_SIZE, ///< name "option-divider-size", size of the divider between options type VECTOR2
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
};
/**
- * Create the TextSelectionPopup control.
+ * Create the TextSelectionPopup control with the given set of buttons.
+ * @param[in] enabledButtons The given set of buttons to enable
+ * @param[in] callbackInterface The text popup callback interface which receives the button click callbacks.
* @return A handle to the TextSelectionPopup control.
*/
- static TextSelectionPopup New();
+ static TextSelectionPopup New( Buttons enabledButtons,
+ TextSelectionPopupCallbackInterface* callbackInterface );
/**
* @brief Creates an empty handle.
} // namespace Toolkit
-} // namepsace Dali
+} // namespace Dali
#endif // __DALI_TOOLKIT_TEXT_SELECTION_POPUP_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h>
+
+using namespace Dali;
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+TextSelectionToolbar TextSelectionToolbar::New()
+{
+ return Internal::TextSelectionToolbar::New();
+}
+
+TextSelectionToolbar::TextSelectionToolbar()
+{
+}
+
+TextSelectionToolbar::TextSelectionToolbar( const TextSelectionToolbar& handle )
+: Control( handle )
+{
+}
+
+TextSelectionToolbar& TextSelectionToolbar::operator=( const TextSelectionToolbar& handle )
+{
+ if( &handle != this )
+ {
+ Control::operator=( handle );
+ }
+ return *this;
+}
+
+TextSelectionToolbar::~TextSelectionToolbar()
+{
+}
+
+void TextSelectionToolbar::AddOption( Actor& option )
+{
+ GetImpl(*this).AddOption(option);
+}
+
+
+void TextSelectionToolbar::AddDivider( Actor& divider )
+{
+ GetImpl(*this).AddDivider( divider );
+}
+
+void TextSelectionToolbar::ResizeDividers( Size& size )
+{
+ GetImpl(*this).ResizeDividers( size );
+}
+
+TextSelectionToolbar TextSelectionToolbar::DownCast( BaseHandle handle )
+{
+ return Control::DownCast<TextSelectionToolbar, Internal::TextSelectionToolbar>(handle);
+}
+
+TextSelectionToolbar::TextSelectionToolbar( Internal::TextSelectionToolbar& implementation )
+: Control(implementation)
+{
+}
+
+TextSelectionToolbar::TextSelectionToolbar( Dali::Internal::CustomActor* internal )
+: Control( internal )
+{
+ VerifyCustomActorPointer<Internal::TextSelectionToolbar>( internal );
+}
+
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_TEXT_SELECTION_TOOLBAR_H__
+#define __DALI_TOOLKIT_TEXT_SELECTION_TOOLBAR_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 <dali-toolkit/public-api/controls/control.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class TextSelectionToolbar;
+}
+
+/**
+ * @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 TextSelectionToolbar : 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 TextSelectionToolbar class.
+ */
+ struct Property
+ {
+ enum
+ {
+ MAX_SIZE = PROPERTY_START_INDEX ///< name "popup-max-size", The maximum size the Popup can be, type VECTOR2
+ };
+ };
+
+ /**
+ * Create the TextSelectionToolbar control.
+ * @return A handle to the TextSelectionToolbar control.
+ */
+ static TextSelectionToolbar New();
+
+ /**
+ * @brief Creates an empty handle.
+ */
+ TextSelectionToolbar();
+
+ /**
+ * @brief Copy constructor.
+ *
+ * @param[in] handle The handle to copy from.
+ */
+ TextSelectionToolbar( const TextSelectionToolbar& handle );
+
+ /**
+ * @brief Assignment operator.
+ *
+ * @param[in] handle The handle to copy from.
+ * @return A reference to this.
+ */
+ TextSelectionToolbar& operator=( const TextSelectionToolbar& handle );
+
+ /**
+ * @brief Destructor
+ *
+ * This is non-virtual since derived Handle types must not contain data or virtual methods.
+ */
+ ~TextSelectionToolbar();
+
+
+ /**
+ * @brief Add a option to the the Tool bar
+ * @param[in] option Option actor to add
+ */
+ void AddOption( Actor& option );
+
+ /**
+ * @brief Add a divider to the the Tool bar
+ * @param[in] divider Actor to be used as divider
+ */
+ void AddDivider( Actor& divider );
+
+ /**
+ * @brief ResizeDividers
+ * @param[in] size New size of dividers, provide 0 for height to automatically set height
+ */
+ void ResizeDividers( Size& size );
+
+ /**
+ * @brief Downcast a handle to TextSelectionToolbar.
+ *
+ * If the BaseHandle points is a TextSelectionToolbar 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 TextSelectionToolbar or an empty handle
+ */
+ static TextSelectionToolbar 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 TextSelectionToolbar( Internal::TextSelectionToolbar& 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 TextSelectionToolbar( Dali::Internal::CustomActor* internal );
+
+}; // Class TextSelectionToolbar
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_SELECTION_TOOLBAR_H__
$(devel_api_src_dir)/controls/slider/slider.cpp \
$(devel_api_src_dir)/controls/super-blur-view/super-blur-view.cpp \
$(devel_api_src_dir)/controls/text-controls/text-selection-popup.cpp \
+ $(devel_api_src_dir)/controls/text-controls/text-selection-toolbar.cpp \
$(devel_api_src_dir)/controls/tool-bar/tool-bar.cpp \
$(devel_api_src_dir)/focus-manager/keyinput-focus-manager.cpp \
$(devel_api_src_dir)/styling/style-manager.cpp \
devel_api_super_blur_view_header_files = \
$(devel_api_src_dir)/controls/super-blur-view/super-blur-view.h
-devel_api_text_selection_popup_header_files = \
- $(devel_api_src_dir)/controls/text-controls/text-selection-popup.h
+devel_api_text_controls_header_files = \
+ $(devel_api_src_dir)/controls/text-controls/text-selection-popup.h \
+ $(devel_api_src_dir)/controls/text-controls/text-selection-toolbar.h
devel_api_tool_bar_header_files = \
$(devel_api_src_dir)/controls/tool-bar/tool-bar.h
void AtlasManager::GenerateMeshData( ImageId id,
const Vector2& position,
- Toolkit::AtlasManager::Mesh2D& meshData )
+ Toolkit::AtlasManager::Mesh2D& meshData,
+ bool addReference )
{
// Read the atlas Id to use for this image
SizeType imageId = id - 1u;
CreateMesh( atlas, width, height, position, widthInBlocks, heightInBlocks, meshData, mImageList[ imageId ] );
- // Mesh created so increase the reference count
- mImageList[ imageId ].mCount++;
+ // Mesh created so increase the reference count, if we're asked to
+ if ( addReference )
+ {
+ mImageList[ imageId ].mCount++;
+ }
}
Dali::Atlas AtlasManager::GetAtlasContainer( AtlasId atlas ) const
*/
void GenerateMeshData( ImageId id,
const Vector2& position,
- Toolkit::AtlasManager::Mesh2D& mesh );
+ Toolkit::AtlasManager::Mesh2D& mesh,
+ bool addReference );
/**
* @copydoc Toolkit::AtlasManager::StitchMesh
void AtlasManager::GenerateMeshData( ImageId id,
const Vector2& position,
- Mesh2D& mesh )
+ Mesh2D& mesh,
+ bool addReference )
{
GetImplementation(*this).GenerateMeshData( id,
position,
- mesh );
+ mesh,
+ addReference );
}
void AtlasManager::StitchMesh( Mesh2D& first,
* @param[in] id Image Id returned in the AtlasSlot from the add operation
* @param[in] position position of the resulting mesh in model space
* @param[out] mesh Mesh Data Object to populate with mesh data
+ * @param[in] addReference Whether to increase the internal reference count for image or not
*/
void GenerateMeshData( ImageId id,
const Vector2& position,
- Mesh2D& mesh );
+ Mesh2D& mesh,
+ bool addReference = true );
/**
* @brief Append second mesh to the first mesh
// this has already been set as a generic property.
if( !IsVector3( child, "parent-origin") )
{
- if( OptionalVector3 v = IsVector3(child, "parent-origin") )
+ if( OptionalVector3 v = constant.IsVector3( IsChild(child, "parent-origin") ) )
{
actor.SetParentOrigin( *v );
}
- else if( OptionalString origin = IsString(child, "parent-origin") )
+ else if( OptionalString origin = constant.IsString( IsChild(child, "parent-origin") ) )
{
actor.SetParentOrigin( GetAnchorConstant(*origin) );
}
if( !IsVector3(child, "anchor-point") )
{
- if( OptionalVector3 v = IsVector3(child, "anchor-point") )
+ if( OptionalVector3 v = constant.IsVector3( IsChild(child, "anchor-point") ) )
{
actor.SetAnchorPoint( *v );
}
- else if( OptionalString anchor = IsString(child, "anchor-point") )
+ else if( OptionalString anchor = constant.IsString( IsChild(child, "anchor-point") ) )
{
actor.SetAnchorPoint( GetAnchorConstant(*anchor) );
}
{
if( Property::INVALID_INDEX == index )
{
- actor.RegisterProperty( key, value );
+ actor.RegisterProperty( key, value, Property::READ_WRITE );
}
else
{
}
else
{
- DALI_ASSERT_ALWAYS( iter != alphaFunctionLut.end() && "Unknown Anchor Constant" );
+ DALI_ASSERT_ALWAYS( iter != alphaFunctionLut.end() && "Unknown Alpha Constant" );
return Dali::AlphaFunction::DEFAULT;
}
}
ret = std::string("Map Size=") + ToString( value.Get<Property::Map>().Count() );
break;
}
- case Property::TYPE_COUNT:
- {
- ret = "";
- break;
- }
}
return ret;
{
if( OptionalChild image = IsChild( *images, name ) )
{
- Dali::Property::Value propertyMap(Property::MAP);
- if( SetPropertyFromNode( *image, Property::MAP, propertyMap, constant ) )
+ Dali::Property::Value property(Property::MAP);
+ if( SetPropertyFromNode( *image, Property::MAP, property, constant ) )
{
- propertyMap.SetValue(KEYNAME_TYPE, Property::Value(std::string("FrameBufferImage")));
- ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( propertyMap ) );
+ Property::Map* map = property.GetMap();
+ (*map)[ KEYNAME_TYPE ] = Property::Value(std::string("FrameBufferImage") );
+ ret = FrameBufferImage::DownCast( Dali::Scripting::NewImage( property ) );
mFrameBufferImageLut[ name ] = ret;
}
}
/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * 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.
// EXTERNAL INCLUDES
#include <sstream>
+#include <dali/public-api/object/property-array.h>
+#include <dali/public-api/object/property-map.h>
#include <dali/devel-api/adaptor-framework/color-controller.h>
// INTERNAL INCLUDES
{
if( OptionalUnsignedInt v = replacer.IsUnsignedInteger( node) )
{
- if( *v >= 0 ) // with a loss of resolution....
- {
- value = *v;
- done = true;
- }
+ value = *v;
+ done = true;
}
break;
}
else if(node.Size())
{
value = Property::Value(Property::ARRAY);
+ Property::Array* array = value.GetArray();
unsigned int i = 0;
TreeNode::ConstIterator iter(node.CBegin());
for( ; i < node.Size(); ++i, ++iter)
{
- Property::Value v;
- if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
{
- value.AppendItem(v);
+ array->PushBack( childValue );
}
}
- if( value.GetSize() == static_cast<int>(node.Size()) )
+ if( array->Count() == node.Size() )
{
done = true;
}
else if(node.Size())
{
value = Property::Value(Property::MAP);
+ Property::Map* map = value.GetMap();
unsigned int i = 0;
TreeNode::ConstIterator iter(node.CBegin());
for( ; i < node.Size(); ++i, ++iter)
{
- Property::Value v;
- if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
{
- value.SetValue( (*iter).first, v );
+ map->Insert( (*iter).first, childValue );
}
}
- if( value.GetSize() == static_cast<int>(node.Size()) )
+ if( map->Count() == node.Size() )
{
done = true;
}
}
break;
}
- case Property::TYPE_COUNT:
case Property::NONE:
{
break;
else
{
value = Property::Value(Property::ARRAY);
- Property::Value v;
+ Property::Array* array = value.GetArray();
for(TreeConstIter iter = node.CBegin(); iter != node.CEnd(); ++iter)
{
- if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
{
- value.AppendItem(v);
+ array->PushBack( childValue );
done = true;
}
}
if( ((*iter).first) == 0 )
{
value = Property::Value(Property::ARRAY);
- Property::Value v;
+ Property::Array* array = value.GetArray();
for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
{
- if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
{
- value.AppendItem(v);
+ array->PushBack( childValue );
done = true;
}
}
else
{
value = Property::Value(Property::MAP);
- Property::Value v;
+ Property::Map* map = value.GetMap();
for(unsigned int i = 0; i < node.Size(); ++i, ++iter)
{
- if( SetPropertyFromNode( (*iter).second, v, replacer ) )
+ Property::Value childValue;
+ if( SetPropertyFromNode( (*iter).second, childValue, replacer ) )
{
- value.SetValue((*iter).first, v);
+ map->Insert( (*iter).first, childValue );
done = true;
}
}
DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Alignment, Toolkit::Control, Create )
DALI_TYPE_REGISTRATION_END()
-struct ScaleToFillConstraint
-{
- /**
- * @param padding to be added.
- */
- ScaleToFillConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding )
- {}
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
- return Vector3( parentSizeWidth, parentSizeHeight, parentSize.depth );
- }
-
- const Toolkit::Alignment::Padding mPadding;
-};
-
-struct ScaleToFitKeepAspectConstraint
-{
- /**
- * @param padding to be added.
- */
- ScaleToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding ),
- mSizeStored( false ),
- mOriginalSize()
- {}
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
- {
- mOriginalSize = currentSize;
- mSizeStored = true;
- }
-
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
- ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
-
- return mOriginalSize * std::min( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
- }
-
- const Toolkit::Alignment::Padding mPadding;
- bool mSizeStored;
- Vector3 mOriginalSize;
-};
-
-struct ScaleToFillKeepAspectConstraint
-{
- /**
- * @param padding to be added.
- */
- ScaleToFillKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding ),
- mSizeStored( false ),
- mOriginalSize()
- { }
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
- {
- mOriginalSize = currentSize;
- mSizeStored = true;
- }
-
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
- ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
-
- return mOriginalSize * std::max( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
- }
-
- const Toolkit::Alignment::Padding mPadding;
- bool mSizeStored;
- Vector3 mOriginalSize;
-};
-
-struct ShrinkToFitConstraint
-{
- /**
- * @param padding to be added.
- */
- ShrinkToFitConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding ),
- mSizeStored( false ),
- mOriginalSize()
- {}
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
- {
- mOriginalSize = currentSize;
- mSizeStored = true;
- }
-
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
- ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
-
- return Vector3( std::min( parentSizeWidth, mOriginalSize.width ), std::min( parentSizeHeight, mOriginalSize.height ), std::min( parentSize.depth, mOriginalSize.depth ) );
- }
-
- const Toolkit::Alignment::Padding mPadding;
- bool mSizeStored;
- Vector3 mOriginalSize;
-};
-
-/**
- * Constraint that uses naturalSize if it fits inside parent and parent size if not. It also adds some padding pixels
- */
-struct ShrinkToFitKeepAspectConstraint
-{
- /**
- * @param padding to be added.
- */
- ShrinkToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding ),
- mSizeStored( false ),
- mOriginalSize()
- {}
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
- {
- mOriginalSize = currentSize;
- mSizeStored = true;
- }
-
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
- ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
-
- return Vector3( ShrinkInside( Vector2( parentSizeWidth, parentSizeHeight ), Vector2( mOriginalSize ) ) );
- }
-
- const Toolkit::Alignment::Padding mPadding;
- bool mSizeStored;
- Vector3 mOriginalSize;
-};
-
/**
- * Constraint that modifies the contained actor taking into account the padding value.
+ * @param padding The padding value
+ * @param horizontalAlignment The horizontal alignment.
+ * @param verticalAlignment The vertical alignment.
+ * @param currentSize of the object
+ * @param parentSize
*/
-struct PositionConstraint
+inline Vector3 GetPosition( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment,
+ const Vector2& currentSize, const Vector2& parentSize )
{
- /**
- * @param padding The padding value
- * @param horizontalAlignment The horizontal alignment.
- * @param verticalAlignment The vertical alignment.
- */
- PositionConstraint( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment )
- : mPadding( padding ),
- mHorizontalAlignment( horizontalAlignment ),
- mVerticalAlignment( verticalAlignment )
- {}
-
- /**
- * Called by render thread.
- */
- Vector3 operator()( const Vector3& currentPosition,
- const PropertyInput& currentSizeProperty,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& currentSize( currentSizeProperty.GetVector3() );
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
-
- return GetPosition( currentSize, parentSize );
- }
+ Vector3 position( 0.f, 0.f, 0.f );
- inline Vector3 GetPosition( const Vector3& currentSize, const Vector3& parentSize )
+ switch( horizontalAlignment )
{
- Vector3 position( 0.f, 0.f, 0.f );
-
- switch( mHorizontalAlignment )
- {
case Dali::Toolkit::Alignment::HorizontalLeft:
{
- position.x += mPadding.left;
- break;
- }
- case Dali::Toolkit::Alignment::HorizontalCenter:
- {
- if( currentSize.width + mPadding.left + mPadding.right >= parentSize.width )
- {
- position.x += 0.5f * ( mPadding.left - mPadding.right );
- }
+ position.x += padding.left;
break;
}
case Dali::Toolkit::Alignment::HorizontalRight:
{
- position.x -= mPadding.right;
+ position.x -= padding.right;
break;
}
- default:
+ case Dali::Toolkit::Alignment::HorizontalCenter: // FALLTHROUGH
+ default: // use center as default
{
- DALI_ASSERT_ALWAYS( !"Wrong horizontal alignment value" );
+ if( currentSize.width + padding.left + padding.right >= parentSize.width )
+ {
+ position.x += 0.5f * ( padding.left - padding.right );
+ }
break;
}
- }
+ }
- switch( mVerticalAlignment )
- {
+ switch( verticalAlignment )
+ {
case Dali::Toolkit::Alignment::VerticalTop:
{
- position.y += mPadding.top;
- break;
- }
- case Dali::Toolkit::Alignment::VerticalCenter:
- {
- if( currentSize.height + mPadding.top + mPadding.bottom >= parentSize.height )
- {
- position.y += 0.5f * ( mPadding.top - mPadding.bottom );
- }
+ position.y += padding.top;
break;
}
case Dali::Toolkit::Alignment::VerticalBottom:
{
- position.y -= mPadding.bottom;
+ position.y -= padding.bottom;
break;
}
- default:
+ case Dali::Toolkit::Alignment::VerticalCenter: // FALLTHROUGH
+ default: // use center as default
{
- DALI_ASSERT_ALWAYS( !"Wrong vertical alignment value" );
+ if( currentSize.height + padding.top + padding.bottom >= parentSize.height )
+ {
+ position.y += 0.5f * ( padding.top - padding.bottom );
+ }
break;
}
- }
-
- return position;
}
- const Toolkit::Alignment::Padding mPadding;
- const Toolkit::Alignment::Type mHorizontalAlignment;
- const Toolkit::Alignment::Type mVerticalAlignment;
-};
+ return position;
+}
+
} // namespace
Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
child.SetAnchorPoint( anchorPointAndParentOrigin );
child.SetParentOrigin( anchorPointAndParentOrigin );
- Vector3 currentChildSize( child.GetTargetSize() );
- if( currentChildSize == Vector3::ZERO )
+ Vector2 currentChildSize( child.GetTargetSize().GetVectorXY() );
+ if( currentChildSize == Vector2::ZERO )
{
currentChildSize = child.GetNaturalSize();
}
bool renegotiate = true;
- Vector3 newChildSize;
+ Vector2 newChildSize;
+ newChildSize.width = size.width - ( mPadding.left + mPadding.right );
+ newChildSize.height = size.height- ( mPadding.top + mPadding.bottom );
- switch( mScaling )
+ // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
+ if( ( newChildSize.width > Math::MACHINE_EPSILON_1000 ) && ( newChildSize.height > Math::MACHINE_EPSILON_1000 ) &&
+ ( currentChildSize.width > Math::MACHINE_EPSILON_1000 ) && ( currentChildSize.height > Math::MACHINE_EPSILON_1000 ) )
{
- case Toolkit::Alignment::ScaleNone:
- {
- // Nothing to do but needed just to not to jump to the default.
- newChildSize = currentChildSize;
- renegotiate = false;
- break;
- }
- case Toolkit::Alignment::ScaleToFill:
- {
- ScaleToFillConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) ) ;
- break;
- }
- case Toolkit::Alignment::ScaleToFitKeepAspect:
- {
- ScaleToFitKeepAspectConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) ) ;
- break;
- }
- case Toolkit::Alignment::ScaleToFillKeepAspect:
- {
- ScaleToFillKeepAspectConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) );
- break;
- }
- case Toolkit::Alignment::ShrinkToFit:
- {
- ShrinkToFitConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) );
- break;
- }
- case Toolkit::Alignment::ShrinkToFitKeepAspect:
- {
- ShrinkToFitKeepAspectConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) );
- break;
- }
- default:
+ // no point trying to squeeze actors into too small size
+ switch( mScaling )
{
- DALI_ASSERT_ALWAYS( !"Invalid Alignment::mGeometryScaling value" );
- break;
+ case Toolkit::Alignment::ScaleNone:
+ {
+ // Nothing to do
+ renegotiate = false;
+ break;
+ }
+ case Toolkit::Alignment::ScaleToFill:
+ {
+ // Nothing to do, newChildSize is already full size minus padding
+ break;
+ }
+ case Toolkit::Alignment::ScaleToFitKeepAspect:
+ {
+ newChildSize = currentChildSize * std::min( ( newChildSize.width / currentChildSize.width ), ( newChildSize.height / currentChildSize.height ) );
+ break;
+ }
+ case Toolkit::Alignment::ScaleToFillKeepAspect:
+ {
+ newChildSize = currentChildSize * std::max( ( newChildSize.width / currentChildSize.width ), ( newChildSize.height / currentChildSize.height ) );
+ break;
+ }
+ case Toolkit::Alignment::ShrinkToFit:
+ {
+ newChildSize = Vector2( std::min( newChildSize.width, currentChildSize.width ), std::min( newChildSize.height, currentChildSize.height ) );
+ break;
+ }
+ case Toolkit::Alignment::ShrinkToFitKeepAspect:
+ {
+ // check source size vs target size to see if we need to shrink
+ float widthScale = ( newChildSize.width < currentChildSize.width ) ? (newChildSize.width / currentChildSize.width) : 1.f;
+ float heightScale = ( newChildSize.height < currentChildSize.height ) ? (newChildSize.height / currentChildSize.height) : 1.0f;
+ // use smaller of the scales
+ float scale = std::min( widthScale, heightScale );
+ // check if we need to scale
+ if( scale < 1.0f )
+ {
+ // scale natural size to fit inside
+ newChildSize *= scale;
+ }
+ break;
+ }
}
}
- PositionConstraint positionConstraint(mPadding, mHorizontal, mVertical);
- child.SetPosition( positionConstraint.GetPosition(newChildSize, currentChildSize) );
+ child.SetPosition( GetPosition( mPadding, mHorizontal, mVertical , newChildSize, currentChildSize ) );
if( renegotiate )
{
- container.Add( child, Vector2(newChildSize) );
+ container.Add( child, newChildSize );
}
}
}
#include <dali/public-api/common/stage.h>
#include <dali/public-api/render-tasks/render-task-list.h>
#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/object/type-registry-helper.h>
-using namespace Dali;
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
namespace // unnamed namespace
{
+
+Dali::BaseHandle Create()
+{
+ return Toolkit::Magnifier::New();
+}
+
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Magnifier, Toolkit::Control, Create )
+
+DALI_PROPERTY_REGISTRATION( Toolkit, Magnifier, "frame-visibility", BOOLEAN, FRAME_VISIBILITY )
+DALI_PROPERTY_REGISTRATION( Toolkit, Magnifier, "magnification-factor", FLOAT, MAGNIFICATION_FACTOR )
+
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Magnifier, "source-position", VECTOR3, SOURCE_POSITION )
+
+DALI_TYPE_REGISTRATION_END()
+
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.
}
};
-}
-
-namespace Dali
-{
-
-namespace Toolkit
-{
-
-namespace Internal
-{
+} // unnamed namespace
///////////////////////////////////////////////////////////////////////////////////////////////////
// Magnifier
Magnifier::Magnifier()
: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
- mPropertySourcePosition(Property::INVALID_INDEX),
mDefaultCameraDistance(1000.f),
mActorSize(Vector3::ZERO),
mMagnificationFactor(1.0f)
mTask.SetSourceActor( actor );
}
-void Magnifier::SetSourcePosition(const Vector3& position)
-{
- Self().SetProperty(mPropertySourcePosition, position);
-}
-
void Magnifier::Initialize()
{
Actor self = Self();
- mPropertySourcePosition = self.RegisterProperty( Toolkit::Magnifier::SOURCE_POSITION_PROPERTY_NAME, Vector3::ZERO );
Vector2 stageSize(Stage::GetCurrent().GetSize());
// NOTE:
Stage().GetCurrent().Add(mSourceActor);
mSourceActor.SetParentOrigin(ParentOrigin::CENTER);
Constraint constraint = Constraint::New<Vector3>( mSourceActor, Actor::Property::POSITION, EqualToConstraint() );
- constraint.AddSource( Source( self, mPropertySourcePosition ) );
+ constraint.AddSource( Source( self, Toolkit::Magnifier::Property::SOURCE_POSITION ) );
constraint.Apply();
// create the render task this will render content on top of everything
mCameraActor.SetAspectRatio( worldSize.width / worldSize.height );
}
+void Magnifier::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+ Toolkit::Magnifier magnifier = Toolkit::Magnifier::DownCast( Dali::BaseHandle( object ) );
+
+ if( magnifier )
+ {
+ Magnifier& magnifierImpl( GetImpl( magnifier ) );
+ switch( index )
+ {
+ case Toolkit::Magnifier::Property::FRAME_VISIBILITY:
+ {
+ magnifierImpl.SetFrameVisibility( value.Get< bool >() );
+ break;
+ }
+ case Toolkit::Magnifier::Property::MAGNIFICATION_FACTOR:
+ {
+ magnifierImpl.SetMagnificationFactor( value.Get< float >() );
+ break;
+ }
+ }
+ }
+}
+
+Property::Value Magnifier::GetProperty( BaseObject* object, Property::Index index )
+{
+ Property::Value value;
+
+ Toolkit::Magnifier magnifier = Toolkit::Magnifier::DownCast( Dali::BaseHandle( object ) );
+
+ if( magnifier )
+ {
+ Magnifier& magnifierImpl( GetImpl( magnifier ) );
+ switch( index )
+ {
+ case Toolkit::Magnifier::Property::FRAME_VISIBILITY:
+ {
+ value = magnifierImpl.GetFrameVisibility();
+ break;
+ }
+ case Toolkit::Magnifier::Property::MAGNIFICATION_FACTOR:
+ {
+ value = magnifierImpl.GetMagnificationFactor();
+ break;
+ }
+ }
+ }
+
+ return value;
+}
+
} // namespace Internal
} // namespace Toolkit
void SetSourceActor(Actor actor);
/**
- * @copydoc Toolkit::ImageView::SetSourcePosition
- */
- void SetSourcePosition(const Vector3& position);
-
- /**
- * @copydoc Toolkit::ImageView::GetFrameVisibility
+ * Returns whether the frame is visible or not.
+ * @return true if frame is visible, false if not.
*/
bool GetFrameVisibility() const;
/**
- * @copydoc Toolkit::ImageView::SetFrameVisibility
+ * Sets whether the frame part of the magnifier should be visible or not.
+ * @param[in] visible true to display frame, false to hide frame.
*/
void SetFrameVisibility(bool visible);
/**
- * @copydoc Toolkit::ImageView::GetMagnificationFactor
+ * Get the magnification factor of the magnifier
+ * The larger the value the larger the contents magnified.
+ * A value of 1.0f indications 1x magnification.
+ * @return Magnification factor is returned
*/
float GetMagnificationFactor() const;
/**
- * @copydoc Toolkit::ImageView::SetMagnificationFactor
+ * Set the magnification factor of the magnifier
+ * The larger the value the larger the contents magnified.
+ * A value of 1.0f indications 1x magnification.
+ * @param[in] value Magnification factor.
*/
void SetMagnificationFactor(float value);
*/
void Update();
+ // 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 );
+
protected:
/**
RenderTask mTask; ///< Render Task to render the source actor contents.
CameraActor mCameraActor; ///< CameraActor attached to RenderTask
ImageActor mFrame; ///< The Magnifier Frame
- Property::Index mPropertySourcePosition; ///< Source Position ("source-position")
Actor mSourceActor; ///< Source Delegate Actor represents the source position to read.
float mDefaultCameraDistance; ///< Default RenderTask's camera distance from target.
Vector3 mActorSize; ///< The Actor size
// EXTERNAL INCLUDES
#include <cstring> // for strcmp
-#include <dali/integration-api/debug.h>
#include <dali/public-api/animation/constraint.h>
#include <dali/public-api/animation/constraints.h>
+#include <dali/public-api/images/resource-image.h>
#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/property-array.h>
#include <dali/devel-api/object/type-registry-helper.h>
-#include <dali/public-api/images/resource-image.h>
+#include <dali/integration-api/debug.h>
+
// INTERNAL INCLUDES
#include <dali-toolkit/internal/controls/scrollable/item-view/item-view-impl.h>
}
case Toolkit::ScrollBar::Property::SCROLL_POSITION_INTERVALS:
{
- Dali::Vector<float> positions;
- size_t positionCount = value.GetSize();
- positions.Resize( positionCount );
-
- for( size_t i = 0; i != positionCount; ++i )
+ Property::Array* array = value.GetArray();
+ if( array )
{
- value.GetItem(i).Get( positions[i] );
+ Dali::Vector<float> positions;
+ size_t positionCount = array->Count();
+ positions.Resize( positionCount );
+ for( size_t i = 0; i != positionCount; ++i )
+ {
+ array->GetElementAt( i ).Get( positions[i] );
+ }
+
+ scrollBarImpl.SetScrollPositionIntervals(positions);
}
-
- scrollBarImpl.SetScrollPositionIntervals(positions);
break;
}
}
}
case Toolkit::ScrollBar::Property::SCROLL_POSITION_INTERVALS:
{
- Property::Value value;
+ Property::Value value( Property::ARRAY );
+ Property::Array* array = value.GetArray();
Dali::Vector<float> positions = scrollBarImpl.GetScrollPositionIntervals();
- size_t positionCount( positions.Size() );
+ size_t positionCount( array->Count() );
for( size_t i( 0 ); i != positionCount; ++i )
{
- value.AppendItem( positions[i] );
+ array->PushBack( positions[i] );
}
break;
}
DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "layout-orientation", INTEGER, LAYOUT_ORIENTATION)
DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, ItemView, "scroll-content-size", FLOAT, SCROLL_CONTENT_SIZE)
+DALI_SIGNAL_REGISTRATION( Toolkit, ItemView, "layout-activated", LAYOUT_ACTIVATED_SIGNAL )
+
DALI_TYPE_REGISTRATION_END()
const float DEFAULT_MINIMUM_SWIPE_SPEED = 1.0f;
mScrollAnimation.FinishedSignal().Connect(this, &ItemView::OnLayoutActivationScrollFinished);
mScrollAnimation.Play();
}
+ else
+ {
+ // Emit the layout activated signal
+ mLayoutActivatedSignal.Emit();
+ }
AnimateScrollOvershoot(0.0f);
mScrollOvershoot = 0.0f;
RemoveAnimation(mScrollAnimation);
mRefreshEnabled = true;
DoRefresh(GetCurrentLayoutPosition(0), true);
+
+ // Emit the layout activated signal
+ mLayoutActivatedSignal.Emit();
}
void ItemView::OnOvershootOnFinished(Animation& animation)
DoRefresh(position, false); // No need to cache extra items.
}
+bool ItemView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+ Dali::BaseHandle handle( object );
+
+ bool connected( true );
+ Toolkit::ItemView itemView = Toolkit::ItemView::DownCast( handle );
+
+ if( 0 == strcmp( signalName.c_str(), LAYOUT_ACTIVATED_SIGNAL ) )
+ {
+ itemView.LayoutActivatedSignal().Connect( tracker, functor );
+ }
+ else
+ {
+ // signalName does not match any signal
+ connected = false;
+ }
+
+ return connected;
+}
+
} // namespace Internal
} // namespace Toolkit
{
public:
+ // Signals
+ typedef Toolkit::ItemView::LayoutActivatedSignalType LayoutActivatedSignalType;
+
+public:
+
/**
* Create a new ItemView.
* @param[in] factory The factory which provides ItemView with items.
*/
void GetItemsRange(ItemRange& range);
+ /**
+ * @copydoc Toolkit::ItemView::LayoutActivatedSignal()
+ */
+ LayoutActivatedSignalType& LayoutActivatedSignal()
+ {
+ return mLayoutActivatedSignal;
+ }
+
+ /**
+ * 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 );
+
private:
/**
Vector3 mItemsParentOrigin;
Vector3 mItemsAnchorPoint;
+
+ LayoutActivatedSignalType mLayoutActivatedSignal;
};
} // namespace Internal
// CLASS HEADER
#include <dali-toolkit/internal/controls/scrollable/scroll-view/scroll-view-page-path-effect-impl.h>
-//INTERNAL INCLUDES
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/property-array.h>
+
+// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
namespace Dali
//Create linear constrainer
pointsProperty = Property::Value(Property::ARRAY);
- pointsProperty.AppendItem(0.0f);
- pointsProperty.AppendItem(1.0f);
- pointsProperty.AppendItem(0.0f);
+ Property::Array* array = pointsProperty.GetArray();
+ array->PushBack(0.0f);
+ array->PushBack(1.0f);
+ array->PushBack(0.0f);
mLinearConstrainer = Dali::LinearConstrainer::New();
mLinearConstrainer.SetProperty( LinearConstrainer::Property::VALUE, pointsProperty );
}
const float MARK_TOLERANCE = GetMarkTolerance();
float mark;
- for( std::size_t i = 0; i < mMarks.Size(); ++i)
+ for( MarkList::SizeType i = 0; i < mMarks.Count(); ++i)
{
const Property::Value& propertyValue = mMarks[i];
propertyValue.Get( mark );
float closestDist = std::numeric_limits<float>::max();
float mark;
- for( std::size_t i = 0; i < mMarks.Size(); ++i)
+ for( MarkList::SizeType i = 0; i < mMarks.Count(); ++i)
{
const Property::Value& propertyValue = mMarks[i];
propertyValue.Get( mark );
namespace
{
+/*
+ * Custom properties for where to put the actor.
+ *
+ * When an actor is add to the tableView through Actor::Add() instead of TableView::AddChild,
+ * the following custom properties of the actor are checked to decide the actor position inside the table
+ *
+ * These non-animatable properties should be registered to the child which would be added to the table
+ */
+const char * const CELL_INDEX_PROPERTY_NAME("cell-index");
+const char * const ROW_SPAN_PROPERTY_NAME("row-span");
+const char * const COLUMN_SPAN_PROPERTY_NAME("column-span");
+const char * const CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME("cell-horizontal-alignment");
+const char * const CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME("cell-vertical-alignment");
/**
* @brief Should the tableview fit around the given actor
*
* @param[in] actor The child actor to test against
- * @param[dimension] The dimnesion to test against
+ * @param[dimension] The dimension to test against
*/
bool FitToChild( Actor actor, Dimension::Type dimension )
{
#define TABLEVIEW_TAG "DALI Toolkit::TableView "
#define TV_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args)
+//#define TABLEVIEW_DEBUG 1
+#if defined(TABLEVIEW_DEBUG)
void PrintArray( Array2d<Dali::Toolkit::Internal::TableView::CellData>& array )
{
TV_LOG( "Array2d<CellData> size [%d,%d] \n", array.GetRows(), array.GetColumns() );
}
TV_LOG( "\n" );
}
+#endif // defined(TABLEVIEW_DEBUG)
#endif // defined(DEBUG_ENABLED)
} // namespace
DALI_TYPE_REGISTRATION_END()
-const Scripting::StringEnum< Toolkit::TableView::LayoutPolicy > LAYOUT_POLICY_STRING_TABLE[] =
+const Scripting::StringEnum LAYOUT_POLICY_STRING_TABLE[] =
{
{ "fixed", Toolkit::TableView::FIXED },
{ "relative", Toolkit::TableView::RELATIVE },
- { "fill", Toolkit::TableView::FILL }
+ { "fill", Toolkit::TableView::FILL },
+ { "fit", Toolkit::TableView::FIT }
};
-
const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof( LAYOUT_POLICY_STRING_TABLE[0] );
+const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
+{
+ {"left", HorizontalAlignment::LEFT},
+ {"center", HorizontalAlignment::CENTER},
+ {"right", HorizontalAlignment::RIGHT}
+};
+const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
+
+const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
+{
+ {"top", VerticalAlignment::TOP},
+ {"center", VerticalAlignment::CENTER},
+ {"bottom", VerticalAlignment::BOTTOM}
+};
+const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(VERTICAL_ALIGNMENT_STRING_TABLE) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] );
+
} // Unnamed namespace
Toolkit::TableView TableView::New( unsigned int initialRows, unsigned int initialColumns )
DALI_ASSERT_ALWAYS( child );
// if child is already parented, we adopt it
- if( child.GetParent() )
- {
- child.GetParent().Remove( child );
- }
+ child.Unparent();
// check if we need to expand our data array
if( position.rowIndex >= mCellData.GetRows() )
return mPadding;
}
-void TableView::SetRowPolicy( unsigned int rowIndex, CellSizePolicy policy )
+void TableView::SetFitHeight( unsigned int rowIndex )
{
DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
- if( mRowData[ rowIndex ].sizePolicy != policy )
+ if( mRowData[ rowIndex ].sizePolicy != Toolkit::TableView::FIT )
{
- mRowData[ rowIndex ].sizePolicy = policy;
+ mRowData[ rowIndex ].sizePolicy = Toolkit::TableView::FIT;
mRowColumnDirty = true;
RelayoutRequest();
}
}
-TableView::CellSizePolicy TableView::GetRowPolicy( unsigned int rowIndex ) const
+bool TableView::IsFitHeight( unsigned int rowIndex ) const
{
DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
- return mRowData[ rowIndex ].sizePolicy;
+ return mRowData[ rowIndex ].sizePolicy == Toolkit::TableView::FIT;
}
-void TableView::SetColumnPolicy( unsigned int columnIndex, CellSizePolicy policy )
+void TableView::SetFitWidth( unsigned int columnIndex )
{
DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
- if( mColumnData[ columnIndex ].sizePolicy != policy )
+ if( mColumnData[ columnIndex ].sizePolicy != Toolkit::TableView::FIT )
{
- mColumnData[ columnIndex ].sizePolicy = policy;
+ mColumnData[ columnIndex ].sizePolicy = Toolkit::TableView::FIT;
mRowColumnDirty = true;
RelayoutRequest();
}
}
-TableView::CellSizePolicy TableView::GetColumnPolicy( unsigned int columnIndex ) const
+bool TableView::IsFitWidth( unsigned int columnIndex ) const
{
DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
- return mColumnData[ columnIndex ].sizePolicy;
+ return mColumnData[ columnIndex ].sizePolicy == Toolkit::TableView::FIT;
}
void TableView::SetFixedHeight( unsigned int rowIndex, float height )
RowColumnData& data = mRowData[ rowIndex ];
data.size = height;
- data.sizePolicy = FIXED;
+ data.sizePolicy = Toolkit::TableView::FIXED;
mRowColumnDirty = true;
RelayoutRequest();
RowColumnData& data = mColumnData[ columnIndex ];
data.size = width;
- data.sizePolicy = FIXED;
+ data.sizePolicy = Toolkit::TableView::FIXED;
mRowColumnDirty = true;
RelayoutRequest();
RowColumnData& data = mRowData[ rowIndex ];
data.fillRatio = heightPercentage;
- data.userFillRatio = true;
- data.sizePolicy = FILL;
+ data.sizePolicy = Toolkit::TableView::RELATIVE;
mRowColumnDirty = true;
RelayoutRequest();
RowColumnData& data = mColumnData[ columnIndex ];
data.fillRatio = widthPercentage;
- data.userFillRatio = true;
- data.sizePolicy = FILL;
+ data.sizePolicy = Toolkit::TableView::RELATIVE;
mRowColumnDirty = true;
RelayoutRequest();
{
CalculateRowColumnData();
- // Go through the layout data
- float cumulatedHeight = 0.0f;
-
- const unsigned int rowCount = mCellData.GetRows();
+ // update every column position in ColumnData array
+ float cumulatedWidth = 0.0f;
const unsigned int columnCount = mCellData.GetColumns();
+ for( unsigned int column = 0; column < columnCount; ++column )
+ {
+ mColumnData[column].position = cumulatedWidth;
+ cumulatedWidth += mColumnData[ column ].size;
+ }
+ // update every row position in RowData array
+ float cumulatedHeight = 0.0f;
+ const unsigned int rowCount = mCellData.GetRows();
for( unsigned int row = 0; row < rowCount; ++row )
{
- float cumulatedWidth = 0.0f;
+ mRowData[row].position = cumulatedHeight;
+ cumulatedHeight += mRowData[ row ].size;
+ }
+ // Go through the layout data
+ for( unsigned int row = 0; row < rowCount; ++row )
+ {
for( unsigned int column = 0; column < columnCount; ++column )
{
- Actor& actor = mCellData[ row ][ column ].actor;
- const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].position;
+ CellData& cellData= mCellData[ row ][ column ];
+ Actor& actor = cellData.actor;
+ const Toolkit::TableView::CellPosition position = cellData.position;
// If there is an actor and this is the main cell of the actor.
- // An actor can be in multiple cells if its row or columnspan is more than 1.
+ // An actor can be in multiple cells if its row or column span is more than 1.
// We however must lay out each actor only once.
- if( actor && ( position.rowIndex == row ) && ( position.columnIndex == column ) )
+ if( actor && position.rowIndex == row && position.columnIndex == column )
{
- // Anchor actor to top left of table view
+ // Anchor actor to top left of the cell
actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ Vector2( actor.GetRelayoutSize( Dimension::WIDTH ), actor.GetRelayoutSize( Dimension::HEIGHT ) );
+
Padding padding;
actor.GetPadding( padding );
- Vector3 actorPosition( cumulatedWidth + mPadding.width + padding.left, // Left padding
- cumulatedHeight + mPadding.height + padding.top, // Top padding
- 0.0f );
- actor.SetPosition( actorPosition );
- }
+ if( cellData.horizontalAlignment == HorizontalAlignment::LEFT )
+ {
+ actor.SetX( mColumnData[column].position + mPadding.width + padding.left );
+ }
+ else
+ {
+ float cellRightPosition = column+position.columnSpan < columnCount ? mColumnData[column+position.columnSpan].position : cumulatedWidth;
- DALI_ASSERT_DEBUG( column < mColumnData.Size() );
- cumulatedWidth += mColumnData[ column ].size;
- }
+ if( cellData.horizontalAlignment == HorizontalAlignment::RIGHT )
+ {
+ actor.SetX( cellRightPosition - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) );
+ }
+ else //if( cellData.horizontalAlignment == HorizontalAlignment::CENTER )
+ {
+ actor.SetX( (mColumnData[column].position + cellRightPosition
+ + padding.left - padding.right
+ - actor.GetRelayoutSize( Dimension::WIDTH )) * 0.5f );
+ }
+ }
- DALI_ASSERT_DEBUG( row < mRowData.Size() );
- cumulatedHeight += mRowData[ row ].size;
+ if( cellData.verticalAlignment == VerticalAlignment::TOP )
+ {
+ actor.SetY( mRowData[row].position + mPadding.height + padding.top );
+ }
+ else
+ {
+ float cellBottomPosition = row+position.rowSpan < rowCount ? mRowData[row+position.rowSpan].position : cumulatedHeight;
+
+ if( cellData.verticalAlignment == VerticalAlignment::BOTTOM )
+
+ {
+ actor.SetY( cellBottomPosition - mPadding.height - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT ) );
+ }
+ else //if( cellData.verticalAlignment = VerticalAlignment::CENTER )
+ {
+ actor.SetY( (mRowData[row].position + cellBottomPosition
+ + padding.top - padding.bottom
+ - actor.GetRelayoutSize( Dimension::HEIGHT )) * 0.5f );
+ }
+ }
+ }
+ }
}
}
}
case Toolkit::TableView::Property::LAYOUT_ROWS:
{
- SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, value );
+ SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, &TableView::SetFitHeight, value );
break;
}
case Toolkit::TableView::Property::LAYOUT_COLUMNS:
{
- SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, value );
+ SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, &TableView::SetFitWidth, value );
break;
}
}
return;
}
- RelayoutRequest();
-
// Test properties on actor
+ HorizontalAlignment::Type horizontalAlignment = HorizontalAlignment::LEFT;
+ VerticalAlignment::Type verticalAlignment = VerticalAlignment::TOP;
+ if( child.GetPropertyIndex( CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME ) != Property::INVALID_INDEX )
+ {
+ std::string value = child.GetProperty( child.GetPropertyIndex(CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME) ).Get<std::string >();
+ Scripting::GetEnumeration< HorizontalAlignment::Type >( value.c_str(),
+ HORIZONTAL_ALIGNMENT_STRING_TABLE,
+ HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
+ horizontalAlignment );
+ }
+ if( child.GetPropertyIndex( CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME ) != Property::INVALID_INDEX )
+ {
+ std::string value = child.GetProperty( child.GetPropertyIndex(CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME) ).Get<std::string >();
+ Scripting::GetEnumeration< VerticalAlignment::Type >( value.c_str(),
+ VERTICAL_ALIGNMENT_STRING_TABLE,
+ VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
+ verticalAlignment );
+ }
+
+
Toolkit::TableView::CellPosition cellPosition;
- if( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
+ if( child.GetPropertyIndex(ROW_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
{
- cellPosition.rowSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) ).Get<float>() );
+ cellPosition.rowSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(ROW_SPAN_PROPERTY_NAME) ).Get<float>() );
}
- if( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
+ if( child.GetPropertyIndex(COLUMN_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
{
- cellPosition.columnSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) ).Get<float>() );
+ cellPosition.columnSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(COLUMN_SPAN_PROPERTY_NAME) ).Get<float>() );
}
- if( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) != Property::INVALID_INDEX )
+ if( child.GetPropertyIndex(CELL_INDEX_PROPERTY_NAME) != Property::INVALID_INDEX )
{
- Vector2 indices = child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) ).Get<Vector2 >();
+ Vector2 indices = child.GetProperty( child.GetPropertyIndex(CELL_INDEX_PROPERTY_NAME) ).Get<Vector2 >();
cellPosition.rowIndex = static_cast<unsigned int>( indices.x );
cellPosition.columnIndex = static_cast<unsigned int>( indices.y );
AddChild( child, cellPosition );
+ SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment);
// Do not continue
+ RelayoutRequest();
return;
}
data.actor = child;
data.position.columnIndex = column;
data.position.rowIndex = row;
+ data.horizontalAlignment = horizontalAlignment;
+ data.verticalAlignment = verticalAlignment;
mCellData[ row ][ column ] = data;
// Don't continue
+ RelayoutRequest();
return;
}
}
data.actor = child;
data.position.rowIndex = rowCount;
data.position.columnIndex = 0;
+ data.horizontalAlignment = horizontalAlignment;
+ data.verticalAlignment = verticalAlignment;
mCellData[ rowCount ][ 0 ] = data;
+ RelayoutRequest();
}
void TableView::OnControlChildRemove( Actor& child )
void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
void(TableView::*funcFixed)(unsigned int, float),
void(TableView::*funcRelative)(unsigned int, float),
+ void(TableView::*funcFit)(unsigned int),
const Property::Value& value )
{
- if( Property::MAP == value.GetType() )
+ Property::Map* map = value.GetMap();
+ if( map )
{
- Property::Map map = value.Get<Property::Map>();
- unsigned int rowIndex(0);
- for ( unsigned int i = 0, count = map.Count(); i < count; ++i )
+ unsigned int index(0);
+ for ( unsigned int i = 0, count = map->Count(); i < count; ++i )
{
- Property::Value& item = map.GetValue(i);
+ Property::Value& item = map->GetValue(i);
+ Property::Map* childMap = item.GetMap();
- if( std::istringstream(map.GetKey(i)) >> rowIndex // the key is a number
- && Property::MAP == item.GetType())
+ std::istringstream( map->GetKey(i) ) >> index;
+ if( childMap )
{
- if( item.HasKey( "policy" ) && item.HasKey( "value" ) )
+ Property::Value* policy = childMap->Find( "policy" );
+ Property::Value* value = childMap->Find( "value" );
+ if( policy && value )
{
- Toolkit::TableView::LayoutPolicy policy = Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( item.GetValue("policy").Get<std::string>().c_str(), LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT );
- if( policy == Toolkit::TableView::FIXED )
+ std::string policyValue;
+ policy->Get( policyValue );
+ Toolkit::TableView::LayoutPolicy policy;
+ if( Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( policyValue.c_str(),
+ LAYOUT_POLICY_STRING_TABLE,
+ LAYOUT_POLICY_STRING_TABLE_COUNT,
+ policy ) )
{
- (tableViewImpl.*funcFixed)( rowIndex, item.GetValue("value").Get<float>() );
- }
- else if( policy == Toolkit::TableView::RELATIVE )
- {
- (tableViewImpl.*funcRelative)( rowIndex, item.GetValue("value").Get<float>() );
+ if( policy == Toolkit::TableView::FIXED )
+ {
+ (tableViewImpl.*funcFixed)( index, value->Get<float>() );
+ }
+ else if( policy == Toolkit::TableView::RELATIVE )
+ {
+ (tableViewImpl.*funcRelative)( index, value->Get<float>() );
+ }
+ else if( policy == Toolkit::TableView::FIT )
+ {
+ (tableViewImpl.*funcFit)( index );
+ }
+ // do nothing for FILL policy
}
}
}
void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map )
{
- std::string fixedPolicy( Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED, LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT ) );
- std::string relativePolicy( Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE, LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT ) );
+ const char* fixedPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED,
+ LAYOUT_POLICY_STRING_TABLE,
+ LAYOUT_POLICY_STRING_TABLE_COUNT );
+ const char* relativePolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE,
+ LAYOUT_POLICY_STRING_TABLE,
+ LAYOUT_POLICY_STRING_TABLE_COUNT );
+ const char* fillPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FILL,
+ LAYOUT_POLICY_STRING_TABLE,
+ LAYOUT_POLICY_STRING_TABLE_COUNT );
+ const char* fitPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIT,
+ LAYOUT_POLICY_STRING_TABLE,
+ LAYOUT_POLICY_STRING_TABLE_COUNT );
const RowColumnArray::SizeType count = data.Size();
for( RowColumnArray::SizeType i = 0; i < count; i++ )
{
const RowColumnData& dataInstance = data[ i ];
+ Property::Map item;
switch( dataInstance.sizePolicy )
{
- case FIXED:
+ case Toolkit::TableView::FIXED:
{
- Property::Map item;
item[ "policy" ] = fixedPolicy;
item[ "value" ] = dataInstance.size;
-
- std::ostringstream ss;
- ss << i;
-
- map[ ss.str() ] = item;
-
break;
}
-
- case FILL:
+ case Toolkit::TableView::RELATIVE:
{
- Property::Map item;
item[ "policy" ] = relativePolicy;
item[ "value" ] = dataInstance.fillRatio;
-
- std::ostringstream ss;
- ss << i;
-
- map[ ss.str() ] = item;
-
break;
}
-
+ case Toolkit::TableView::FIT:
+ {
+ item[ "policy" ] = fitPolicy;
+ item[ "value" ] = 0.f;
+ break;
+ }
+ case Toolkit::TableView::FILL:
default:
{
+ item[ "policy" ] = fillPolicy;
+ item[ "value" ] = 0.f;
break;
}
}
+ std::ostringstream ss;
+ ss << i;
+ map[ ss.str() ] = item;
}
}
}
// Apply padding
- cellSize -= mPadding.width * 2.0f;
+ cellSize -= mPadding.height * 2.0f;
if( cellSize < 0.0f )
{
cellSize = 0.0f;
{
RowColumnData& dataInstance = data[ i ];
- if( dataInstance.sizePolicy == FILL )
+ if( dataInstance.sizePolicy == Toolkit::TableView::RELATIVE )
{
- if( dataInstance.userFillRatio )
- {
- relativeTotal += dataInstance.fillRatio;
- }
- else
- {
- fillData.PushBack( &dataInstance );
- }
+ relativeTotal += dataInstance.fillRatio;
+ }
+ else if(dataInstance.sizePolicy == Toolkit::TableView::FILL)
+ {
+ fillData.PushBack( &dataInstance );
}
}
switch( dataInstance.sizePolicy )
{
- case FIXED:
- case FIT:
+ // we have absolute size to FIXED and FIT column/row and relative size for RELATIVE and FILL column/row
+ case Toolkit::TableView::FIXED:
+ case Toolkit::TableView::FIT:
{
totalSize += dataInstance.size;
break;
{
RowColumnData& dataInstance = data[ i ];
- if( dataInstance.sizePolicy == FIT )
+ if( dataInstance.sizePolicy == Toolkit::TableView::FIT )
{
// Find the size of the biggest actor in the row or column
float maxActorHeight = 0.0f;
{
RowColumnData& dataInstance = data[ i ];
- if( dataInstance.sizePolicy == FILL )
+ if( dataInstance.sizePolicy == Toolkit::TableView::FILL || dataInstance.sizePolicy == Toolkit::TableView::RELATIVE)
{
dataInstance.size = dataInstance.fillRatio * size;
}
{
for( unsigned int i = 0, count = data.Size(); i < count; ++i )
{
- if( data[ i ].sizePolicy == FIT )
+ if( data[ i ].sizePolicy == Toolkit::TableView::FIT )
{
return true;
}
public:
/**
- * Enum for the size policies of rows and columns
- */
- enum CellSizePolicy
- {
- FILL, ///< Fill up available space, may have a ratio associated with it
- FIXED, ///< A specific fixed width or height
- FIT ///< Fit around actors in the row or column
- };
-
- /**
* Create a new TableView.
* @return A smart-pointer to the newly allocated TableView.
*/
Size GetCellPadding();
/**
- * @brief Set a row policy
- *
- * @param[in] rowIndex The row to set the policy for
- * @param[in] policy The policy to set
+ * @copydoc Toolkit::TableView::SetFitHeight
*/
- void SetRowPolicy( unsigned int rowIndex, CellSizePolicy policy );
+ void SetFitHeight( unsigned int rowIndex );
/**
- * @brief Querry a row policy
- *
- * @param[in] rowIndex The row to querry
- * @return Return the policy
+ * @copydoc Toolkit::TableView::IsFitHeight
*/
- CellSizePolicy GetRowPolicy( unsigned int rowIndex ) const;
+ bool IsFitHeight( unsigned int rowIndex ) const;
/**
- * @brief Set a column policy
- *
- * @param[in] columnIndex The column to set the policy for
- * @param[in] policy The policy to set
+ * @copydoc Toolkit::TableView::SetFitWidth
*/
- void SetColumnPolicy( unsigned int columnIndex, CellSizePolicy policy );
+ void SetFitWidth( unsigned int columnIndex );
/**
- * @brief Querry a column policy
- *
- * @param[in] columnIndex The column to querry
- * @return Return the policy
+ * @copydoc Toolkit::TableView::IsFitWidth
*/
- CellSizePolicy GetColumnPolicy( unsigned int columnIndex ) const;
+ bool IsFitWidth( unsigned int columnIndex ) const;
/**
* @copydoc Toolkit::TableView::SetFixedWidth
RowColumnData()
: size( 0.0f ),
fillRatio( 0.0f ),
- sizePolicy( FILL ),
- userFillRatio( false )
+ position(0.0f),
+ sizePolicy( Toolkit::TableView::FILL )
{
}
* @param[in] newSize The size to set for this data
* @param[in] newSizePolicy The policy used to interpret the size value
*/
- RowColumnData( float newSize, float newFillRatio, CellSizePolicy newSizePolicy, bool newUserFillRatio )
+ RowColumnData( float newSize, float newFillRatio, Toolkit::TableView::LayoutPolicy newSizePolicy )
: size( newSize ),
fillRatio( newFillRatio ),
- sizePolicy( newSizePolicy ),
- userFillRatio( newUserFillRatio )
+ position(0.0f),
+ sizePolicy( newSizePolicy )
{
}
- float size; ///< Set or calculated size
- float fillRatio; ///< Ratio to fill remaining space
- CellSizePolicy sizePolicy; ///< The size policy used to interpret the size value
- bool userFillRatio : 1; ///< FillRatio was set by user
+ float size; ///< Set or calculated size
+ float fillRatio; ///< Ratio to fill remaining space, only valid with RELATIVE or FILL policy
+ float position; ///< Position of the row/column, this value is updated during every Relayout round
+ Toolkit::TableView::LayoutPolicy sizePolicy; ///< The size policy used to interpret the size value
};
typedef Dali::Vector<RowColumnData> RowColumnArray;
/**
* Called to set the heights/widths property.
* @param[in] tableViewImpl The object whose property is set.
- * @param[in] funcFixed The set function to call, it can be SetFixedHeight or SetFixedWidths.
- * @param[in] funcRelative The set function to call, it can be SetRelativeHeight or SetRelativeWidths.
+ * @param[in] funcFixed The set function to call, it can be SetFixedHeight or SetFixedWidth.
+ * @param[in] funcRelative The set function to call, it can be SetRelativeHeight or SetRelativeWidth.
+ * @param[in] funcFit The set function to call, it can be SetFitHeight or SetFiltWidth.
* @param[in] value The new property value.
*/
static void SetHeightOrWidthProperty( TableView& tableViewImpl,
void(TableView::*funcFixed)(unsigned int, float),
void(TableView::*funcRelative)(unsigned int, float),
+ void(TableView::*funcFit)(unsigned int),
const Property::Value& map );
/**
private: // Data
- Array2d<CellData> mCellData; ///< Data for each cell: Actor, alignment settings etc
+ Array2d<CellData> mCellData; ///< Data for each cell: Actor, alignment settings etc
RowColumnArray mRowData; ///< Data for each row
RowColumnArray mColumnData; ///< Data for each column
Size mPadding; ///< Padding to apply to each cell
bool mLayoutingChild; ///< Can't be a bitfield due to Relayouting lock
- bool mRowColumnDirty : 1; ///< Flag to indicate the row column data is dirty
+ bool mRowColumnDirty : 1; ///< Flag to indicate the row column data is dirty
};
} // namespace Internal
namespace
{
-const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
+const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
{
{ "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN },
{ "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
};
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[] =
+const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
{
{ "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP },
{ "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER },
const std::string alignStr = value.Get< std::string >();
DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p HORIZONTAL_ALIGNMENT %f\n", impl.mController.Get(), alignStr.c_str() );
- const LayoutEngine::HorizontalAlignment alignment = Scripting::GetEnumeration< LayoutEngine::HorizontalAlignment >( alignStr.c_str(),
- HORIZONTAL_ALIGNMENT_STRING_TABLE,
- HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
-
- impl.mController->SetHorizontalAlignment( alignment );
+ LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN );
+ if( Scripting::GetEnumeration< LayoutEngine::HorizontalAlignment >( alignStr.c_str(),
+ HORIZONTAL_ALIGNMENT_STRING_TABLE,
+ HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
+ alignment ) )
+ {
+ impl.mController->SetHorizontalAlignment( alignment );
+ }
}
break;
}
const std::string alignStr = value.Get< std::string >();
DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p VERTICAL_ALIGNMENT %f\n", impl.mController.Get(), alignStr.c_str() );
- LayoutEngine::VerticalAlignment alignment = Scripting::GetEnumeration< LayoutEngine::VerticalAlignment >( alignStr.c_str(),
- VERTICAL_ALIGNMENT_STRING_TABLE,
- VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
-
- impl.mController->SetVerticalAlignment( alignment );
+ LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM );
+ if( Scripting::GetEnumeration< LayoutEngine::VerticalAlignment >( alignStr.c_str(),
+ VERTICAL_ALIGNMENT_STRING_TABLE,
+ VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
+ alignment ) )
+ {
+ impl.mController->SetVerticalAlignment( alignment );
+ }
}
break;
}
{
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 ) );
+ const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetLayoutEngine().GetHorizontalAlignment(),
+ HORIZONTAL_ALIGNMENT_STRING_TABLE,
+ HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
+ if( name )
+ {
+ value = std::string( name );
+ }
}
break;
}
{
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 ) );
+ const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetLayoutEngine().GetVerticalAlignment(),
+ VERTICAL_ALIGNMENT_STRING_TABLE,
+ VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
+ if( name )
+ {
+ value = std::string( name );
+ }
}
break;
}
mController = Text::Controller::New( *this );
- mDecorator = Text::Decorator::New( *this, *mController );
+ mDecorator = Text::Decorator::New( *mController,
+ *mController );
mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
{
Self().Add( mRenderableActor );
}
+
+ for( std::vector<Actor>::const_iterator it = mClippingDecorationActors.begin(),
+ endIt = mClippingDecorationActors.end();
+ it != endIt;
+ ++it )
+ {
+ Actor actor = *it;
+
+ if( mClipper )
+ {
+ mClipper->GetRootActor().Add( actor );
+ }
+ else
+ {
+ Self().Add( actor );
+ }
+ }
+ mClippingDecorationActors.clear();
}
}
return mController->KeyEvent( event );
}
-ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
+void TextField::AddDecoration( Actor& actor, bool needsClipping )
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
- return mController->OnImfEvent( imfManager, imfEvent );
+ if( actor )
+ {
+ if( needsClipping )
+ {
+ mClippingDecorationActors.push_back( actor );
+ }
+ else
+ {
+ Self().Add( actor );
+ }
+ }
}
void TextField::RequestTextRelayout()
mMaxLengthReachedSignal.Emit( handle );
}
+ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName );
+ return mController->OnImfEvent( imfManager, imfEvent );
+}
+
void TextField::EnableClipping( bool clipping, const Vector2& size )
{
if( clipping )
virtual bool OnKeyEvent(const KeyEvent& event);
/**
- * @copydoc Dali::Toolkit::Text::Controller::(ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent)
+ * @copydoc Text::ControlInterface::AddDecoration()
*/
- ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent );
+ virtual void AddDecoration( Actor& actor, bool needsClipping );
/**
* @copydoc Text::ControlInterface::RequestTextRelayout()
*/
virtual void MaxLengthReached();
+ /**
+ * @copydoc Dali::Toolkit::Text::Controller::(ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent)
+ */
+ ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent );
+
private: // Implementation
/**
Text::RendererPtr mRenderer;
Text::DecoratorPtr mDecorator;
Text::ClipperPtr mClipper; ///< For EXCEED_POLICY_CLIP
+ std::vector<Actor> mClippingDecorationActors; ///< Decoration actors which need clipping.
Actor mRenderableActor;
namespace
{
-const Scripting::StringEnum< Toolkit::Text::LayoutEngine::HorizontalAlignment > HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
+const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
{
{ "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN },
{ "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER },
};
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[] =
+const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
{
{ "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP },
{ "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER },
{
if( impl.mController )
{
- 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 );
-
- impl.mController->SetHorizontalAlignment( alignment );
+ LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN );
+ if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(),
+ HORIZONTAL_ALIGNMENT_STRING_TABLE,
+ HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
+ alignment ) )
+ {
+ impl.mController->SetHorizontalAlignment( alignment );
+ }
}
break;
}
{
if( impl.mController )
{
- 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 );
-
- impl.mController->SetVerticalAlignment( alignment );
+ LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM );
+ if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(),
+ VERTICAL_ALIGNMENT_STRING_TABLE,
+ VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
+ alignment ) )
+ {
+ impl.mController->SetVerticalAlignment( alignment );
+ }
}
break;
}
{
if( impl.mController )
{
- value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
- HORIZONTAL_ALIGNMENT_STRING_TABLE,
- HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ) );
+ const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(),
+ HORIZONTAL_ALIGNMENT_STRING_TABLE,
+ HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT );
+ if( name )
+ {
+ value = std::string( name );
+ }
}
break;
}
{
if( impl.mController )
{
- value = std::string( Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(),
- VERTICAL_ALIGNMENT_STRING_TABLE,
- VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ) );
+ const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(),
+ VERTICAL_ALIGNMENT_STRING_TABLE,
+ VERTICAL_ALIGNMENT_STRING_TABLE_COUNT );
+ if( name )
+ {
+ value = std::string( name );
+ }
}
break;
}
}
}
+void TextLabel::AddDecoration( Actor& actor, bool needsClipping )
+{
+ // TextLabel does not show decorations
+}
+
void TextLabel::OnStageConnection( unsigned int depth )
{
mDepth = depth;
virtual float GetHeightForWidth( float width );
/**
+ * @copydoc Text::ControlInterface::AddDecoration()
+ */
+ virtual void AddDecoration( Actor& actor, bool needsClipping );
+
+ /**
* @copydoc Control::OnStageConnection()
*/
virtual void OnStageConnection( unsigned int depth );
#include <dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/controls/buttons/push-button.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
#include <dali-toolkit/public-api/controls/control-depth-index-ranges.h>
#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
#include <dali-toolkit/public-api/controls/text-controls/text-label.h>
#include <dali/public-api/images/resource-image.h>
#include <dali/public-api/math/vector2.h>
#include <dali/public-api/math/vector4.h>
+#include <dali/devel-api/object/type-registry-helper.h>
#include <libintl.h>
#include <cfloat>
-// todo Move this to adaptor??
-#define GET_LOCALE_TEXT(string) dgettext("elementary", string)
-
namespace Dali
{
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 ) );
+// todo Move this to adaptor??
+#define GET_LOCALE_TEXT(string) dgettext("elementary", string)
+
+const Dali::Vector4 DEFAULT_POPUP_LINE_COLOR( Dali::Vector4( 0.69f, 0.93f, 0.93f, 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 Dali::Vector4 DEFAULT_OPTION_ICON_PRESSED( Dali::Vector4( 0.12f, 0.56f, 1.0f, 1.0f ) );
-const std::string DEFAULT_POPUP_BACKGROUND_IMAGE( DALI_IMAGE_DIR "popup_bubble_bg.#.png" );
+const std::string DEFAULT_POPUP_BACKGROUND_IMAGE( DALI_IMAGE_DIR "selection-popup-bg#.png" );
const std::string OPTION_ICON_CLIPBOARD( DALI_IMAGE_DIR "copy_paste_icon_clipboard.png" );
const std::string OPTION_ICON_COPY( DALI_IMAGE_DIR "copy_paste_icon_copy.png" );
const std::string OPTION_ICON_CUT( DALI_IMAGE_DIR "copy_paste_icon_cut.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).
+#ifdef DGETTEXT_ENABLED
+
+#define POPUP_CUT_STRING GET_LOCALE_TEXT("IDS_COM_BODY_CUT")
+#define POPUP_COPY_STRING GET_LOCALE_TEXT("IDS_COM_BODY_COPY")
+#define POPUP_PASTE_STRING GET_LOCALE_TEXT("IDS_COM_BODY_PASTE")
+#define POPUP_SELECT_STRING GET_LOCALE_TEXT("IDS_COM_SK_SELECT")
+#define POPUP_SELECT_ALL_STRING GET_LOCALE_TEXT("IDS_COM_BODY_SELECT_ALL")
+#define POPUP_CLIPBOARD_STRING GET_LOCALE_TEXT("IDS_COM_BODY_CLIPBOARD")
+
+#else
-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.
+#define POPUP_CUT_STRING "Cut"
+#define POPUP_COPY_STRING "Copy"
+#define POPUP_PASTE_STRING "Paste"
+#define POPUP_SELECT_STRING "Select"
+#define POPUP_SELECT_ALL_STRING "Select All"
+#define POPUP_CLIPBOARD_STRING "Clipboard"
+
+#endif
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_PASTE("option-paste"); // "Paste" popup option.
const char* const OPTION_CLIPBOARD("option-clipboard"); // "Clipboard" popup option.
-} // namespace
+BaseHandle Create()
+{
+ return Toolkit::TextSelectionPopup::New( Toolkit::TextSelectionPopup::NONE, NULL );
+}
+
+// Setup properties, signals and actions using the type-registry.
+
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextSelectionPopup, Toolkit::Control, Create );
-//// Comparison function for ButtonRequirement Priority
-//bool TextSelectionPopup::PriorityCompare( ButtonRequirement const& a, ButtonRequirement const& b )
-//{
-// return a.priority < b.priority;
-//}
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-max-size", VECTOR2, POPUP_MAX_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-min-size", VECTOR2, POPUP_MIN_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "option-max-size", VECTOR2, OPTION_MAX_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "option-min-size", VECTOR2, OPTION_MIN_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "option-divider-size", VECTOR2, OPTION_DIVIDER_SIZE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-clipboard-button-image", STRING, POPUP_CLIPBOARD_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-cut-button-image", STRING, POPUP_CUT_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-copy-button-image", STRING, POPUP_COPY_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-paste-button-image", STRING, POPUP_PASTE_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-select-button-image", STRING, POPUP_SELECT_BUTTON_ICON_IMAGE )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionPopup, "popup-select-all-button-image", STRING, POPUP_SELECT_ALL_BUTTON_ICON_IMAGE )
+DALI_TYPE_REGISTRATION_END()
-Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New()
+} // namespace
+
+
+Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New( Toolkit::TextSelectionPopup::Buttons buttonsToEnable,
+ TextSelectionPopupCallbackInterface* callbackInterface )
{
- // Create the implementation, temporarily owned by this handle on stack
- IntrusivePtr< TextSelectionPopup > impl = new TextSelectionPopup();
+ // Create the implementation, temporarily owned by this handle on stack
+ IntrusivePtr< TextSelectionPopup > impl = new TextSelectionPopup( callbackInterface );
// Pass ownership to CustomActor handle
Dali::Toolkit::TextSelectionPopup handle( *impl );
+ impl->mEnabledButtons = buttonsToEnable;
+
// Second-phase init of the implementation
// This can only be done after the CustomActor connection has been made...
impl->Initialize();
{
case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE:
{
- impl.SetPopupMaxSize( value.Get< Vector2 >() );
+ impl.SetDimensionToCustomise( POPUP_MAXIMUM_SIZE, value.Get< Vector2 >() );
break;
}
- case Toolkit::TextSelectionPopup::Property::POPUP_BACKGROUND_IMAGE:
+ case Toolkit::TextSelectionPopup::Property::POPUP_MIN_SIZE:
{
- ResourceImage image = ResourceImage::New( value.Get< std::string >() );
- impl.SetPopupImage( POPUP_BACKGROUND, image );
+ impl.SetDimensionToCustomise( POPUP_MINIMUM_SIZE, value.Get< Vector2 >() );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::Property::OPTION_MAX_SIZE:
+ {
+ impl.SetDimensionToCustomise( OPTION_MAXIMUM_SIZE, value.Get< Vector2 >() );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::Property::OPTION_MIN_SIZE:
+ {
+ impl.SetDimensionToCustomise( OPTION_MINIMUM_SIZE, value.Get< Vector2>() );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::Property::OPTION_DIVIDER_SIZE:
+ {
+ impl.SetDimensionToCustomise( OPTION_DIVIDER_SIZE, value.Get< Vector2>() );
break;
}
case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE:
{
ResourceImage image = ResourceImage::New( value.Get< std::string >() );
- impl.SetPopupImage( POPUP_CLIPBOARD_BUTTON, image );
+ impl.SetButtonImage( Toolkit::TextSelectionPopup::CLIPBOARD, 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 );
+ impl.SetButtonImage( Toolkit::TextSelectionPopup::CUT, 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 );
+ impl.SetButtonImage( Toolkit::TextSelectionPopup::COPY, 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 );
+ impl.SetButtonImage( Toolkit::TextSelectionPopup::PASTE, 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 );
+ impl.SetButtonImage( Toolkit::TextSelectionPopup::SELECT, 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 );
+ impl.SetButtonImage( Toolkit::TextSelectionPopup::SELECT_ALL, image );
break;
}
} // switch
{
case Toolkit::TextSelectionPopup::Property::POPUP_MAX_SIZE:
{
- value = impl.GetPopupMaxSize();
+ value = impl.GetDimensionToCustomise( POPUP_MAXIMUM_SIZE );
break;
}
- case Toolkit::TextSelectionPopup::Property::POPUP_BACKGROUND_IMAGE:
+ case Toolkit::TextSelectionPopup::Property::OPTION_MAX_SIZE:
{
- ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_BACKGROUND ) );
- if( image )
- {
- value = image.GetUrl();
- }
+ value = impl.GetDimensionToCustomise( OPTION_MAXIMUM_SIZE );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::Property::OPTION_MIN_SIZE:
+ {
+ value = impl.GetDimensionToCustomise( OPTION_MINIMUM_SIZE );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::Property::OPTION_DIVIDER_SIZE:
+ {
+ value = impl.GetDimensionToCustomise( OPTION_DIVIDER_SIZE );
break;
}
case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE:
{
- ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_CLIPBOARD_BUTTON ) );
+ ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::CLIPBOARD ) );
if( image )
{
value = image.GetUrl();
}
case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE:
{
- ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_CUT_BUTTON_ICON ) );
+ ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::CUT ) );
if( image )
{
value = image.GetUrl();
}
case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE:
{
- ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_COPY_BUTTON_ICON ) );
+ ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::COPY ) );
if( image )
{
value = image.GetUrl();
}
case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE:
{
- ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_PASTE_BUTTON_ICON ) );
+ ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::PASTE ) );
if( image )
{
value = image.GetUrl();
}
case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE:
{
- ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_SELECT_BUTTON_ICON ) );
+ ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::SELECT ) );
if( image )
{
value = image.GetUrl();
}
case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE:
{
- ResourceImage image = ResourceImage::DownCast( impl.GetPopupImage( POPUP_SELECT_ALL_BUTTON_ICON ) );
+ ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::SELECT_ALL ) );
if( image )
{
value = image.GetUrl();
CreatePopup();
}
-void TextSelectionPopup::OnRelayout( const Vector2& size, RelayoutContainer& container )
+bool TextSelectionPopup::OnCutButtonPressed( Toolkit::Button button )
{
+ if( mCallbackInterface )
+ {
+ mCallbackInterface->TextPopupButtonTouched( Toolkit::TextSelectionPopup::CUT );
+ }
+ return true;
}
-void TextSelectionPopup::SetPopupMaxSize( const Size& maxSize )
+bool TextSelectionPopup::OnCopyButtonPressed( Toolkit::Button button )
{
- mMaxSize = maxSize;
+ if( mCallbackInterface )
+ {
+ mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::COPY );
+ }
+
+ return true;
}
-const Dali::Vector2& TextSelectionPopup::GetPopupMaxSize() const
+bool TextSelectionPopup::OnPasteButtonPressed( Toolkit::Button button )
{
- return mMaxSize;
+ if( mCallbackInterface )
+ {
+ mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::PASTE );
+ }
+
+ return true;
}
-void TextSelectionPopup::SetPopupImage( PopupParts part, Dali::Image image )
+bool TextSelectionPopup::OnSelectButtonPressed( Toolkit::Button button )
{
- switch ( part )
- {
- case POPUP_BACKGROUND :
+ if( mCallbackInterface )
+ {
+ mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::SELECT );
+ }
+
+ return true;
+}
+
+bool TextSelectionPopup::OnSelectAllButtonPressed( Toolkit::Button button )
+{
+ if( mCallbackInterface )
+ {
+ mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::SELECT_ALL );
+ }
+
+ return true;
+}
+
+bool TextSelectionPopup::OnClipboardButtonPressed( Toolkit::Button button )
+{
+ if( mCallbackInterface )
+ {
+ mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::CLIPBOARD );
+ }
+
+ return true;
+}
+
+void TextSelectionPopup::SetDimensionToCustomise( const PopupCustomisations& settingToCustomise, const Size& dimension )
+{
+ switch( settingToCustomise )
+ {
+ case POPUP_MAXIMUM_SIZE :
+ {
+ Actor self = Self();
+ mMaxSize = dimension;
+ if ( mToolbar )
+ {
+ mToolbar.SetProperty( Toolkit::TextSelectionToolbar::Property::MAX_SIZE, mMaxSize );
+ }
+ break;
+ }
+ case POPUP_MINIMUM_SIZE :
+ {
+ Actor self = Self();
+ mMinSize = dimension;
+ // Option can not be smaller than this if only one.
+ break;
+ }
+ case OPTION_MAXIMUM_SIZE :
+ {
+ mOptionMaxSize = dimension;
+ // Option max size not currently currently supported
+
+ break;
+ }
+ case OPTION_MINIMUM_SIZE :
+ {
+ mOptionMinSize = dimension;
+ // Option min size not currently currently supported
+ break;
+ }
+ case OPTION_DIVIDER_SIZE :
+ {
+ mOptionDividerSize = dimension;
+ if ( mToolbar )
+ {
+ // Resize Dividers not currently supported
+ }
+ break;
+ }
+ } // switch
+}
+
+Size TextSelectionPopup::GetDimensionToCustomise( const PopupCustomisations& settingToCustomise )
+{
+ switch( settingToCustomise )
+ {
+ case POPUP_MAXIMUM_SIZE :
+ {
+ return mMaxSize;
+ }
+ case POPUP_MINIMUM_SIZE :
+ {
+ return mMinSize;
+ }
+ case OPTION_MAXIMUM_SIZE :
+ {
+ return mOptionMaxSize;
+ }
+ case OPTION_MINIMUM_SIZE :
+ {
+ return mOptionMinSize;
+ }
+ case OPTION_DIVIDER_SIZE :
+ {
+ return mOptionDividerSize;
+ }
+ } // switch
+
+ return Size::ZERO;
+}
+
+void TextSelectionPopup::SetButtonImage( Toolkit::TextSelectionPopup::Buttons button, Dali::Image image )
+{
+ switch ( button )
{
- mBackgroundImage = image;
- }
break;
- case POPUP_CLIPBOARD_BUTTON :
+ case Toolkit::TextSelectionPopup::CLIPBOARD:
{
mClipboardIconImage = image;
}
break;
- case POPUP_CUT_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::CUT :
{
mCutIconImage = image;
}
break;
- case POPUP_COPY_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::COPY :
{
mCopyIconImage = image;
}
break;
- case POPUP_PASTE_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::PASTE :
{
mPasteIconImage = image;
}
break;
- case POPUP_SELECT_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::SELECT :
{
mSelectIconImage = image;
}
break;
- case POPUP_SELECT_ALL_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::SELECT_ALL :
{
mSelectAllIconImage = image;
}
break;
-
+ default :
+ {
+ DALI_ASSERT_DEBUG( "TextSelectionPopup SetPopupImage Unknown Button" );
+ }
} // switch
}
-Dali::Image TextSelectionPopup::GetPopupImage( PopupParts part )
+Dali::Image TextSelectionPopup::GetButtonImage( Toolkit::TextSelectionPopup::Buttons button )
{
- switch ( part )
+ switch ( button )
{
- case POPUP_BACKGROUND :
- {
- return mBackgroundImage;
- }
- break;
- case POPUP_CLIPBOARD_BUTTON :
+ case Toolkit::TextSelectionPopup::CLIPBOARD :
{
return mClipboardIconImage;
}
break;
- case POPUP_CUT_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::CUT :
{
return mCutIconImage;
}
break;
- case POPUP_COPY_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::COPY :
{
return mCopyIconImage;
}
break;
- case POPUP_PASTE_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::PASTE :
{
return mPasteIconImage;
}
break;
- case POPUP_SELECT_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::SELECT :
{
return mSelectIconImage;
}
break;
- case POPUP_SELECT_ALL_BUTTON_ICON :
+ case Toolkit::TextSelectionPopup::SELECT_ALL :
{
return mSelectAllIconImage;
}
break;
default :
{
- DALI_ASSERT_DEBUG( "Unknown Popup Part" );
+ DALI_ASSERT_DEBUG( "TextSelectionPopup GetPopupImage Unknown Button" );
}
} // switch
{
mCutIconImage = ResourceImage::New( OPTION_ICON_CUT );
}
- mOrderListOfButtons.push_back( ButtonRequirement( ButtonsCut, mCutOptionPriority, OPTION_CUT, GET_LOCALE_TEXT("IDS_COM_BODY_CUT"), mCutIconImage, true ) );
+ mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::CUT, mCutOptionPriority, OPTION_CUT, POPUP_CUT_STRING , mCutIconImage, ( mEnabledButtons & Toolkit::TextSelectionPopup::CUT) ) );
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 ) );
+ mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::COPY, mCopyOptionPriority, OPTION_COPY, POPUP_COPY_STRING, mCopyIconImage, ( mEnabledButtons & Toolkit::TextSelectionPopup::COPY) ) );
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 ) );
+ mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::PASTE, mPasteOptionPriority, OPTION_PASTE, POPUP_PASTE_STRING, mPasteIconImage, ( mEnabledButtons & Toolkit::TextSelectionPopup::PASTE) ) );
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 ) );
+ mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::SELECT, mSelectOptionPriority, OPTION_SELECT_WORD, POPUP_SELECT_STRING, mSelectIconImage, ( mEnabledButtons & Toolkit::TextSelectionPopup::SELECT) ) );
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 ) );
+ mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::SELECT_ALL, mSelectAllOptionPriority, OPTION_SELECT_ALL, POPUP_SELECT_ALL_STRING, mSelectAllIconImage, ( mEnabledButtons & Toolkit::TextSelectionPopup::SELECT_ALL) ) );
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 ) );
+ mOrderListOfButtons.push_back( ButtonRequirement( Toolkit::TextSelectionPopup::CLIPBOARD, mClipboardOptionPriority, OPTION_CLIPBOARD, POPUP_CLIPBOARD_STRING, mClipboardIconImage, ( mEnabledButtons & Toolkit::TextSelectionPopup::CLIPBOARD) ) );
// Sort the buttons according their priorities.
std::sort( mOrderListOfButtons.begin(), mOrderListOfButtons.end(), TextSelectionPopup::ButtonPriorityCompare() );
}
- void TextSelectionPopup::CreateBackground()
+ void TextSelectionPopup::AddOption( const ButtonRequirement& button, bool showDivider, bool showIcons, bool showCaption )
{
- if ( mBackgroundImage )
- {
- SetBackgroundImage ( mBackgroundImage );
- }
- SetBackgroundColor( mBackgroundColor );
- }
+ const std::string& name = button.name;
+ const std::string& caption = button.caption;
+ Image iconImage = button.icon;
- 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.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
- optionContainer.SetMinimumSize( Vector2( OPTION_MIN_WIDTH, 0 ) );
+ Toolkit::TableView optionContainer = Toolkit::TableView::New( (showIcons&showCaption)?2:1 , 1 );
+ optionContainer.SetFitHeight( 0 );
optionContainer.SetFitWidth( 0 );
- Toolkit::TableView optionPressedContainer = Toolkit::TableView::New( (showIcons)?2:1 , 1 );
- optionPressedContainer.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
- optionPressedContainer.SetMinimumSize( Vector2( OPTION_MIN_WIDTH, 0 ) );
+ Toolkit::TableView optionPressedContainer = Toolkit::TableView::New( (showIcons&showCaption)?2:1 , 1 );
+ optionPressedContainer.SetFitHeight( 0 );
optionPressedContainer.SetFitWidth( 0 );
+ optionPressedContainer.SetBackgroundColor( mPressedColor );
+
#ifdef DECORATOR_DEBUG
optionContainer.SetName("optionContainer");
optionPressedContainer.SetName("optionPressedContainer");
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
+ Toolkit::TextLabel captionTextLabel = Toolkit::TextLabel::New();
+ captionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption );
+ captionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+
+ Toolkit::TextLabel pressedCaptionTextLabel = Toolkit::TextLabel::New();
+ pressedCaptionTextLabel.SetProperty( Toolkit::TextLabel::Property::TEXT, caption );
+ pressedCaptionTextLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+
+ Padding padding;
+ padding.left = 24.0f;
+ padding.right = 24.0f;
+ padding.top = 14.0f;
+ padding.bottom = 14.0f;
+ captionTextLabel.SetPadding( padding );
+ pressedCaptionTextLabel.SetPadding( padding );
+
+ optionContainer.AddChild( captionTextLabel, Toolkit::TableView::CellPosition(( showIcons&showCaption)?1:0, 0 ) );
+ optionPressedContainer.AddChild( pressedCaptionTextLabel, Toolkit::TableView::CellPosition(( showIcons&showCaption)?1:0, 0 ) );
}
+ // 3. Create the icons
if ( showIcons )
{
- // 3. Create the icons
ImageActor pressedIcon = ImageActor::New( iconImage );
ImageActor icon = ImageActor::New( iconImage );
icon.SetSortModifier( DECORATION_DEPTH_INDEX - 1 );
pressedIcon.SetSortModifier( DECORATION_DEPTH_INDEX - 1 );
- 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 );
+ icon.SetColor( mIconColor );
+
+ if ( showCaption & showIcons )
+ {
+ optionContainer.SetFitHeight( 1 );
+ optionContainer.SetFitWidth( 1 );
+ optionPressedContainer.SetFitHeight( 1 );
+ optionPressedContainer.SetFitWidth( 1 );
+ }
+
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.
+ // 4. Create a option.
Toolkit::PushButton option = Toolkit::PushButton::New();
option.SetName( name );
option.SetAnimationTime( 0.0f );
- option.SetSize( OPTION_ICON_SIZE );
- //option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed );
+ option.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
- // 6. Set the normal option image.
+ switch( button.id )
+ {
+ case Toolkit::TextSelectionPopup::CUT:
+ {
+ option.ClickedSignal().Connect( this, &TextSelectionPopup::OnCutButtonPressed );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::COPY:
+ {
+ option.ClickedSignal().Connect( this, &TextSelectionPopup::OnCopyButtonPressed );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::PASTE:
+ {
+ option.ClickedSignal().Connect( this, &TextSelectionPopup::OnPasteButtonPressed );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::SELECT:
+ {
+ option.ClickedSignal().Connect( this, &TextSelectionPopup::OnSelectButtonPressed );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::SELECT_ALL:
+ {
+ option.ClickedSignal().Connect( this, &TextSelectionPopup::OnSelectAllButtonPressed );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::CLIPBOARD:
+ {
+ option.ClickedSignal().Connect( this, &TextSelectionPopup::OnClipboardButtonPressed );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::NONE:
+ {
+ // Nothing to do:
+ break;
+ }
+ }
+
+ // 5. Set the normal option image.
option.SetButtonImage( optionContainer );
- // 7. Set the pressed option image
+ // 6. 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++;
+ // 7 Add option to tool bar
+ mToolbar.AddOption( option );
- // 10. Add the divider
- if( !finalOption )
+ // 8. Add the divider
+ if( showDivider )
{
- const Size size( POPUP_DIVIDER_WIDTH, 0.0f ); // Height FILL_TO_PARENT
+ const Size size( mOptionDividerSize.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++;
+ divider.SetColor( mLineColor );
+ mToolbar.AddDivider( divider );
}
}
- 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 );
-
- 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 )
+ std::size_t TextSelectionPopup::GetNumberOfEnabledOptions()
{
- 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<ButtonRequirement>::const_iterator it = mOrderListOfButtons.begin(), endIt = mOrderListOfButtons.end(); ( it != endIt ); ++it )
{
}
}
- // 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 );
+ return numberOfOptions;
+ }
+ void TextSelectionPopup::AddPopupOptionsToToolbar( bool showIcons, bool showCaptions )
+ {
+ // Iterate list of buttons and add active ones to Toolbar
+ std::size_t numberOfOptionsRequired = GetNumberOfEnabledOptions();
+ std::size_t numberOfOptionsAdded = 0u;
for( std::vector<ButtonRequirement>::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
+ numberOfOptionsAdded++;
+ AddOption( button, ( numberOfOptionsAdded < numberOfOptionsRequired ) , showIcons, showCaptions );
}
}
}
void TextSelectionPopup::CreatePopup()
{
- if ( !mStencilLayer )
+ Actor self = Self();
+ CreateOrderedListOfPopupOptions(); //todo Currently causes all options to be shown
+ self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+ SetBackgroundImage( NinePatchImage::New( DEFAULT_POPUP_BACKGROUND_IMAGE ) );
+
+ if ( !mToolbar )
{
- 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();
+ mToolbar = Toolkit::TextSelectionToolbar::New();
+ mToolbar.SetParentOrigin( ParentOrigin::CENTER );
+ mToolbar.SetProperty( Toolkit::TextSelectionToolbar::Property::MAX_SIZE, mMaxSize );
+ self.Add( mToolbar );
+ AddPopupOptionsToToolbar( mShowIcons, mShowCaptions );
}
-
- mStencilLayer.RaiseToTop();
}
-TextSelectionPopup::TextSelectionPopup()
-: Control( ControlBehaviour( ControlBehaviour( ACTOR_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 ),
+TextSelectionPopup::TextSelectionPopup( TextSelectionPopupCallbackInterface* callbackInterface )
+: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ),
+ mToolbar(),
+ mMaxSize(),
+ mMinSize(),
+ mOptionDividerSize( Size( 2.0f, 0.0f) ),
+ mEnabledButtons( Toolkit::TextSelectionPopup::NONE ),
+ mCallbackInterface( callbackInterface ),
mLineColor( DEFAULT_POPUP_LINE_COLOR ),
mIconColor( DEFAULT_OPTION_ICON ),
- mIconPressedColor( DEFAULT_OPTION_ICON_PRESSED ),
- mTextColor( DEFAULT_OPTION_TEXT ),
- mTextPressedColor( DEFAULT_OPTION_TEXT_PRESSED ),
+ mPressedColor( DEFAULT_OPTION_ICON_PRESSED ),
mSelectOptionPriority( 1 ),
mSelectAllOptionPriority ( 2 ),
mCutOptionPriority ( 3 ),
mCopyOptionPriority ( 4 ),
mPasteOptionPriority ( 5 ),
mClipboardOptionPriority( 6 ),
- mShowIcons( true ),
- mShowCaptions( false )
+ mShowIcons( false ),
+ mShowCaptions( true )
{
}
} // namespace Toolkit
} // namespace Dali
+
+
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/buttons/push-button.h>
#include <dali-toolkit/public-api/controls/table-view/table-view.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
// EXTERNAL INCLUDES
#include <dali/public-api/actors/image-actor.h>
namespace
{
-enum PopupParts
+
+enum PopupCustomisations
{
- 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,
+ POPUP_MAXIMUM_SIZE,
+ POPUP_MINIMUM_SIZE,
+ OPTION_MAXIMUM_SIZE,
+ OPTION_MINIMUM_SIZE,
+ OPTION_DIVIDER_SIZE
};
} // namespace
{
public:
- enum Buttons
- {
- ButtonsCut,
- ButtonsCopy,
- ButtonsPaste,
- ButtonsSelect,
- ButtonsSelectAll,
- ButtonsClipboard,
- ButtonsEnumEnd
- };
-
struct ButtonRequirement
{
ButtonRequirement()
- : id( ButtonsEnumEnd ),
+ : id( Toolkit::TextSelectionPopup::NONE ),
priority( 0u ),
name(),
caption(),
enabled( false )
{}
- ButtonRequirement( Buttons buttonId,
+ ButtonRequirement( Toolkit::TextSelectionPopup::Buttons buttonId,
std::size_t buttonPriority,
const std::string& buttonName,
const std::string& buttonCaption,
enabled( buttonEnabled )
{}
- Buttons id;
+ Toolkit::TextSelectionPopup::Buttons id;
std::size_t priority;
std::string name;
std::string caption;
}
};
-// static inline bool ButtonPriorityCompare( ButtonRequirement a, ButtonRequirement b )
-// {
-// return a.priority < b.priority ? true : false;
-// }
-
/**
- * @copydoc Dali::Toollkit::TextSelectionPopup::New()
+ * @brief New constructor with provided buttons to enable.
+ * @param[in] buttonsToEnable bit mask of buttons to enable
+ * @param[in] callbackInterface The text popup callback interface which receives the button click callbacks.
+ * @return A handle to the TextSelectionPopup control.
*/
- static Toolkit::TextSelectionPopup New();
+ static Toolkit::TextSelectionPopup New( Toolkit::TextSelectionPopup::Buttons buttonsToEnable,
+ TextSelectionPopupCallbackInterface* callbackInterface );
// Properties
*/
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 );
+ virtual void OnInitialize();
+
+private: // Implementation
/**
- * @copydoc Control::OnInitialize()
+ * @brief When the cut button is pressed.
+ * @param[in] button the button pressed
+ * @return @e true to consume the event.
*/
- 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();
+ bool OnCutButtonPressed( Toolkit::Button button );
/**
- * Set max size of Popup
- * @param[in] maxSize Size (Vector2)
+ * @brief When the copy button is pressed.
+ * @param[in] button the button pressed
+ * @return @e true to consume the event.
*/
- void SetPopupMaxSize( const Size& maxSize );
+ bool OnCopyButtonPressed( Toolkit::Button button );
/**
- * Get Max size of Popup
- * @return Vector2 the max size of the Popup
+ * @brief When the paste button is pressed.
+ * @param[in] button the button pressed
+ * @return @e true to consume the event.
*/
- const Dali::Vector2& GetPopupMaxSize() const;
+ bool OnPasteButtonPressed( Toolkit::Button button );
/**
- * @brief Sets the image for the given part of the Popup.
+ * @brief When the select button is pressed.
+ * @param[in] button the button pressed
+ * @return @e true to consume the event.
+ */
+ bool OnSelectButtonPressed( Toolkit::Button button );
+
+ /**
+ * @brief When the select all button is pressed.
+ * @param[in] button the button pressed
+ * @return @e true to consume the event.
+ */
+ bool OnSelectAllButtonPressed( Toolkit::Button button );
+
+ /**
+ * @brief When the clipboard button is pressed.
+ * @param[in] button the button pressed
+ * @return @e true to consume the event.
+ */
+ bool OnClipboardButtonPressed( Toolkit::Button button );
+
+ /**
+ * @brief Method to set the dimension or dimension constraint on certain aspects of the Popup.
+ *
+ * @param[in] settingToCustomise The setting for the PopupCustomisations enum that can be customised
+ * @param[in] dimension The size to customise with
+ */
+ void SetDimensionToCustomise( const PopupCustomisations& settingToCustomise, const Size& dimension );
+
+ /**
+ * @brief Method to get the dimension or dimension constraint on certain aspects of the Popup that was previously customised
+ *
+ * @param[in] setting The setting from the PopupCustomisations enum
+ */
+ Size GetDimensionToCustomise( const PopupCustomisations& setting );
+
+ /**
+ * @brief Sets the image for the given button of the Popup.
*
- * @param[in] part The part of the pop from the Enum PopupParts
+ * @param[in] button The button the image should be used for from the Buttons Enum.
* @param[in] image The image to use.
*/
- void SetPopupImage( PopupParts part, Dali::Image image );
+ void SetButtonImage( Toolkit::TextSelectionPopup::Buttons button, Dali::Image image );
/**
- * @brief Retrieves the image of the given part used by the popup
+ * @brief Retrieves the image of the given button used by the popup
*
- * @param[in] part The part of the popup
- * @return The image used for that part.
+ * @param[in] button The button to get the image from
+ * @return The image used for that button.
*/
- Dali::Image GetPopupImage( PopupParts part );
+ Dali::Image GetButtonImage( Toolkit::TextSelectionPopup::Buttons button );
void CreateOrderedListOfPopupOptions();
- void CreateBackground();
+ void AddOption( const ButtonRequirement& button, bool showDivider, bool showIcons, bool showCaption );
- 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 );
+ std::size_t GetNumberOfEnabledOptions();
- void SetUpPopup();
+ void AddPopupOptionsToToolbar( bool showIcons, bool showCaptions );
- void AddPopupOptions( bool createTail, bool showIcons, bool showCaptions );
-
-private: // Implementation
+ void CreatePopup();
/**
* Construct a new TextField.
*/
- TextSelectionPopup();
+ TextSelectionPopup( TextSelectionPopupCallbackInterface* callbackInterface );
/**
* A reference counted object may only be deleted by calling Unreference()
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;
+ Dali::Toolkit::TextSelectionToolbar mToolbar;
+
+ Dali::Toolkit::TableView mTableOfButtons; // Actor which holds all the buttons, sensitivity can be set on buttons via this actor
+
+ // Images to be used by the Popup buttons
Image mCutIconImage;
Image mCopyIconImage;
Image mPasteIconImage;
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; // Maximum size of the Popup
+ Size mMinSize; // Minimum size of the Popup
- 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.
+ Size mOptionMaxSize; // Maximum size of an Option button
+ Size mOptionMinSize; // Minimum size of an Option button
+ Size mOptionDividerSize; // Size of divider line
std::vector<ButtonRequirement> 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.
+ Toolkit::TextSelectionPopup::Buttons mEnabledButtons; // stores enabled buttons
+ Toolkit::TextSelectionPopupCallbackInterface* mCallbackInterface;
+
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.
+ Vector4 mPressedColor; // Color of the popup option 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 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
+ bool mShowIcons:1; // Flag to show icons
+ bool mShowCaptions:1; // Flag to show text captions
};
} // namespace Dali
#endif // __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_POPUP_H__
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/devel-api/object/type-registry-helper.h>
+#include <cfloat>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+const Dali::Vector2 DEFAULT_MAX_SIZE( 400.0f, 65.0f ); ///< The maximum size of the Toolbar.
+
+BaseHandle Create()
+{
+ return Toolkit::TextSelectionToolbar::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TextSelectionToolbar, Toolkit::Control, Create );
+
+DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionToolbar, "max-size", VECTOR2, MAX_SIZE )
+
+DALI_TYPE_REGISTRATION_END()
+
+} // namespace
+
+Dali::Toolkit::TextSelectionToolbar TextSelectionToolbar::New()
+{
+ // Create the implementation, temporarily owned by this handle on stack
+ IntrusivePtr< TextSelectionToolbar > impl = new TextSelectionToolbar();
+
+ // Pass ownership to CustomActor handle
+ Dali::Toolkit::TextSelectionToolbar 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 TextSelectionToolbar::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+ Toolkit::TextSelectionToolbar selectionPopup = Toolkit::TextSelectionToolbar::DownCast( Dali::BaseHandle( object ) );
+
+ if( selectionPopup )
+ {
+ TextSelectionToolbar& impl( GetImpl( selectionPopup ) );
+
+ switch( index )
+ {
+ case Toolkit::TextSelectionToolbar::Property::MAX_SIZE:
+ {
+ impl.SetPopupMaxSize( value.Get< Vector2 >() );
+ break;
+ }
+
+ } // switch
+ } // TextSelectionToolbar
+}
+
+Property::Value TextSelectionToolbar::GetProperty( BaseObject* object, Property::Index index )
+{
+ Property::Value value;
+
+ Toolkit::TextSelectionToolbar selectionPopup = Toolkit::TextSelectionToolbar::DownCast( Dali::BaseHandle( object ) );
+
+ if( selectionPopup )
+ {
+ TextSelectionToolbar& impl( GetImpl( selectionPopup ) );
+
+ switch( index )
+ {
+ case Toolkit::TextSelectionToolbar::Property::MAX_SIZE:
+ {
+ value = impl.GetPopupMaxSize();
+ break;
+ }
+ } // switch
+ }
+ return value;
+}
+
+void TextSelectionToolbar::OnInitialize()
+{
+ SetUp();
+}
+
+void TextSelectionToolbar::OnRelayout( const Vector2& size, RelayoutContainer& container )
+{
+ float width = std::max ( mTableOfButtons.GetNaturalSize().width, size.width );
+ mRulerX->SetDomain( RulerDomain( 0.0, width, true ) );
+ mScrollView.SetRulerX( mRulerX );
+}
+
+void TextSelectionToolbar::SetPopupMaxSize( const Size& maxSize )
+{
+ mMaxSize = maxSize;
+}
+
+const Dali::Vector2& TextSelectionToolbar::GetPopupMaxSize() const
+{
+ return mMaxSize;
+}
+
+void TextSelectionToolbar::SetUpScrollView( Toolkit::ScrollView& scrollView )
+{
+ scrollView.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+ scrollView.SetParentOrigin( ParentOrigin::CENTER_LEFT );
+ scrollView.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
+ scrollView.SetMaximumSize( mMaxSize );
+
+ scrollView.SetScrollingDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 40.0f ) );
+ scrollView.SetAxisAutoLock( true );
+ scrollView.ScrollStartedSignal().Connect( this, &TextSelectionToolbar::OnScrollStarted );
+ scrollView.ScrollCompletedSignal().Connect( this, &TextSelectionToolbar::OnScrollCompleted );
+
+ mRulerX = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
+
+ RulerPtr rulerY = new DefaultRuler(); // IntrusivePtr which is unreferenced when ScrollView is destroyed.
+ rulerY->Disable();
+ scrollView.SetRulerY( rulerY );
+}
+
+void TextSelectionToolbar::SetUp()
+{
+ Actor self = Self();
+ self.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+
+ // Create Layer and Stencil. Layer enable's clipping when content exceed maximum defined width.
+ Layer stencilLayer = Layer::New();
+ stencilLayer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
+ stencilLayer.SetParentOrigin( ParentOrigin::CENTER );
+ stencilLayer.SetMaximumSize( mMaxSize );
+
+ ImageActor stencil = CreateSolidColorActor( Color::RED );
+ stencil.SetDrawMode( DrawMode::STENCIL );
+ stencil.SetVisible( true );
+ stencil.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+ stencil.SetParentOrigin( ParentOrigin::CENTER );
+
+ mScrollView = Toolkit::ScrollView::New();
+ SetUpScrollView( mScrollView );
+
+ // Toolbar must start with at least one option, adding further options with increase it's size
+ mTableOfButtons = Dali::Toolkit::TableView::New( 1, 1 );
+ mTableOfButtons.SetFitHeight( 0 );
+ mTableOfButtons.SetParentOrigin( ParentOrigin::CENTER_LEFT );
+ mTableOfButtons.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
+
+
+ stencilLayer.Add( stencil );
+ stencilLayer.Add( mScrollView );
+ mScrollView.Add( mTableOfButtons );
+ self.Add( stencilLayer );
+
+ stencilLayer.RaiseToTop();
+}
+
+void TextSelectionToolbar::OnScrollStarted( const Vector2& position )
+{
+ mTableOfButtons.SetSensitive( false );
+}
+
+void TextSelectionToolbar::OnScrollCompleted( const Vector2& position )
+{
+ mTableOfButtons.SetSensitive( true );
+}
+
+void TextSelectionToolbar::AddOption( Actor& option )
+{
+ mTableOfButtons.AddChild( option, Toolkit::TableView::CellPosition( 0, mIndexInTable ) );
+ mTableOfButtons.SetFitWidth( mIndexInTable );
+ mIndexInTable++;
+}
+
+void TextSelectionToolbar::AddDivider( Actor& divider )
+{
+ AddOption( divider );
+ mDividerIndexes.PushBack( mIndexInTable );
+}
+
+void TextSelectionToolbar::ResizeDividers( Size& size )
+{
+ for( unsigned int i = 0; i < mDividerIndexes.Count(); ++i )
+ {
+ Actor divider = mTableOfButtons.GetChildAt( Toolkit::TableView::CellPosition( 0, mDividerIndexes[ i ] ) );
+ divider.SetSize( size );
+ }
+ RelayoutRequest();
+}
+
+TextSelectionToolbar::TextSelectionToolbar()
+: Control( ControlBehaviour( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ) ),
+ mMaxSize ( DEFAULT_MAX_SIZE ),
+ mIndexInTable( 0 ),
+ mDividerIndexes()
+{
+}
+
+TextSelectionToolbar::~TextSelectionToolbar()
+{
+ mRulerX.Reset();
+}
+
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_TOOLBAR_H__
+#define __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_TOOLBAR_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 <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
+#include <dali-toolkit/public-api/controls/table-view/table-view.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+} // namespace
+
+class TextSelectionToolbar : public Control
+{
+public:
+
+ /**
+ * @copydoc Dali::Toollkit::TextSelectionToolbar::New()
+ */
+ static Toolkit::TextSelectionToolbar 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 );
+
+ /**
+ * @copydoc TextSelectionToolbar::AddOption
+ */
+ void AddOption( Actor& option );
+
+ /**
+ * @copydoc TextSelectionToolbar::AddDivider
+ */
+ void AddDivider( Actor& divider );
+
+ /**
+ * @copydoc ResizeDividers
+ */
+ void ResizeDividers( Size& size );
+
+private: // From Control
+
+ /**
+ * @copydoc Control::OnInitialize()
+ */
+ virtual void OnInitialize();
+
+ /**
+ * @copydoc Control::OnRelayout()
+ */
+ virtual void OnRelayout( const Vector2& size, RelayoutContainer& container );
+ /**
+ * @brief Set max size of Popup
+ * @param[in] maxSize Size (Vector2)
+ */
+ void SetPopupMaxSize( const Size& maxSize );
+
+ /**
+ * @brief Get Max size of Popup
+ * @return Vector2 the max size of the Popup
+ */
+ const Dali::Vector2& GetPopupMaxSize() const;
+
+ /**
+ * @brief Set up scrollview to scroll Toolbar horizontally
+ * @param[out] scrollView scrollview to setup
+ */
+ void SetUpScrollView( Toolkit::ScrollView& scrollView );
+
+ /**
+ * @brief Set up the parts that make the Toolbar
+ */
+ void SetUp();
+
+ /**
+ * Toolbar has started to scroll
+ * @param[in] position current scroll view position
+ */
+ void OnScrollStarted( const Vector2& position );
+
+ /**
+ * Toolbar has stopped scrolling
+ * @param[in] position current scroll view position
+ */
+ void OnScrollCompleted( const Vector2& position );
+
+private: // Implementation
+
+ /**
+ * Construct a new TextField.
+ */
+ TextSelectionToolbar();
+
+ /**
+ * A reference counted object may only be deleted by calling Unreference()
+ */
+ virtual ~TextSelectionToolbar();
+
+private:
+
+ // Undefined copy constructor and assignment operators
+ TextSelectionToolbar(const TextSelectionToolbar&);
+ TextSelectionToolbar& operator=(const TextSelectionToolbar& rhs);
+
+private: // Data
+
+ Toolkit::TableView mTableOfButtons; // Actor which holds all the buttons, sensitivity can be set on buttons via this actor
+ Toolkit::ScrollView mScrollView; // Provides scrolling of Toolbar when content does not fit.
+ RulerPtr mRulerX; // Ruler to clamp horizontal scrolling. Updates on Relayout
+ Size mMaxSize; // Max size of the Toolbar
+ unsigned int mIndexInTable; // Index in table to add option
+ Dali::Vector< unsigned int > mDividerIndexes; // Vector of indexes in the Toolbar that contain dividers.
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Toolkit::Internal::TextSelectionToolbar& GetImpl( Toolkit::TextSelectionToolbar& textSelectionToolbar )
+{
+ DALI_ASSERT_ALWAYS( textSelectionToolbar );
+
+ Dali::RefObject& handle = textSelectionToolbar.GetImplementation();
+
+ return static_cast<Toolkit::Internal::TextSelectionToolbar&>(handle);
+}
+
+inline const Toolkit::Internal::TextSelectionToolbar& GetImpl( const Toolkit::TextSelectionToolbar& textSelectionToolbar )
+{
+ DALI_ASSERT_ALWAYS( textSelectionToolbar );
+
+ const Dali::RefObject& handle = textSelectionToolbar.GetImplementation();
+
+ return static_cast<const Toolkit::Internal::TextSelectionToolbar&>(handle);
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_TEXT_SELECTION_TOOLBAR_H__
$(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/text-controls/text-selection-toolbar-impl.cpp \
$(toolkit_src_dir)/controls/tool-bar/tool-bar-impl.cpp \
$(toolkit_src_dir)/focus-manager/accessibility-focus-manager-impl.cpp \
$(toolkit_src_dir)/focus-manager/keyboard-focus-manager-impl.cpp \
#include <dali/public-api/actors/layer.h>
#include <dali/devel-api/adaptor-framework/accessibility-manager.h>
#include <dali/devel-api/adaptor-framework/sound-player.h>
-#include <dali/devel-api/adaptor-framework/tts-player.h>
+#include <dali/public-api/adaptor-framework/tts-player.h>
#include <dali/public-api/animation/constraints.h>
#include <dali/devel-api/events/hit-test-algorithm.h>
#include <dali/public-api/images/resource-image.h>
Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
if(propertyActorFocusable == Property::INVALID_INDEX)
{
- propertyActorFocusable = actor.RegisterProperty(ACTOR_FOCUSABLE, true);
+ propertyActorFocusable = actor.RegisterProperty( ACTOR_FOCUSABLE, true, Property::READ_WRITE );
}
if(order == 0)
Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP);
if(propertyIsFocusGroup == Property::INVALID_INDEX)
{
- actor.RegisterProperty(IS_FOCUS_GROUP, isFocusGroup);
+ actor.RegisterProperty( IS_FOCUS_GROUP, isFocusGroup, Property::READ_WRITE );
}
else
{
Property::Index propertyActorFocusable = actor.GetPropertyIndex(ACTOR_FOCUSABLE);
if(propertyActorFocusable == Property::INVALID_INDEX)
{
- actor.RegisterProperty(ACTOR_FOCUSABLE, focusable);
+ actor.RegisterProperty( ACTOR_FOCUSABLE, focusable, Property::READ_WRITE );
}
else
{
Property::Index propertyIsFocusGroup = actor.GetPropertyIndex(IS_FOCUS_GROUP_PROPERTY_NAME);
if(propertyIsFocusGroup == Property::INVALID_INDEX)
{
- actor.RegisterProperty(IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup);
+ actor.RegisterProperty(IS_FOCUS_GROUP_PROPERTY_NAME, isFocusGroup, Property::READ_WRITE );
}
else
{
}
}
-void ReplaceBidirectionalInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
Vector<LineRun>& lineRuns,
Vector<BidirectionalLineInfoRun>& lineInfoRuns )
}
}
-void ReorderLines( LogicalModel& logicalModel,
- const VisualModel& visualModel,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
bool GetMirroredText( const Vector<Character>& text,
Vector<Character>& mirroredText )
{
Vector<BidirectionalParagraphInfoRun>& 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.
Vector<BidirectionalLineInfoRun>& 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.
namespace Toolkit
{
+namespace Text
+{
+
namespace
{
const static uint8_t U1 = 1u;
Utf32ToUtf8( utf32, numberOfCharacters, reinterpret_cast<uint8_t*>(&utf8[0]) );
}
+} // namespace Text
+
} // namespace Toolkit
} // namespace Dali
namespace Toolkit
{
+namespace Text
+{
+
/**
* @brief Retrieves the number of characters of the text array encoded in UTF8
*
*/
void Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, std::string& utf8 );
+} // namespace Text
+
} // namespace Toolkit
} // namespace Dali
offscreenSize.height,
Pixel::RGBA8888 );
+ mOffscreenRootActor.SetSize( size );
+
mImageActor.SetSize( offscreenSize );
mImageActor.SetImage( frameBufferImage );
mRenderTask.SetTargetFrameBuffer( frameBufferImage );
const char* DEFAULT_GRAB_HANDLE_IMAGE_RELEASED( DALI_IMAGE_DIR "insertpoint-icon.png" );
const char* DEFAULT_GRAB_HANDLE_IMAGE_PRESSED( DALI_IMAGE_DIR "insertpoint-icon-pressed.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_RELEASED( DALI_IMAGE_DIR "text-input-selection-handle-left.png" );
+const char* DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" );
+const char* DEFAULT_SELECTION_HANDLE_TWO_RELEASED( DALI_IMAGE_DIR "text-input-selection-handle-right.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 int DEFAULT_POPUP_OFFSET( -100.0f ); // Vertical offset of Popup from cursor or handles position.
-const Dali::Vector4 LIGHT_BLUE( 0.07f, 0.41f, 0.59f, 1.0f ); // The text highlight color.
+const Dali::Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.25f, 1.5f, 1.0f );
+const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.25f, 1.5f, 1.0f );
+
+const Dali::Vector4 LIGHT_BLUE( (0xb2 / 255.0f), (0xeb / 255.0f), (0xf2 / 255.0f), 0.5f ); // The text highlight color.
const unsigned int CURSOR_BLINK_INTERVAL = 500u; // Cursor blink interval
const float TO_MILLISECONDS = 1000.f;
grabDisplacementY( 0.f ),
active( false ),
visible( false ),
+ pressed( false ),
flipped( false )
{
}
float grabDisplacementY;
bool active : 1;
bool visible : 1;
+ bool pressed : 1;
bool flipped : 1;
};
- Impl( Dali::Toolkit::Internal::Control& parent, Observer& observer )
- : mTextControlParent( parent ),
- mObserver( observer ),
+ struct PopupImpl
+ {
+ PopupImpl()
+ : position(),
+ offset( DEFAULT_POPUP_OFFSET )
+ {
+ }
+
+ TextSelectionPopup actor;
+ Vector3 position;
+ int offset;
+ };
+
+ Impl( ControllerInterface& controller,
+ TextSelectionPopupCallbackInterface& callbackInterface )
+ : mController( controller ),
+ mEnabledPopupButtons( TextSelectionPopup::NONE ),
+ mTextSelectionPopupCallbackInterface( callbackInterface ),
mBoundingBox( Rect<int>() ),
mHighlightColor( LIGHT_BLUE ),
+ mHighlightPosition( Vector2::ZERO ),
mActiveCursor( ACTIVE_CURSOR_NONE ),
mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ),
mCursorBlinkDuration( 0.0f ),
mActiveCopyPastePopup( false ),
mCursorBlinkStatus( true ),
mPrimaryCursorVisible( false ),
- mSecondaryCursorVisible( false )
+ mSecondaryCursorVisible( false ),
+ mSwapSelectionHandles( false ),
+ mNotifyEndOfScroll( false )
{
}
if( mPrimaryCursorVisible )
{
Vector2 position = cursor.position;
- if( GRAB_HANDLE == mHandleScrolling )
- {
- if( mScrollDirection == SCROLL_RIGHT )
- {
- position.x = 0.f;
- }
- else
- {
- position.x = size.width;
- }
- }
mPrimaryCursor.SetPosition( position.x,
position.y );
{
Vector2 position = grabHandle.position;
- if( GRAB_HANDLE == mHandleScrolling )
- {
- if( mScrollDirection == SCROLL_RIGHT )
- {
- position.x = 0.f;
- }
- else
- {
- position.x = size.width;
- }
- }
-
const bool isVisible = ( position.x <= size.width ) && ( position.x >= 0.f );
if( isVisible )
HandleImpl& secondary = mHandle[ RIGHT_SELECTION_HANDLE ];
if( primary.active || secondary.active )
{
- SetupTouchEvents();
+ Vector2 primaryPosition = primary.position;
+ Vector2 secondaryPosition = secondary.position;
+
+ const bool isPrimaryVisible = ( primaryPosition.x <= size.width ) && ( primaryPosition.x >= 0.f );
+ const bool isSecondaryVisible = ( secondaryPosition.x <= size.width ) && ( secondaryPosition.x >= 0.f );
+
+ if( isPrimaryVisible || isSecondaryVisible )
+ {
+ SetupTouchEvents();
- CreateSelectionHandles();
+ CreateSelectionHandles();
- primary.actor.SetPosition( primary.position.x,
- primary.position.y + primary.lineHeight );
+ if( isPrimaryVisible )
+ {
+ primary.actor.SetPosition( primaryPosition.x,
+ primaryPosition.y + primary.lineHeight );
+ }
- secondary.actor.SetPosition( secondary.position.x,
- secondary.position.y + secondary.lineHeight );
+ if( isSecondaryVisible )
+ {
+ secondary.actor.SetPosition( secondaryPosition.x,
+ secondaryPosition.y + secondary.lineHeight );
+ }
+ }
+ primary.actor.SetVisible( isPrimaryVisible );
+ secondary.actor.SetVisible( isSecondaryVisible );
CreateHighlight();
UpdateHighlight();
if ( mActiveCopyPastePopup )
{
- if ( !mCopyPastePopup )
+ // todo Swap UnparentAndReset for DeterminePositionPopup() if mCopyPastePopup.actor valid Once the issue with the labels disappearing is fixed.
+ UnparentAndReset( mCopyPastePopup.actor );
+ if ( !mCopyPastePopup.actor )
{
- mCopyPastePopup = TextSelectionPopup::New();
+ mCopyPastePopup.actor = TextSelectionPopup::New( mEnabledPopupButtons, &mTextSelectionPopupCallbackInterface );
#ifdef DECORATOR_DEBUG
- mCopyPastePopup.SetName("mCopyPastePopup");
+ mCopyPastePopup.actor.SetName("mCopyPastePopup");
#endif
- mCopyPastePopup.SetAnchorPoint( AnchorPoint::CENTER );
- mCopyPastePopup.OnRelayoutSignal().Connect( this, &Decorator::Impl::PopUpRelayoutComplete ); // Position popup after size negotiation
- mActiveLayer.Add ( mCopyPastePopup );
+ mCopyPastePopup.actor.SetAnchorPoint( AnchorPoint::CENTER );
+ mCopyPastePopup.actor.OnRelayoutSignal().Connect( this, &Decorator::Impl::PopupRelayoutComplete ); // Position popup after size negotiation
+ mActiveLayer.Add ( mCopyPastePopup.actor );
}
}
else
{
- if ( mCopyPastePopup )
+ if ( mCopyPastePopup.actor )
{
- UnparentAndReset( mCopyPastePopup );
+ UnparentAndReset( mCopyPastePopup.actor );
}
}
}
mHandle[ GRAB_HANDLE ].position += scrollOffset;
mHandle[ LEFT_SELECTION_HANDLE ].position += scrollOffset;
mHandle[ RIGHT_SELECTION_HANDLE ].position += scrollOffset;
-
- // TODO Highlight box??
+ mHighlightPosition += scrollOffset;
}
- void PopUpRelayoutComplete( Actor actor )
+ void DeterminePositionPopup()
{
- // Size negotiation for CopyPastePopup complete so can get the size and constrain position within bounding box.
+ if ( !mActiveCopyPastePopup )
+ {
+ return;
+ }
- mCopyPastePopup.OnRelayoutSignal().Disconnect( this, &Decorator::Impl::PopUpRelayoutComplete );
+ if ( mHandle[LEFT_SELECTION_HANDLE].active || mHandle[RIGHT_SELECTION_HANDLE].active )
+ {
+ float minHandleXPosition = std::min ( mHandle[LEFT_SELECTION_HANDLE].position.x, mHandle[RIGHT_SELECTION_HANDLE].position.x );
+ float maxHandleXPosition = std::max ( mHandle[LEFT_SELECTION_HANDLE].position.x, mHandle[RIGHT_SELECTION_HANDLE].position.x );
- Vector3 popupPosition( mCursor[PRIMARY_CURSOR].position.x, mCursor[PRIMARY_CURSOR].position.y -100.0f , 0.0f); //todo 100 to be an offset Property
+ float minHandleYPosition = std::min ( mHandle[LEFT_SELECTION_HANDLE].position.y, mHandle[RIGHT_SELECTION_HANDLE].position.y );
- Vector3 popupSize = Vector3( mCopyPastePopup.GetRelayoutSize( Dimension::WIDTH ), mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT ), 0.0f );
+ mCopyPastePopup.position.x = minHandleXPosition + ( ( maxHandleXPosition - minHandleXPosition ) *0.5f );
+ mCopyPastePopup.position.y = minHandleYPosition + mCopyPastePopup.offset;
+ }
+ else
+ {
+ mCopyPastePopup.position = Vector3( mCursor[PRIMARY_CURSOR].position.x, mCursor[PRIMARY_CURSOR].position.y -100.0f , 0.0f ); //todo 100 to be an offset Property
+ }
+
+ Vector3 popupSize = Vector3( mCopyPastePopup.actor.GetRelayoutSize( Dimension::WIDTH ), mCopyPastePopup.actor.GetRelayoutSize( Dimension::HEIGHT ), 0.0f );
- GetConstrainedPopupPosition( popupPosition, popupSize, AnchorPoint::CENTER, mActiveLayer, mBoundingBox );
+ GetConstrainedPopupPosition( mCopyPastePopup.position, popupSize, AnchorPoint::CENTER, mActiveLayer, mBoundingBox );
- SetUpPopUpPositionNotifications();
+ SetUpPopupPositionNotifications();
+
+ mCopyPastePopup.actor.SetPosition( mCopyPastePopup.position );
+ }
+
+ void PopupRelayoutComplete( Actor actor )
+ {
+ // Size negotiation for CopyPastePopup complete so can get the size and constrain position within bounding box.
+ mCopyPastePopup.actor.OnRelayoutSignal().Disconnect( this, &Decorator::Impl::PopupRelayoutComplete );
- mCopyPastePopup.SetPosition( popupPosition ); //todo grabhandle(cursor) or selection handle positions to be used
+ DeterminePositionPopup();
}
void CreateCursor( ImageActor& cursor, const Vector4& color )
{
if( !mActiveLayer )
{
- Actor parent = mTextControlParent.Self();
-
mActiveLayer = Layer::New();
#ifdef DECORATOR_DEBUG
mActiveLayer.SetName ( "ActiveLayerActor" );
mActiveLayer.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
mActiveLayer.SetPositionInheritanceMode( USE_PARENT_POSITION );
- parent.Add( mActiveLayer );
+ // Add the active layer telling the controller it doesn't need clipping.
+ mController.AddDecoration( mActiveLayer, false );
}
mActiveLayer.RaiseToTop();
{
if( !mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] )
{
- mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE );
+ mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE_RELEASED );
+ }
+ if( !mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] )
+ {
+ mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE_PRESSED );
}
primary.actor = ImageActor::New( mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] );
primary.grabArea.SetName("SelectionHandleOneGrabArea");
#endif
primary.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
+ primary.grabArea.SetParentOrigin( ParentOrigin::TOP_CENTER );
+ primary.grabArea.SetAnchorPoint( AnchorPoint::TOP_CENTER );
primary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE );
- primary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
mTapDetector.Attach( primary.grabArea );
mPanGestureDetector.Attach( primary.grabArea );
{
if( !mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] )
{
- mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO );
+ mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO_RELEASED );
+ }
+ if( !mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] )
+ {
+ mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO_PRESSED );
}
secondary.actor = ImageActor::New( mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] );
secondary.grabArea.SetName("SelectionHandleTwoGrabArea");
#endif
secondary.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
+ secondary.grabArea.SetParentOrigin( ParentOrigin::TOP_CENTER );
+ secondary.grabArea.SetAnchorPoint( AnchorPoint::TOP_CENTER );
secondary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE );
- secondary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
mTapDetector.Attach( secondary.grabArea );
mPanGestureDetector.Attach( secondary.grabArea );
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 );
+ // Add the highlight box telling the controller it needs clipping.
+ mController.AddDecoration( mHighlightMeshActor, true );
}
+
+ mHighlightMeshActor.SetPosition( mHighlightPosition.x, mHighlightPosition.y, DISPLAYED_HIGHLIGHT_Z_OFFSET );
*/
}
if( Gesture::Started == gesture.state ||
Gesture::Continuing == gesture.state )
{
+ Vector2 targetSize;
+ mController.GetTargetSize( targetSize );
+
if( x < mScrollThreshold )
{
mScrollDirection = SCROLL_RIGHT;
mHandleScrolling = type;
StartScrollTimer();
}
- else if( x > mTextControlParent.Self().GetTargetSize().width - mScrollThreshold )
+ else if( x > targetSize.width - mScrollThreshold )
{
mScrollDirection = SCROLL_LEFT;
mHandleScrolling = type;
{
mHandleScrolling = HANDLE_TYPE_COUNT;
StopScrollTimer();
- mObserver.HandleEvent( type, HANDLE_PRESSED, x, y );
+ mController.DecorationEvent( type, HANDLE_PRESSED, x, y );
}
}
else if( Gesture::Finished == gesture.state ||
Gesture::Cancelled == gesture.state )
{
- if( mScrollTimer && mScrollTimer.IsRunning() )
+ if( mScrollTimer &&
+ ( mScrollTimer.IsRunning() || mNotifyEndOfScroll ) )
{
+ mNotifyEndOfScroll = false;
mHandleScrolling = HANDLE_TYPE_COUNT;
StopScrollTimer();
- mObserver.HandleEvent( type, HANDLE_STOP_SCROLLING, x, y );
+ mController.DecorationEvent( type, HANDLE_STOP_SCROLLING, x, y );
}
else
{
- mObserver.HandleEvent( type, HANDLE_RELEASED, x, y );
+ mController.DecorationEvent( type, HANDLE_RELEASED, x, y );
}
- handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_RELEASED] );
+
+ if( GRAB_HANDLE == type )
+ {
+ handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_RELEASED] );
+ }
+ else
+ {
+ HandleType selectionHandleType = type;
+
+ if( mSwapSelectionHandles != handle.flipped )
+ {
+ selectionHandleType = ( LEFT_SELECTION_HANDLE == type ) ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE;
+ }
+
+ handle.actor.SetImage( mHandleImages[selectionHandleType][HANDLE_IMAGE_RELEASED] );
+ }
+ handle.pressed = false;
}
}
{
const TouchPoint& point = event.GetPoint(0);
- if( TouchPoint::Down == point.state &&
- mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED] )
+ if( TouchPoint::Down == point.state )
{
- mHandle[GRAB_HANDLE].actor.SetImage( mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED] );
+ mHandle[GRAB_HANDLE].pressed = true;
+ Image imagePressed = mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED];
+ if( imagePressed )
+ {
+ mHandle[GRAB_HANDLE].actor.SetImage( imagePressed );
+ }
}
- else if( TouchPoint::Up == point.state &&
- mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] )
+ else if( TouchPoint::Up == point.state )
{
- mHandle[GRAB_HANDLE].actor.SetImage( mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] );
+ mHandle[GRAB_HANDLE].pressed = false;
+ Image imageReleased = mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED];
+ if( imageReleased )
+ {
+ mHandle[GRAB_HANDLE].actor.SetImage( imageReleased );
+ }
}
}
return true;
}
- bool OnHandleOneTouched( Actor actor, const TouchEvent& touch )
+ bool OnHandleOneTouched( Actor actor, const TouchEvent& event )
{
- // TODO
+ // Switch between pressed/release selection handle images
+ if( event.GetPointCount() > 0 &&
+ mHandle[LEFT_SELECTION_HANDLE].actor )
+ {
+ const TouchPoint& point = event.GetPoint(0);
+
+ const bool flip = mSwapSelectionHandles != mHandle[LEFT_SELECTION_HANDLE].flipped;
+ if( TouchPoint::Down == point.state )
+ {
+ mHandle[LEFT_SELECTION_HANDLE].pressed = true;
+ Image imagePressed = mHandleImages[flip ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED];
+ if( imagePressed )
+ {
+ mHandle[LEFT_SELECTION_HANDLE].actor.SetImage( imagePressed );
+ }
+ }
+ else if( TouchPoint::Up == point.state )
+ {
+ mHandle[LEFT_SELECTION_HANDLE].pressed = false;
+ Image imageReleased = mHandleImages[flip ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED];
+ if( imageReleased )
+ {
+ mHandle[LEFT_SELECTION_HANDLE].actor.SetImage( imageReleased );
+ }
+ }
+ }
+
// Consume to avoid pop-ups accidentally closing, when handle is outside of pop-up area
return true;
}
- bool OnHandleTwoTouched( Actor actor, const TouchEvent& touch )
+ bool OnHandleTwoTouched( Actor actor, const TouchEvent& event )
{
- // TODO
+ // Switch between pressed/release selection handle images
+ if( event.GetPointCount() > 0 &&
+ mHandle[RIGHT_SELECTION_HANDLE].actor )
+ {
+ const TouchPoint& point = event.GetPoint(0);
+
+ const bool flip = mSwapSelectionHandles != mHandle[RIGHT_SELECTION_HANDLE].flipped;
+ if( TouchPoint::Down == point.state )
+ {
+ Image imagePressed = mHandleImages[flip ? LEFT_SELECTION_HANDLE : RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED];
+ mHandle[RIGHT_SELECTION_HANDLE].pressed = true;
+ if( imagePressed )
+ {
+ mHandle[RIGHT_SELECTION_HANDLE].actor.SetImage( imagePressed );
+ }
+ }
+ else if( TouchPoint::Up == point.state )
+ {
+ Image imageReleased = mHandleImages[flip ? LEFT_SELECTION_HANDLE : RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED];
+ mHandle[RIGHT_SELECTION_HANDLE].pressed = false;
+ if( imageReleased )
+ {
+ mHandle[RIGHT_SELECTION_HANDLE].actor.SetImage( imageReleased );
+ }
+ }
+ }
+
// Consume to avoid pop-ups accidentally closing, when handle is outside of pop-up area
return true;
}
// if can't be positioned above, then position below row.
alternativeYPosition = AlternatePopUpPositionRelativeToCursor();
- mCopyPastePopup.SetY( alternativeYPosition );
+ mCopyPastePopup.actor.SetY( alternativeYPosition );
}
- void SetUpPopUpPositionNotifications( )
+ void SetUpPopupPositionNotifications( )
{
// Note Property notifications ignore any set anchor point so conditions must allow for this. Default is Top Left.
Vector4 worldCoordinatesBoundingBox;
LocalToWorldCoordinatesBoundingBox( mBoundingBox, worldCoordinatesBoundingBox );
- float popupHeight = mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT);
+ float popupHeight = mCopyPastePopup.actor.GetRelayoutSize( Dimension::HEIGHT);
- PropertyNotification verticalExceedNotification = mCopyPastePopup.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y,
- OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight/2,
- worldCoordinatesBoundingBox.w - popupHeight/2 ) );
+ PropertyNotification verticalExceedNotification = mCopyPastePopup.actor.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y,
+ OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight * 0.5f,
+ worldCoordinatesBoundingBox.w - popupHeight * 0.5f ) );
verticalExceedNotification.NotifySignal().Connect( this, &Decorator::Impl::PopUpLeavesVerticalBoundary );
}
}
requiredPopupPosition.x = requiredPopupPosition.x + xOffSetToKeepWithinBounds;
+
+ // Prevent pixel mis-alignment by rounding down.
+ requiredPopupPosition.x = static_cast<int>( requiredPopupPosition.x );
+ requiredPopupPosition.y = static_cast<int>( requiredPopupPosition.y );
+
+ }
+
+ void FlipSelectionHandleImages()
+ {
+ SetupTouchEvents();
+
+ CreateSelectionHandles();
+
+ HandleImpl& leftHandle = mHandle[LEFT_SELECTION_HANDLE];
+ HandleImpl& rightHandle = mHandle[RIGHT_SELECTION_HANDLE];
+
+ const HandleImageType leftImageType = leftHandle.pressed ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED;
+ const HandleImageType rightImageType = rightHandle.pressed ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED;
+ const bool leftFlipped = mSwapSelectionHandles != leftHandle.flipped;
+ const bool rightFlipped = mSwapSelectionHandles != rightHandle.flipped;
+
+ leftHandle.actor.SetImage( leftFlipped ? mHandleImages[RIGHT_SELECTION_HANDLE][leftImageType] : mHandleImages[LEFT_SELECTION_HANDLE][leftImageType] );
+
+ leftHandle.actor.SetAnchorPoint( leftFlipped ? AnchorPoint::TOP_LEFT : AnchorPoint::TOP_RIGHT );
+
+ rightHandle.actor.SetImage( rightFlipped ? mHandleImages[LEFT_SELECTION_HANDLE][rightImageType] : mHandleImages[RIGHT_SELECTION_HANDLE][rightImageType] );
+
+ rightHandle.actor.SetAnchorPoint( rightFlipped ? AnchorPoint::TOP_RIGHT : AnchorPoint::TOP_LEFT );
}
void SetScrollThreshold( float threshold )
return mScrollSpeed;
}
+ void NotifyEndOfScroll()
+ {
+ StopScrollTimer();
+
+ if( mScrollTimer )
+ {
+ mNotifyEndOfScroll = true;
+ }
+ }
+
/**
* Creates and starts a timer to scroll the text when handles are close to the edges of the text.
*
{
if( HANDLE_TYPE_COUNT != mHandleScrolling )
{
- mObserver.HandleEvent( mHandleScrolling,
- HANDLE_SCROLLING,
- mScrollDirection == SCROLL_RIGHT ? mScrollDistance : -mScrollDistance,
- 0.f );
+ mController.DecorationEvent( mHandleScrolling,
+ HANDLE_SCROLLING,
+ mScrollDirection == SCROLL_RIGHT ? mScrollDistance : -mScrollDistance,
+ 0.f );
}
return true;
}
- Internal::Control& mTextControlParent;
- Observer& mObserver;
+ ControllerInterface& mController;
TapGestureDetector mTapDetector;
PanGestureDetector mPanGestureDetector;
//ImageActor mPrimaryCursor;
//ImageActor mSecondaryCursor;
//MeshActor mHighlightMeshActor; ///< Mesh Actor to display highlight
- TextSelectionPopup mCopyPastePopup;
+
+ PopupImpl mCopyPastePopup;
+ TextSelectionPopup::Buttons mEnabledPopupButtons; /// Bit mask of currently enabled Popup buttons
+ TextSelectionPopupCallbackInterface& mTextSelectionPopupCallbackInterface;
Image mHandleImages[HANDLE_TYPE_COUNT][HANDLE_IMAGE_TYPE_COUNT];
Image mCursorImage;
Rect<int> mBoundingBox;
Vector4 mHighlightColor; ///< Color of the highlight
+ Vector2 mHighlightPosition; ///< The position of the highlight actor.
unsigned int mActiveCursor;
unsigned int mCursorBlinkInterval;
float mScrollThreshold; ///< Defines a square area inside the control, close to the edge. A cursor entering this area will trigger scroll events.
float mScrollSpeed; ///< The scroll speed in pixels per second.
float mScrollDistance; ///< Distance the text scrolls during a scroll interval.
- unsigned int mScrollInterval; ///< Time in milliseconds of a scroll interval.
bool mActiveCopyPastePopup : 1;
bool mCursorBlinkStatus : 1; ///< Flag to switch between blink on and blink off.
bool mPrimaryCursorVisible : 1; ///< Whether the primary cursor is visible.
bool mSecondaryCursorVisible : 1; ///< Whether the secondary cursor is visible.
+ bool mSwapSelectionHandles : 1; ///< Whether to swap the selection handle images.
+ bool mNotifyEndOfScroll : 1; ///< Whether to notify the end of the scroll.
};
-DecoratorPtr Decorator::New( Internal::Control& parent, Observer& observer )
+DecoratorPtr Decorator::New( ControllerInterface& controller,
+ TextSelectionPopupCallbackInterface& callbackInterface )
{
- return DecoratorPtr( new Decorator(parent, observer) );
+ return DecoratorPtr( new Decorator( controller,
+ callbackInterface ) );
}
void Decorator::SetBoundingBox( const Rect<int>& boundingBox )
height = handle.lineHeight;
}
+const Vector2& Decorator::GetPosition( HandleType handleType ) const
+{
+ return mImpl->mHandle[handleType].position;
+}
+
+void Decorator::SwapSelectionHandlesEnabled( bool enable )
+{
+ mImpl->mSwapSelectionHandles = enable;
+
+ mImpl->FlipSelectionHandleImages();
+}
+
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();
+ mImpl->mHighlightPosition = Vector2::ZERO;
}
void Decorator::SetHighlightColor( const Vector4& color )
return mImpl->mActiveCopyPastePopup ;
}
+void Decorator::SetEnabledPopupButtons( TextSelectionPopup::Buttons& enabledButtonsBitMask )
+{
+ mImpl->mEnabledPopupButtons = enabledButtonsBitMask;
+}
+
+TextSelectionPopup::Buttons& Decorator::GetEnabledPopupButtons()
+{
+ return mImpl->mEnabledPopupButtons;
+}
+
/** Scroll **/
void Decorator::SetScrollThreshold( float threshold )
return mImpl->GetScrollSpeed();
}
+void Decorator::NotifyEndOfScroll()
+{
+ mImpl->NotifyEndOfScroll();
+}
+
Decorator::~Decorator()
{
delete mImpl;
}
-Decorator::Decorator( Dali::Toolkit::Internal::Control& parent, Observer& observer )
+Decorator::Decorator( ControllerInterface& controller,
+ TextSelectionPopupCallbackInterface& callbackInterface )
: mImpl( NULL )
{
- mImpl = new Decorator::Impl( parent, observer );
+ mImpl = new Decorator::Impl( controller, callbackInterface );
}
} // namespace Text
#include <dali/public-api/math/rect.h>
#include <dali/public-api/math/vector2.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
+
namespace Dali
{
+class Actor;
class Image;
class Vector2;
class Vector4;
namespace Toolkit
{
+class TextSelectionPopupCallbackInterface;
+
namespace Internal
{
class Control;
*
* Selection handles will be flipped around to ensure they do not exceed the Decoration Bounding Box. ( Stay visible ).
*
- * Decorator components forward input events to a controller class through an observer interface.
+ * Decorator components forward input events to a controller class through an interface.
* The controller is responsible for selecting which components are active.
*/
class Decorator : public RefObject
{
public:
- class Observer
+ class ControllerInterface
{
public:
/**
* @brief Constructor.
*/
- Observer() {};
+ ControllerInterface() {};
/**
* @brief Virtual destructor.
*/
- virtual ~Observer() {};
+ virtual ~ControllerInterface() {};
+
+ /**
+ * @brief An input event from one of the handles.
+ *
+ * @param[out] targetSize The Size of the UI control the decorator is adding it's decorations to.
+ */
+ virtual void GetTargetSize( Vector2& targetSize ) = 0;
+
+ /**
+ * @brief Add a decoration to the parent UI control.
+ *
+ * @param[in] decoration The actor displaying a decoration.
+ */
+ virtual void AddDecoration( Actor& actor, bool needsClipping ) = 0;
/**
* @brief An input event from one of the handles.
* @param[in] x The x position relative to the top-left of the parent control.
* @param[in] y The y position relative to the top-left of the parent control.
*/
- virtual void HandleEvent( HandleType handleType, HandleState state, float x, float y ) = 0;
+ virtual void DecorationEvent( HandleType handleType, HandleState state, float x, float y ) = 0;
};
/**
* @brief Create a new instance of a Decorator.
*
- * @param[in] parent Decorations will be added to this parent control.
- * @param[in] observer A class which receives input events from Decorator components.
+ * @param[in] controller The controller which receives input events from Decorator components.
+ * @param[in] callbackInterface The text popup callback interface which receives the button click callbacks.
+ *
* @return A pointer to a new Decorator.
*/
- static DecoratorPtr New( Dali::Toolkit::Internal::Control& parent, Observer& observer );
+ static DecoratorPtr New( ControllerInterface& controller,
+ TextSelectionPopupCallbackInterface& callbackInterface );
/**
* @brief Set the bounding box which handles, popup and similar decorations will not exceed.
void GetPosition( HandleType handleType, float& x, float& y, float& lineHeight ) const;
/**
+ * @brief Retrieves the position of a selection handle.
+ *
+ * @param[in] handleType The handle to get.
+ *
+ * @return The position of the selection handle relative to the top-left of the parent control.
+ */
+ const Vector2& GetPosition( HandleType handleType ) const;
+
+ /**
+ * @brief Swaps the selection handle's images.
+ *
+ * This method is called by the text controller to swap the handles
+ * when the start index is bigger than the end one.
+ */
+ void SwapSelectionHandlesEnabled( bool enable );
+
+ /**
* @brief Adds a quad to the existing selection highlights.
*
* @param[in] x1 The top-left x position.
bool IsPopupActive() const;
/**
+ * @brief Set a bit mask of the buttons to be shown by Popup
+ * @param[in] enabledButtonsBitMask from TextSelectionPopup::Buttons enum
+ */
+ void SetEnabledPopupButtons( TextSelectionPopup::Buttons& enabledButtonsBitMask );
+
+ /**
+ * @brief Get the current bit mask of buttons to be shown by Popup
+ * @return bitmask of TextSelectionPopup::Buttons
+ */
+ TextSelectionPopup::Buttons& GetEnabledPopupButtons();
+
+ /**
* @brief Sets the scroll threshold.
*
* It defines a square area inside the control, close to the edge.
float GetScrollSpeed() const;
/**
- * @brief Sets the scroll interval.
- *
- * @param[in] seconds The scroll interval in seconds.
- */
- void SetScrollTickInterval( float seconds );
-
- /**
- * @brief Retrieves the scroll interval.
- *
- * @return The scroll interval.
+ * @brief Notifies the decorator the whole text has been scrolled.
*/
- float GetScrollTickInterval() const;
+ void NotifyEndOfScroll();
protected:
/**
* @brief Private constructor.
- * @param[in] parent Decorations will be added to this parent control.
- * @param[in] observer A class which receives input events from Decorator components.
+ * @param[in] controller The controller which receives input events from Decorator components.
+ * @param[in] callbackInterface The text popup callback interface which receives the button click callbacks.
*/
- Decorator(Dali::Toolkit::Internal::Control& parent, Observer& observer );
+ Decorator( ControllerInterface& controller,
+ TextSelectionPopupCallbackInterface& callbackInterface );
// Undefined
Decorator( const Decorator& handle );
numberOfGlyphs( 0u ),
numberOfCharacters( 0u ),
length( 0.f ),
- widthAdvanceDiff( 0.f ),
+ extraBearing( 0.f ),
+ extraWidth( 0.f ),
wsLengthEndOfLine( 0.f ),
ascender( 0.f ),
descender( MAX_FLOAT )
numberOfGlyphs = 0u;
numberOfCharacters = 0u;
length = 0.f;
- widthAdvanceDiff = 0.f;
+ extraBearing = 0.f;
+ extraWidth = 0.f;
wsLengthEndOfLine = 0.f;
ascender = 0.f;
descender = MAX_FLOAT;
CharacterIndex characterIndex; ///< Index of the first character to be laid-out.
Length numberOfGlyphs; ///< The number of glyph which fit in one line.
Length numberOfCharacters; ///< The number of characters 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 length; ///< The addition of the advance metric of all the glyphs which fit in one line.
+ float extraBearing; ///< The extra width to be added to the line's length when the bearing of the first glyph is negative.
+ float extraWidth; ///< The extra width to be added to the line's length when the bearing + width of the last glyph is greater than the advance.
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.
lineLayout.length += lineLayout.wsLengthEndOfLine;
lineLayout.wsLengthEndOfLine = tmpLineLayout.wsLengthEndOfLine;
- lineLayout.widthAdvanceDiff = tmpLineLayout.widthAdvanceDiff;
}
else
{
/**
* Retrieves the line layout for a given box width.
*
+ * @note This method lais out text as it were left to right. At this point is not possible to reorder the line
+ * because the number of characters of the line is not known (one of the responsabilities of this method
+ * is calculate that). Due to glyph's 'x' bearing, width and advance, when right to left or mixed right to left
+ * and left to right text is laid out, it can be small differences in the line length. One solution is to
+ * reorder and re-lay out the text after this method and add or remove one extra glyph if needed. However,
+ * this method calculates which are the first and last glyphs of the line (the ones that causes the
+ * differences). This is a good point to check if there is problems with the text exceeding the boundaries
+ * of the control when there is right to left text.
+ *
* @param[in] parameters The layout parameters.
* @param[out] lineLayout The line layout.
+ * @param[in,out] paragraphDirection in: the current paragraph's direction, out: the next paragraph's direction. Is set after a must break.
* @param[in] completelyFill Whether to completely fill the line ( even if the last word exceeds the boundaries ).
*/
void GetLineLayoutForBox( const LayoutParameters& parameters,
LineLayout& lineLayout,
+ CharacterDirection& paragraphDirection,
bool completelyFill )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->GetLineLayoutForBox\n" );
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.
+ // In the case the line starts with a right to left character, if the width is longer than the advance,
+ // the difference needs to be added to the line length.
const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + lineLayout.glyphIndex );
- float initialHorizontalBearing = glyphInfo.xBearing;
+ // Set the direction of the first character of the line.
lineLayout.characterIndex = *( parameters.glyphsToCharactersBuffer + lineLayout.glyphIndex );
const CharacterDirection firstCharacterDirection = ( NULL == parameters.characterDirectionBuffer ) ? false : *( parameters.characterDirectionBuffer + lineLayout.characterIndex );
+ CharacterDirection previousCharacterDirection = firstCharacterDirection;
- if( RTL == firstCharacterDirection )
- {
- initialHorizontalBearing = -initialHorizontalBearing;
+ const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+ float tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
- 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;
- }
- }
+ float tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+
+ tmpLineLayout.length += 1.f; // Added one unit to give some space to the cursor.
// 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;
// Used to restore the temporal line layout when a single word does not fit in the control's width and is split by character.
const float previousTmpLineLength = tmpLineLayout.length;
- const float previousTmpWidthAdvanceDiff = tmpLineLayout.widthAdvanceDiff;
+ const float previousTmpExtraBearing = tmpExtraBearing;
+ const float previousTmpExtraWidth = tmpExtraWidth;
+
+ // Get the character's direction.
+ const CharacterDirection characterDirection = ( NULL == parameters.characterDirectionBuffer ) ? false : *( parameters.characterDirectionBuffer + characterFirstIndex );
// Increase the accumulated length.
if( isWhiteSpace )
{
// Add as well any previous white space length.
tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphInfo.advance;
- if( RTL == firstCharacterDirection )
+
+ // An extra space may be added to the line for the first and last glyph of the line.
+ // If the bearing of the first glyph is negative, its positive value needs to be added.
+ // If the bearing plus the width of the last glyph is greater than the advance, the difference
+ // needs to be added.
+
+ if( characterDirection == paragraphDirection )
{
- tmpLineLayout.widthAdvanceDiff = -glyphInfo.xBearing;
+ if( RTL == characterDirection )
+ {
+ // <--
+ // | Rrrrr|
+ // or
+ // | Rllrrr|
+ // or
+ // |lllrrrrr|
+ // | Rll|
+ //
+
+ tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+ }
+ else // LTR
+ {
+ // -->
+ // |lllL |
+ // or
+ // |llrrL |
+ // or
+ // |lllllrrr|
+ // |rrL |
+ //
+
+ const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+ tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+ }
}
else
{
- tmpLineLayout.widthAdvanceDiff = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+ if( characterDirection != previousCharacterDirection )
+ {
+ if( RTL == characterDirection )
+ {
+ // -->
+ // |lllR |
+
+ const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+ tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+ }
+ else // LTR
+ {
+ // <--
+ // | Lrrrr|
+
+ tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+ }
+ }
+ else if( characterDirection == firstCharacterDirection )
+ {
+ if( RTL == characterDirection )
+ {
+ // -->
+ // |llllllrr|
+ // |Rr |
+
+ tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+ }
+ else // LTR
+ {
+ // <--
+ // |llllrrrr|
+ // | llL|
+
+ const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+ tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
+ }
+ }
}
// Clear the white space length at the end of the line.
// Check if the accumulated length fits in the width of the box.
if( ( completelyFill || isMultiline ) && !isWhiteSpace &&
- ( lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpLineLayout.widthAdvanceDiff > boundingBoxWidth ) )
+ ( tmpExtraBearing + lineLayout.length + lineLayout.wsLengthEndOfLine + tmpLineLayout.length + tmpExtraWidth > parameters.boundingBox.width ) )
{
// Current word does not fit in the box's width.
if( !oneWordLaidOut || completelyFill )
tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
--tmpLineLayout.numberOfGlyphs;
tmpLineLayout.length = previousTmpLineLength;
- tmpLineLayout.widthAdvanceDiff = previousTmpWidthAdvanceDiff;
+ tmpExtraBearing = previousTmpExtraBearing;
+ tmpExtraWidth = previousTmpExtraWidth;
}
// Add part of the word to the line layout.
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, " Current word does not fit.\n" );
}
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
+
+ lineLayout.extraBearing = tmpExtraBearing;
+ lineLayout.extraWidth = tmpExtraWidth;
+
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox.\n" );
+
return;
}
// Must break the line. Update the line layout and return.
MergeLineLayout( lineLayout, tmpLineLayout );
+ // Set the next paragraph's direction.
+ if( !isLastGlyph &&
+ ( NULL != parameters.characterDirectionBuffer ) )
+ {
+ paragraphDirection = *( parameters.characterDirectionBuffer + 1u + characterLastIndex );
+ }
+
+ lineLayout.extraBearing = tmpExtraBearing;
+ lineLayout.extraWidth = tmpExtraWidth;
+
DALI_LOG_INFO( gLogFilter, Debug::Verbose, " Must break\n" );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
return;
UpdateLineHeight( glyphInfo.fontId, tmpLineLayout );
lastFontId = glyphInfo.fontId;
}
+
+ previousCharacterDirection = characterDirection;
}
+
+ lineLayout.extraBearing = tmpExtraBearing;
+ lineLayout.extraWidth = tmpExtraWidth;
+
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
}
// 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 = *glyphsBuffer;
- if( 0.f > glyph.xBearing )
- {
- penX = -glyph.xBearing;
- }
+ float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f;
+ penX += 1.f; // Added one unit to give some space to the cursor.
for( GlyphIndex i = 0u; i < numberOfGlyphs; ++i )
{
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->LayoutText\n" );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, " box size %f, %f\n", layoutParameters.boundingBox.width, layoutParameters.boundingBox.height );
+ // Set the first paragraph's direction.
+ CharacterDirection paragraphDirection = ( NULL != layoutParameters.characterDirectionBuffer ) ? *layoutParameters.characterDirectionBuffer : !RTL;
+
float penY = 0.f;
for( GlyphIndex index = 0u; index < layoutParameters.totalNumberOfGlyphs; )
{
+ CharacterDirection currentParagraphDirection = paragraphDirection;
+
// Get the layout for the line.
LineLayout layout;
layout.glyphIndex = index;
GetLineLayoutForBox( layoutParameters,
layout,
+ paragraphDirection,
false );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, " glyph index %d\n", layout.glyphIndex );
if( mEllipsisEnabled &&
( ( penY - layout.descender > layoutParameters.boundingBox.height ) ||
( ( mLayout == SINGLE_LINE_BOX ) &&
- ( layout.length + layout.widthAdvanceDiff > layoutParameters.boundingBox.width ) ) ) )
+ ( layout.extraBearing + layout.length + layout.extraWidth > layoutParameters.boundingBox.width ) ) ) )
{
// Do not layout more lines if ellipsis is enabled.
GetLineLayoutForBox( layoutParameters,
ellipsisLayout,
+ currentParagraphDirection,
true );
lineRun.numberOfGlyphs = ellipsisLayout.numberOfGlyphs;
lineRun.characterRun.characterIndex = ellipsisLayout.characterIndex;
lineRun.characterRun.numberOfCharacters = ellipsisLayout.numberOfCharacters;
- lineRun.width = layoutParameters.boundingBox.width;
+ lineRun.width = ellipsisLayout.length;
+ lineRun.extraLength = ( ellipsisLayout.wsLengthEndOfLine > 0.f ) ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.extraWidth : 0.f;
lineRun.ascender = ellipsisLayout.ascender;
lineRun.descender = ellipsisLayout.descender;
- lineRun.extraLength = ellipsisLayout.wsLengthEndOfLine > 0.f ? ellipsisLayout.wsLengthEndOfLine - ellipsisLayout.widthAdvanceDiff : 0.f;
lineRun.ellipsis = true;
actualSize.width = layoutParameters.boundingBox.width;
}
else
{
+ const bool isLastLine = index + layout.numberOfGlyphs == layoutParameters.totalNumberOfGlyphs;
+
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;
+ if( isLastLine )
+ {
+ const float width = layout.extraBearing + layout.length + layout.extraWidth + layout.wsLengthEndOfLine;
+ if( MULTI_LINE_BOX == mLayout )
+ {
+ lineRun.width = ( width > layoutParameters.boundingBox.width ) ? layoutParameters.boundingBox.width : width;
+ }
+ else
+ {
+ lineRun.width = width;
+ }
+
+ lineRun.extraLength = 0.f;
+ }
+ else
+ {
+ lineRun.width = layout.extraBearing + layout.length + layout.extraWidth;
+ lineRun.extraLength = ( layout.wsLengthEndOfLine > 0.f ) ? layout.wsLengthEndOfLine - layout.extraWidth : 0.f;
+ }
lineRun.ascender = layout.ascender;
lineRun.descender = layout.descender;
- lineRun.extraLength = layout.wsLengthEndOfLine > 0.f ? layout.wsLengthEndOfLine - layout.widthAdvanceDiff : 0.f;
lineRun.direction = false;
lineRun.ellipsis = false;
}
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--LayoutText\n\n" );
+
return true;
}
{
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;
+ float penX = ( 0.f > glyph.xBearing ) ? -glyph.xBearing : 0.f;
+ penX += 1.f; // Added one unit to give some space to the cursor.
Vector2* glyphPositionsBuffer = glyphPositions.Begin();
}
}
- void Align( const LayoutParameters& layoutParameters,
- const Size& layoutSize,
- const Vector<LineRun>& lines,
- Vector<Vector2>& glyphPositions )
+ void Align( const Size& layoutSize,
+ Vector<LineRun>& lines )
{
- 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<LineRun>::ConstIterator it = lines.Begin(), endIt = lines.End();
+ for( Vector<LineRun>::Iterator 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;
- }
+ LineRun& line = *it;
+ const bool isLastLine = lines.End() == it + 1u;
+
+ // Calculate the alignment offset accordingly with the align option,
+ // the box width, line length, and the paragraphs direction.
+ CalculateHorizontalAlignment( layoutSize.width,
+ line,
+ isLastLine );
}
}
- float CalculateHorizontalAlignment( float boxWidth,
- float lineLength,
- float extraLength,
- bool paragraphDirection )
+ void CalculateHorizontalAlignment( float boxWidth,
+ LineRun& line,
+ bool isLastLine )
{
- float offset = 0.f;
+ line.alignmentOffset = 0.f;
+ const bool isRTL = RTL == line.direction;
+ float lineLength = line.width;
HorizontalAlignment alignment = mHorizontalAlignment;
- if( paragraphDirection &&
+ if( isRTL &&
( HORIZONTAL_ALIGN_CENTER != alignment ) )
{
if( HORIZONTAL_ALIGN_BEGIN == alignment )
{
case HORIZONTAL_ALIGN_BEGIN:
{
- offset = 0.f;
+ line.alignmentOffset = 0.f;
+
+ if( isRTL )
+ {
+ // 'Remove' the white spaces at the end of the line (which are at the beginning in visual order)
+ line.alignmentOffset -= line.extraLength;
+
+ if( isLastLine )
+ {
+ line.alignmentOffset += std::min( line.extraLength, boxWidth - lineLength );
+ }
+ }
break;
}
case HORIZONTAL_ALIGN_CENTER:
{
- offset = 0.5f * ( boxWidth - lineLength );
- const int intOffset = static_cast<int>( offset ); // try to avoid pixel alignment.
- offset = static_cast<float>( intOffset );
+ if( isLastLine && !isRTL )
+ {
+ lineLength += line.extraLength;
+ if( lineLength > boxWidth )
+ {
+ lineLength = boxWidth;
+ line.alignmentOffset = 0.f;
+ break;
+ }
+ }
+
+ line.alignmentOffset = 0.5f * ( boxWidth - lineLength );
+
+ if( isRTL )
+ {
+ line.alignmentOffset -= line.extraLength;
+
+ if( isLastLine )
+ {
+ line.alignmentOffset += 0.5f * std::min( line.extraLength, boxWidth - lineLength );
+ }
+ }
+
+ line.alignmentOffset = floorf( line.alignmentOffset ); // try to avoid pixel alignment.
break;
}
case HORIZONTAL_ALIGN_END:
{
- offset = boxWidth - lineLength;
+ if( isLastLine && !isRTL )
+ {
+ lineLength += line.extraLength;
+ if( lineLength > boxWidth )
+ {
+ line.alignmentOffset = 0.f;
+ break;
+ }
+ }
+
+ if( isRTL )
+ {
+ lineLength += line.extraLength;
+ }
+
+ line.alignmentOffset = boxWidth - lineLength;
break;
}
}
-
- if( paragraphDirection )
- {
- offset -= extraLength;
- }
-
- return offset;
}
LayoutEngine::Layout mLayout;
glyphPositions );
}
-void LayoutEngine::Align( const LayoutParameters& layoutParameters,
- const Size& layoutSize,
- const Vector<LineRun>& lines,
- Vector<Vector2>& glyphPositions )
+void LayoutEngine::Align( const Size& layoutSize,
+ Vector<LineRun>& lines )
{
- mImpl->Align( layoutParameters,
- layoutSize,
- lines,
- glyphPositions );
+ mImpl->Align( layoutSize,
+ lines );
}
} // namespace Text
/**
* @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.
+ * @param[in,out] lines The laid-out lines.
*/
- void Align( const LayoutParameters& layoutParameters,
- const Size& layoutSize,
- const Vector<LineRun>& lines,
- Vector<Vector2>& glyphPositions );
+ void Align( const Size& layoutSize,
+ Vector<LineRun>& lines );
private:
*/
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 : 1; ///< Direction of the first character of the paragraph.
- bool ellipsis : 1; ///< Wheter ellipsis is added to the line.
+ 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.
+ float alignmentOffset; ///< The horizontal alignment offset.
+ CharacterDirection direction : 1; ///< Direction of the first character of the paragraph.
+ bool ellipsis : 1; ///< Wheter ellipsis is added to the line.
};
} // namespace Text
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<ScriptRun>::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.
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<FontRun>::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<BidirectionalParagraphInfoRun>::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() )
}
}
-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() )
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()
{
}
*/
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.
*/
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().
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.
*/
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:
/**
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<FontId>::ConstIterator it = mValidFonts.Begin(),
// Skip those characters valid for many scripts like white spaces or '\n'.
bool endOfText = index == numberOfCharacters;
while( !endOfText &&
- IsValidForAllScripts( character ) )
+ TextAbstraction::IsCommonScript( character ) )
{
// Count all these characters to be added into a script.
++numberOfAllScriptCharacters;
// 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 );
+ DALI_ASSERT_DEBUG( ( 0u != currentScriptRun.characterRun.numberOfCharacters ) && "MultilanguageSupport::SetScripts() Trying to insert a script run with zero characters." );
+
+ if( TextAbstraction::UNKNOWN == currentScriptRun.script )
+ {
+ // There are only white spaces in the last script. Set the latin script.
+ currentScriptRun.script = TextAbstraction::LATIN;
}
-}
-void MultilanguageSupport::ReplaceScripts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
+ // Store the last run.
+ scripts.PushBack( currentScriptRun );
}
void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
Vector<FontRun>& fonts )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->MultilanguageSupport::ValidateFonts\n" );
const Length numberOfCharacters = text.Count();
if( 0u == numberOfCharacters )
{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--MultilanguageSupport::ValidateFonts\n" );
// Nothing to do if there are no characters.
return;
}
scriptRunIt,
scriptRunEndIt );
+#ifdef DEBUG_ENABLED
+ {
+ Dali::TextAbstraction::FontDescription description;
+ fontClient.GetDescription( fontId, description );
+
+ DALI_LOG_INFO( gLogFilter,
+ Debug::Verbose,
+ " Initial font set\n Character : %x, Script : %s, Font : %s \n",
+ character,
+ Dali::TextAbstraction::ScriptName[script],
+ description.path.c_str() );
+ }
+#endif
+
if( TextAbstraction::UNKNOWN == script )
{
DALI_LOG_WARNING( "MultilanguageSupport::ValidateFonts. Unknown script!" );
// Whether the font being validated is a default one not set by the user.
const bool isDefault = ( 0u == fontId );
+ DALI_LOG_INFO( gLogFilter,
+ Debug::Verbose,
+ " Is a default font : %s\n",
+ ( isDefault ? "true" : "false" ) );
+
// The default font point size.
PointSize26Dot6 pointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE;
else
{
// Add the font to the valid font cache.
+
+ // At this point the validated font supports the given character. However, characters
+ // common for all scripts, like white spaces or new paragraph characters, need to be
+ // processed differently.
+ //
+ // i.e. A white space can have assigned a DEVANAGARI script but the font assigned may not
+ // support none of the DEVANAGARI glyphs. This font can't be added to the cache as a valid
+ // font for the DEVANAGARI script but the COMMON one.
+ if( TextAbstraction::IsCommonScript( character ) )
+ {
+ validateFontsPerScript = *( validFontsPerScriptCacheBuffer + TextAbstraction::COMMON );
+
+ if( NULL == validateFontsPerScript )
+ {
+ validateFontsPerScript = new ValidateFontsPerScript();
+
+ *( validFontsPerScriptCacheBuffer + TextAbstraction::COMMON ) = validateFontsPerScript;
+ }
+ }
+
validateFontsPerScript->mValidFonts.PushBack( 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;
}
}
+#ifdef DEBUG_ENABLED
+ {
+ Dali::TextAbstraction::FontDescription description;
+ fontClient.GetDescription( fontId, description );
+ DALI_LOG_INFO( gLogFilter,
+ Debug::Verbose,
+ " Validated font set\n Character : %x, Script : %s, Font : %s \n",
+ character,
+ Dali::TextAbstraction::ScriptName[script],
+ description.path.c_str() );
+ }
+#endif
+
// The font is now validated.
if( ( fontId != currentFontRun.fontId ) ||
// Store the last run.
fonts.PushBack( currentFontRun );
}
-}
-
-void MultilanguageSupport::ValidateFonts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--MultilanguageSupport::ValidateFonts\n" );
}
} // namespace Internal
Vector<ScriptRun>& scripts );
/**
- * @copydoc Dali::MultilanguageSupport::ReplaceScripts()
- */
- void ReplaceScripts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
-
- /**
* @copydoc Dali::MultilanguageSupport::ValidateFonts( const Vector<Character>& text, const Vector<ScriptRun>& scripts, Vector<FontRun>& fonts )
*/
void ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
Vector<FontRun>& 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<FontId> mDefaultFontPerScriptCache; ///< Caches the default font for a script.
Vector<ValidateFontsPerScript*> mValidFontsPerScriptCache; ///< Caches valid fonts for a script.
scripts );
}
-void MultilanguageSupport::ReplaceScripts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
- GetImplementation( *this ).ReplaceScripts( model,
- characterIndex,
- numberOfCharactersToRemove,
- numberOfCharactersToInsert );
-}
-
void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
Vector<FontRun>& fonts )
fonts );
}
-void MultilanguageSupport::ValidateFonts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
- GetImplementation( *this ).ValidateFonts( model,
- characterIndex,
- numberOfCharactersToRemove,
- numberOfCharactersToInsert );
-}
-
} // namespace Text
} // namespace Toolkit
Vector<ScriptRun>& 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.
void ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
Vector<FontRun>& 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
AtlasGlyphManager::~AtlasGlyphManager()
{
+ // Clear up any remaining references
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end();
+ ++fontGlyphRecordIt )
+ {
+ for ( Vector< GlyphRecordEntry >::Iterator glyphRecordEntryIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+ glyphRecordEntryIt != fontGlyphRecordIt->mGlyphRecords.End();
+ ++glyphRecordEntryIt )
+ {
+ mAtlasManager.Remove( glyphRecordEntryIt->mImageId );
+ }
+ }
}
AtlasGlyphManagerPtr AtlasGlyphManager::New()
return internal;
}
-void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
+void AtlasGlyphManager::Add( Text::FontId fontId,
+ const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
Dali::Toolkit::AtlasManager::AtlasSlot& slot )
{
- GlyphRecord record;
- record.mFontId = glyph.fontId;
- record.mIndex = glyph.index;
-
mAtlasManager.Add( bitmap, slot );
+
+ GlyphRecordEntry record;
+ record.mIndex = glyph.index;
record.mImageId = slot.mImageId;
- mGlyphRecords.PushBack( record );
+ record.mCount = 1;
+
+ // Have glyph records been created for this fontId ?
+ bool foundGlyph = false;
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end(); ++fontGlyphRecordIt )
+ {
+ if ( fontGlyphRecordIt->mFontId == fontId )
+ {
+ fontGlyphRecordIt->mGlyphRecords.PushBack( record );
+ foundGlyph = true;
+ break;
+ }
+ }
+
+ if ( !foundGlyph )
+ {
+ // We need to add a new font entry
+ FontGlyphRecord fontGlyphRecord;
+ fontGlyphRecord.mFontId = fontId;
+ fontGlyphRecord.mGlyphRecords.PushBack( record );
+ mFontGlyphRecords.push_back( fontGlyphRecord );
+ }
}
void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
const Vector2& position,
Toolkit::AtlasManager::Mesh2D& mesh )
{
- mAtlasManager.GenerateMeshData( imageId, position, mesh );
+ // Generate mesh data and tell Atlas Manager not to handle reference counting ( we'll do it )
+ mAtlasManager.GenerateMeshData( imageId, position, mesh, false );
}
void AtlasGlyphManager::StitchMesh( Toolkit::AtlasManager::Mesh2D& first,
mAtlasManager.StitchMesh( first, second );
}
-void AtlasGlyphManager::Cached( Text::FontId fontId,
+bool AtlasGlyphManager::Cached( Text::FontId fontId,
uint32_t index,
Dali::Toolkit::AtlasManager::AtlasSlot& slot )
{
- for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i )
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end();
+ ++fontGlyphRecordIt )
{
- if ( fontId == mGlyphRecords[ i ].mFontId && index == mGlyphRecords[ i ].mIndex )
+ if ( fontGlyphRecordIt->mFontId == fontId )
{
- slot.mImageId = mGlyphRecords[ i ].mImageId;
- slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
- return;
+ for ( Vector< GlyphRecordEntry >::Iterator glyphRecordIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+ glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
+ ++glyphRecordIt )
+ {
+ if ( glyphRecordIt->mIndex == index )
+ {
+ slot.mImageId = glyphRecordIt->mImageId;
+ slot.mAtlasId = mAtlasManager.GetAtlas( slot.mImageId );
+ return true;
+ }
+ }
}
}
slot.mImageId = 0;
+ return false;
}
Vector2 AtlasGlyphManager::GetAtlasSize( uint32_t atlasId )
mAtlasManager.SetNewAtlasSize( size );
}
-void AtlasGlyphManager::Remove( uint32_t imageId )
+Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId )
+{
+ return mAtlasManager.GetPixelFormat( atlasId );
+}
+
+const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
+{
+ mMetrics.mGlyphCount = mFontGlyphRecords.size();
+ mAtlasManager.GetMetrics( mMetrics.mAtlasMetrics );
+ return mMetrics;
+}
+
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, uint32_t imageId, int32_t delta )
{
- if ( mAtlasManager.Remove( imageId ) )
+ for ( std::vector< FontGlyphRecord >::iterator fontGlyphRecordIt = mFontGlyphRecords.begin();
+ fontGlyphRecordIt != mFontGlyphRecords.end();
+ ++fontGlyphRecordIt )
{
- for ( uint32_t i = 0; i < mGlyphRecords.Size(); ++i )
+ if ( fontGlyphRecordIt->mFontId == fontId )
{
- if ( mGlyphRecords[ i ].mImageId == imageId )
+ for ( Vector< GlyphRecordEntry >::Iterator glyphRecordIt = fontGlyphRecordIt->mGlyphRecords.Begin();
+ glyphRecordIt != fontGlyphRecordIt->mGlyphRecords.End();
+ ++glyphRecordIt )
{
- mGlyphRecords.Remove( mGlyphRecords.Begin() + i );
- return;
+ if ( glyphRecordIt->mImageId == imageId )
+ {
+ glyphRecordIt->mCount += delta;
+ if ( !glyphRecordIt->mCount )
+ {
+ mAtlasManager.Remove( glyphRecordIt->mImageId );
+ fontGlyphRecordIt->mGlyphRecords.Remove( glyphRecordIt );
+ }
+ return;
+ }
}
}
}
}
-Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId )
-{
- return mAtlasManager.GetPixelFormat( atlasId );
-}
-
Material AtlasGlyphManager::GetMaterial( uint32_t atlasId ) const
{
return mAtlasManager.GetMaterial( atlasId );
return mAtlasManager.GetSampler( atlasId );
}
-const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
-{
- mMetrics.mGlyphCount = mGlyphRecords.Size();
- mAtlasManager.GetMetrics( mMetrics.mAtlasMetrics );
- return mMetrics;
-}
-
} // namespace Internal
} // namespace Toolkit
{
public:
- struct GlyphRecord
+ struct GlyphRecordEntry
{
- Text::FontId mFontId;
Text::GlyphIndex mIndex;
uint32_t mImageId;
+ int32_t mCount;
+ };
+
+ struct FontGlyphRecord
+ {
+ Text::FontId mFontId;
+ Vector< GlyphRecordEntry > mGlyphRecords;
};
AtlasGlyphManager();
/**
* @copydoc Toolkit::AtlasGlyphManager::Add
*/
- void Add( const Text::GlyphInfo& glyph,
+ void Add( Text::FontId fontId,
+ const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
Dali::Toolkit::AtlasManager::AtlasSlot& slot );
/**
* @copydoc Toolkit::AtlasGlyphManager::Cached
*/
- void Cached( Text::FontId fontId,
+ bool Cached( Text::FontId fontId,
Text::GlyphIndex index,
Dali::Toolkit::AtlasManager::AtlasSlot& slot );
void SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight );
/**
- * @copydoc Toolkit::AtlasGlyphManager::Remove
+ * @copydoc Toolkit::AtlasGlyphManager::GetPixelFormat
*/
- void Remove( uint32_t imageId );
+ Pixel::Format GetPixelFormat( uint32_t atlasId );
/**
- * @copydoc Toolkit::AtlasGlyphManager::GetPixelFormat
+ * @copydoc toolkit::AtlasGlyphManager::AdjustReferenceCount
*/
- Pixel::Format GetPixelFormat( uint32_t atlasId );
+ void AdjustReferenceCount( Text::FontId fontId, uint32_t imageId, int32_t delta );
/**
* @copydoc Toolkit::AtlasGlyphManager::GetMaterial
private:
Dali::Toolkit::AtlasManager mAtlasManager; ///> Atlas Manager created by GlyphManager
- Vector< GlyphRecord > mGlyphRecords; ///> Cached glyph information
+ std::vector< FontGlyphRecord > mFontGlyphRecords;
Toolkit::AtlasGlyphManager::Metrics mMetrics; ///> Metrics to pass back on GlyphManager status
Shader mEffectBufferShader; ///> Shader used to render drop shadow buffer textures
Shader mShadowShader; ///> Shader used to render drop shadow into buffer
} // namespace Dali
- #endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
\ No newline at end of file
+ #endif // __DALI_TOOLKIT_ATLAS_GLYPH_MANAGER_IMPL_H__
{
}
-void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
+void AtlasGlyphManager::Add( Text::FontId fontId,
+ const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
AtlasManager::AtlasSlot& slot )
{
- GetImplementation(*this).Add( glyph, bitmap, slot );
+ GetImplementation(*this).Add( fontId, glyph, bitmap, slot );
}
void AtlasGlyphManager::GenerateMeshData( uint32_t imageId,
GetImplementation(*this).StitchMesh( first, second );
}
-void AtlasGlyphManager::Cached( Text::FontId fontId,
+bool AtlasGlyphManager::Cached( Text::FontId fontId,
Text::GlyphIndex index,
AtlasManager::AtlasSlot& slot )
{
- GetImplementation(*this).Cached( fontId, index, slot );
+ return GetImplementation(*this).Cached( fontId, index, slot );
}
void AtlasGlyphManager::SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight )
return GetImplementation(*this).GetAtlasSize( atlasId );
}
-void AtlasGlyphManager::Remove( uint32_t imageId )
-{
- GetImplementation(*this).Remove( imageId );
-}
-
Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId )
{
return GetImplementation(*this).GetPixelFormat( atlasId );
return GetImplementation(*this).GetMetrics();
}
+void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, uint32_t imageId, int32_t delta )
+{
+ GetImplementation(*this).AdjustReferenceCount( fontId, imageId, delta );
+}
+
Shader AtlasGlyphManager::GetEffectBufferShader() const
{
return GetImplementation(*this).GetEffectBufferShader();
/**
* @brief Ask Atlas Manager to add a glyph
*
+ * @param[in] fontId fontId glyph comes from
* @param[in] glyph glyph to add to an atlas
* @param[in] bitmap bitmap to use for glyph addition
* @param[out] slot information returned by atlas manager for addition
*/
- void Add( const Text::GlyphInfo& glyph,
+ void Add( Text::FontId fontId,
+ const Text::GlyphInfo& glyph,
const BufferImage& bitmap,
AtlasManager::AtlasSlot& slot );
* @param[in] fontId The font that this glyph comes from
* @param[in] index The GlyphIndex of this glyph
* @param[out] slot container holding information about the glyph( mImage = 0 indicates not being cached )
+ *
+ * @return Whether glyph is cached or not ?
*/
- void Cached( Text::FontId fontId,
+ bool Cached( Text::FontId fontId,
Text::GlyphIndex index,
AtlasManager::AtlasSlot& slot );
void SetNewAtlasSize( uint32_t width, uint32_t height, uint32_t blockWidth, uint32_t blockHeight );
/**
- * @brief Unreference an image from the atlas and remove from cache if no longer needed
- *
- * @param[in] imageId ID of the image
- */
- void Remove( uint32_t imageId );
-
- /**
* @brief Get the Pixel Format used by an atlas
*
* @param[in] atlasId Id of atlas to check
const Metrics& GetMetrics();
/**
+ * @brief Adjust the reference count for an imageId and remove cache entry if it becomes free
+ *
+ * @param[in] fontId the font this image came from
+ * @param[in] imageId The imageId
+ * @param[in] delta adjustment to make to reference count
+ */
+ void AdjustReferenceCount( Text::FontId fontId, uint32_t imageId, int32_t delta );
+
+ /**
* @brief Get Shader used for rendering glyph effect buffers
*
* @return Handle of shader needed
uint32_t mMeshRecordIndex;
};
- struct AtlasRecord
+ struct MaxBlockSize
{
- uint32_t mImageId;
+ FontId mFontId;
+ uint32_t mNeededBlockWidth;
+ uint32_t mNeededBlockHeight;
+ };
+
+ struct CheckEntry
+ {
+ FontId mFontId;
Text::GlyphIndex mIndex;
};
- struct MaxBlockSize
+ struct TextCacheEntry
{
FontId mFontId;
- uint32_t mNeededBlockWidth;
- uint32_t mNeededBlockHeight;
+ Text::GlyphIndex mIndex;
+ uint32_t mImageId;
};
Impl()
AtlasManager::AtlasSlot slot;
std::vector< MeshRecord > meshContainer;
Vector< Extent > extents;
+ TextCacheEntry textCacheEntry;
mDepth = static_cast< int >( depth );
float currentUnderlinePosition = ZERO;
style = STYLE_DROP_SHADOW;
}
- if ( mImageIds.Size() )
+ if ( mTextCache.Size() )
{
- // Unreference any currently used glyphs
- RemoveText();
+ // Update the glyph cache with any changes to current text
+ RemoveText( glyphs );
}
CalculateBlocksSize( glyphs );
const Vector2& position = positions[ i ];
AtlasManager::Mesh2D newMesh;
- 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, newMesh );
- mImageIds.PushBack( slot.mImageId );
- }
- else
+ if ( !mGlyphManager.Cached( glyph.fontId, glyph.index, slot ) )
{
-
// Select correct size for new atlas if needed....?
if ( lastFontId != glyph.fontId )
{
}
// Locate a new slot for our glyph
- mGlyphManager.Add( glyph, bitmap, slot );
-
- // Generate mesh data for this quad, plugging in our supplied position
- if ( slot.mImageId )
- {
- mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh );
- mImageIds.PushBack( slot.mImageId );
- }
+ mGlyphManager.Add( glyph.fontId, glyph, bitmap, slot );
}
}
+
+ // Generate mesh data for this quad, plugging in our supplied position
+ mGlyphManager.GenerateMeshData( slot.mImageId, position, newMesh );
+ textCacheEntry.mFontId = glyph.fontId;
+ textCacheEntry.mImageId = slot.mImageId;
+ textCacheEntry.mIndex = glyph.index;
+ mTextCache.PushBack( textCacheEntry );
+
// Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas)
StitchTextMesh( meshContainer,
newMesh,
mActor = actor;
}
}
- mActor.OffStageSignal().Connect( this, &AtlasRenderer::Impl::OffStageDisconnect );
}
#if defined(DEBUG_ENABLED)
Toolkit::AtlasGlyphManager::Metrics metrics = mGlyphManager.GetMetrics();
}
}
- // Unreference any glyphs that were used with this actor
- void OffStageDisconnect( Dali::Actor actor )
+ void RemoveText( const Vector<GlyphInfo>& glyphs )
{
- RemoveText();
- }
+ Vector< CheckEntry > checked;
+ CheckEntry checkEntry;
- void RemoveText()
- {
- for ( uint32_t i = 0; i < mImageIds.Size(); ++i )
+ for ( Vector< TextCacheEntry >::Iterator tCit = mTextCache.Begin(); tCit != mTextCache.End(); ++tCit )
{
- mGlyphManager.Remove( mImageIds[ i ] );
+ uint32_t index = tCit->mIndex;
+ uint32_t fontId = tCit->mFontId;
+
+ // Check that this character has not already been checked...
+ bool wasChecked = false;
+ for ( Vector< CheckEntry >::Iterator cEit = checked.Begin(); cEit != checked.End(); ++cEit )
+ {
+ if ( fontId == cEit->mFontId && index == cEit->mIndex )
+ {
+ wasChecked = true;
+ }
+ }
+
+ if ( !wasChecked )
+ {
+
+ int32_t newCount = 0;
+ int32_t oldCount = 0;
+
+ // How many times does this character occur in the old text ?
+ for ( Vector< TextCacheEntry >::Iterator oTcit = mTextCache.Begin(); oTcit != mTextCache.End(); ++oTcit )
+ {
+ if ( fontId == oTcit->mFontId && index == oTcit->mIndex )
+ {
+ oldCount++;
+ }
+ }
+
+ // And how many times in the new ?
+ for ( Vector< GlyphInfo >::Iterator cGit = glyphs.Begin(); cGit != glyphs.End(); ++cGit )
+ {
+ if ( fontId == cGit->fontId && index == cGit->index )
+ {
+ newCount++;
+ }
+ }
+ mGlyphManager.AdjustReferenceCount( fontId, tCit->mImageId, newCount - oldCount );
+ checkEntry.mIndex = index;
+ checkEntry.mFontId = fontId;
+ checked.PushBack( checkEntry );
+ }
}
- mImageIds.Resize( 0 );
+ mTextCache.Resize( 0 );
}
void CalculateBlocksSize( const Vector<GlyphInfo>& glyphs )
Actor 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
std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas
std::vector< uint32_t > mFace; ///> Face indices for a quad
+ Vector< TextCacheEntry > mTextCache;
Property::Map mQuadVertexFormat;
Property::Map mQuadIndexFormat;
int mDepth;
AtlasRenderer::~AtlasRenderer()
{
+ Vector< GlyphInfo > emptyGlyphs;
+ mImpl->RemoveText( emptyGlyphs );
delete mImpl;
}
#endif
}
-void ReplaceLineBreakInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
void SetWordBreakInfo( const Vector<Character>& text,
Vector<WordBreakInfo>& wordBreakInfo )
{
#endif
}
-void ReplaceWordBreakInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
} // namespace Text
} // namespace Toolkit
Vector<LineBreakInfo>& 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.
void SetWordBreakInfo( const Vector<Character>& text,
Vector<WordBreakInfo>& 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
glyphToCharacterMap.Resize( totalNumberOfGlyphs );
}
-void ShapeText( const LogicalModel& logicalModel,
- VisualModel& visualModel,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
} // namespace Text
} // namespace Toolkit
Vector<CharacterIndex>& glyphToCharacterMap,
Vector<Length>& 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
{
+class Actor;
+
namespace Toolkit
{
virtual ~ControlInterface();
/**
+ * @brief Add a decoration.
+ *
+ * @param[in] decoration The actor displaying a decoration.
+ * @param[in] needsClipping Whether the actor needs clipping.
+ */
+ virtual void AddDecoration( Actor& actor, bool needsClipping ) = 0;
+
+ /**
* @brief Called to request a text relayout.
*/
virtual void RequestTextRelayout() = 0;
mDecoratorUpdated( false ),
mCursorBlinkEnabled( true ),
mGrabHandleEnabled( true ),
- mGrabHandlePopupEnabled( false ),
- mSelectionEnabled( false ),
+ mGrabHandlePopupEnabled( true ),
+ mSelectionEnabled( true ),
mHorizontalScrollingEnabled( true ),
mVerticalScrollingEnabled( false ),
mUpdateCursorPosition( false ),
mUpdateLeftSelectionPosition( false ),
mUpdateRightSelectionPosition( false ),
- mScrollAfterUpdateCursorPosition( false )
+ mScrollAfterUpdatePosition( false ),
+ mScrollAfterDelete( false )
{}
EventData::~EventData()
{
switch( iter->type )
{
- case Event::CURSOR_KEY_EVENT:
- {
- OnCursorKeyEvent( *iter );
- break;
- }
- case Event::TAP_EVENT:
- {
- OnTapEvent( *iter );
- break;
- }
- case Event::PAN_EVENT:
- {
- OnPanEvent( *iter );
- break;
- }
- case Event::GRAB_HANDLE_EVENT:
- case Event::LEFT_SELECTION_HANDLE_EVENT:
- case Event::RIGHT_SELECTION_HANDLE_EVENT: // Fall through
- {
- OnHandleEvent( *iter );
- break;
- }
+ case Event::CURSOR_KEY_EVENT:
+ {
+ OnCursorKeyEvent( *iter );
+ break;
+ }
+ case Event::TAP_EVENT:
+ {
+ OnTapEvent( *iter );
+ break;
+ }
+ case Event::PAN_EVENT:
+ {
+ OnPanEvent( *iter );
+ break;
+ }
+ case Event::GRAB_HANDLE_EVENT:
+ case Event::LEFT_SELECTION_HANDLE_EVENT:
+ case Event::RIGHT_SELECTION_HANDLE_EVENT: // Fall through
+ {
+ OnHandleEvent( *iter );
+ break;
+ }
+ case Event::SELECT:
+ {
+ OnSelectEvent( *iter );
+ break;
+ }
+ case Event::SELECT_ALL:
+ {
+ OnSelectAllEvent();
+ break;
+ }
}
}
}
UpdateCursorPosition();
- if( mEventData->mScrollAfterUpdateCursorPosition )
+ if( mEventData->mScrollAfterUpdatePosition )
{
- ScrollToMakeCursorVisible();
- mEventData->mScrollAfterUpdateCursorPosition = false;
+ const Vector2& primaryCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
+
+ ScrollToMakePositionVisible( primaryCursorPosition );
+ mEventData->mScrollAfterUpdatePosition = false;
}
mEventData->mDecoratorUpdated = true;
mEventData->mUpdateCursorPosition = false;
}
- else if( mEventData->mUpdateLeftSelectionPosition )
+ else if( mEventData->mScrollAfterDelete )
{
- UpdateSelectionHandle( LEFT_SELECTION_HANDLE );
-
- if( mEventData->mScrollAfterUpdateCursorPosition )
- {
- ScrollToMakeCursorVisible();
- mEventData->mScrollAfterUpdateCursorPosition = false;
- }
-
+ ScrollTextToMatchCursor();
mEventData->mDecoratorUpdated = true;
- mEventData->mUpdateLeftSelectionPosition = false;
+ mEventData->mScrollAfterDelete = false;
}
- else if( mEventData->mUpdateRightSelectionPosition )
+ else
{
- UpdateSelectionHandle( RIGHT_SELECTION_HANDLE );
+ bool leftScroll = false;
+ bool rightScroll = false;
+
+ if( mEventData->mUpdateLeftSelectionPosition )
+ {
+ UpdateSelectionHandle( LEFT_SELECTION_HANDLE );
+
+ if( mEventData->mScrollAfterUpdatePosition )
+ {
+ const Vector2& leftHandlePosition = mEventData->mDecorator->GetPosition( LEFT_SELECTION_HANDLE );
+
+ ScrollToMakePositionVisible( leftHandlePosition );
+ leftScroll = true;
+ }
- if( mEventData->mScrollAfterUpdateCursorPosition )
+ mEventData->mDecoratorUpdated = true;
+ mEventData->mUpdateLeftSelectionPosition = false;
+ }
+
+ if( mEventData->mUpdateRightSelectionPosition )
{
- ScrollToMakeCursorVisible();
- mEventData->mScrollAfterUpdateCursorPosition = false;
+ UpdateSelectionHandle( RIGHT_SELECTION_HANDLE );
+
+ if( mEventData->mScrollAfterUpdatePosition )
+ {
+ const Vector2& rightHandlePosition = mEventData->mDecorator->GetPosition( RIGHT_SELECTION_HANDLE );
+
+ ScrollToMakePositionVisible( rightHandlePosition );
+ rightScroll = true;
+ }
+
+ mEventData->mDecoratorUpdated = true;
+ mEventData->mUpdateRightSelectionPosition = false;
}
- mEventData->mDecoratorUpdated = true;
- mEventData->mUpdateRightSelectionPosition = false;
+ if( leftScroll || rightScroll )
+ {
+ mEventData->mScrollAfterUpdatePosition = false;
+ }
}
mEventData->mEventQueue.clear();
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents\n" );
- bool decoratorUpdated = mEventData->mDecoratorUpdated;
+ const bool decoratorUpdated = mEventData->mDecoratorUpdated;
mEventData->mDecoratorUpdated = false;
+
return decoratorUpdated;
}
}
else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode )
{
- if( mLogicalModel->GetNumberOfCharacters() > mEventData->mPrimaryCursorPosition )
+ if( mLogicalModel->mText.Count() > mEventData->mPrimaryCursorPosition )
{
mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition );
}
}
mEventData->mUpdateCursorPosition = true;
- mEventData->mScrollAfterUpdateCursorPosition = true;
+ mEventData->mScrollAfterUpdatePosition = true;
}
void Controller::Impl::OnTapEvent( const Event& event )
}
mEventData->mUpdateCursorPosition = true;
- mEventData->mScrollAfterUpdateCursorPosition = true;
- }
- else if( mEventData->mSelectionEnabled &&
- ( 2u == tapCount ) )
- {
- RepositionSelectionHandles( event.p2.mFloat, event.p3.mFloat );
+ mEventData->mScrollAfterUpdatePosition = true;
}
}
}
}
const unsigned int state = event.p1.mUint;
+ const bool handleStopScrolling = ( HANDLE_STOP_SCROLLING == state );
if( HANDLE_PRESSED == state )
{
if( Event::GRAB_HANDLE_EVENT == event.type )
{
- ChangeState ( EventData::EDITING );
+ ChangeState ( EventData::GRAB_HANDLE_PANNING );
if( handleNewPosition != mEventData->mPrimaryCursorPosition )
{
}
else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type )
{
- if( handleNewPosition != mEventData->mLeftSelectionPosition )
+ ChangeState ( EventData::SELECTION_HANDLE_PANNING );
+
+ if( ( handleNewPosition != mEventData->mLeftSelectionPosition ) &&
+ ( handleNewPosition != mEventData->mRightSelectionPosition ) )
{
mEventData->mLeftSelectionPosition = handleNewPosition;
+
+ RepositionSelectionHandles( mEventData->mLeftSelectionPosition,
+ mEventData->mRightSelectionPosition );
+
mEventData->mUpdateLeftSelectionPosition = true;
}
}
else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type )
{
- if( handleNewPosition != mEventData->mRightSelectionPosition )
+ ChangeState ( EventData::SELECTION_HANDLE_PANNING );
+
+ if( ( handleNewPosition != mEventData->mRightSelectionPosition ) &&
+ ( handleNewPosition != mEventData->mLeftSelectionPosition ) )
{
mEventData->mRightSelectionPosition = handleNewPosition;
+
+ RepositionSelectionHandles( mEventData->mLeftSelectionPosition,
+ mEventData->mRightSelectionPosition );
+
mEventData->mUpdateRightSelectionPosition = true;
}
}
- }
+ } // end ( HANDLE_PRESSED == state )
else if( ( HANDLE_RELEASED == state ) ||
- ( HANDLE_STOP_SCROLLING == state ) )
+ handleStopScrolling )
{
- if( mEventData->mGrabHandlePopupEnabled )
+ CharacterIndex handlePosition = 0u;
+ if( handleStopScrolling )
{
- ChangeState( EventData::EDITING_WITH_POPUP );
+ // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords.
+ const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
+ const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
+
+ handlePosition = GetClosestCursorIndex( xPosition, yPosition );
}
+
if( Event::GRAB_HANDLE_EVENT == event.type )
{
mEventData->mUpdateCursorPosition = true;
- if( HANDLE_STOP_SCROLLING == state )
+ ChangeState( EventData::EDITING_WITH_POPUP );
+
+ if( handleStopScrolling )
{
- // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords.
- const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
- const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
+ mEventData->mScrollAfterUpdatePosition = mEventData->mPrimaryCursorPosition != handlePosition;
+ mEventData->mPrimaryCursorPosition = handlePosition;
+ }
+ }
+ else if( Event::LEFT_SELECTION_HANDLE_EVENT == event.type )
+ {
+ ChangeState( EventData::SELECTING );
- mEventData->mPrimaryCursorPosition = GetClosestCursorIndex( xPosition, yPosition );
+ if( handleStopScrolling )
+ {
+ mEventData->mUpdateLeftSelectionPosition = ( mEventData->mLeftSelectionPosition != handlePosition ) && ( mEventData->mRightSelectionPosition != handlePosition);
+ mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateLeftSelectionPosition;
+
+ if( mEventData->mUpdateLeftSelectionPosition )
+ {
+ mEventData->mLeftSelectionPosition = handlePosition;
- mEventData->mScrollAfterUpdateCursorPosition = true;
+ RepositionSelectionHandles( mEventData->mLeftSelectionPosition,
+ mEventData->mRightSelectionPosition );
+ }
}
}
+ else if( Event::RIGHT_SELECTION_HANDLE_EVENT == event.type )
+ {
+ ChangeState( EventData::SELECTING );
+
+ if( handleStopScrolling )
+ {
+ mEventData->mUpdateRightSelectionPosition = ( mEventData->mRightSelectionPosition != handlePosition ) && ( mEventData->mLeftSelectionPosition != handlePosition );
+ mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateRightSelectionPosition;
+
+ if( mEventData->mUpdateRightSelectionPosition )
+ {
+ mEventData->mRightSelectionPosition = handlePosition;
+ RepositionSelectionHandles( mEventData->mLeftSelectionPosition,
+ mEventData->mRightSelectionPosition );
+ }
+ }
+ }
+
mEventData->mDecoratorUpdated = true;
- }
+ } // end ( ( HANDLE_RELEASED == state ) || ( HANDLE_STOP_SCROLLING == state ) )
else if( HANDLE_SCROLLING == state )
{
const float xSpeed = event.p2.mFloat;
const Vector2& actualSize = mVisualModel->GetActualSize();
+ const Vector2 currentScrollPosition = mEventData->mScrollPosition;
mEventData->mScrollPosition.x += xSpeed;
ClampHorizontalScroll( actualSize );
- mEventData->mDecoratorUpdated = true;
+ if( Vector2::ZERO == ( currentScrollPosition - mEventData->mScrollPosition ) )
+ {
+ // Notify the decorator there is no more text to scroll.
+ // The decorator won't send more scroll events.
+ mEventData->mDecorator->NotifyEndOfScroll();
+ }
+ else
+ {
+ const bool scrollRightDirection = xSpeed > 0.f;
+ const bool leftSelectionHandleEvent = Event::LEFT_SELECTION_HANDLE_EVENT == event.type;
+ const bool rightSelectionHandleEvent = Event::RIGHT_SELECTION_HANDLE_EVENT == event.type;
+
+ if( Event::GRAB_HANDLE_EVENT == event.type )
+ {
+ ChangeState( EventData::GRAB_HANDLE_PANNING );
+
+ Vector2 position = mEventData->mDecorator->GetPosition( GRAB_HANDLE );
+
+ // Position the grag handle close to either the left or right edge.
+ position.x = scrollRightDirection ? 0.f : mControlSize.width;
+
+ // Get the new handle position.
+ // The grab handle's position is in decorator coords. Need to transforms to text coords.
+ const CharacterIndex handlePosition = GetClosestCursorIndex( position.x - mEventData->mScrollPosition.x - mAlignmentOffset.x,
+ position.y - mEventData->mScrollPosition.y - mAlignmentOffset.y );
+
+ mEventData->mUpdateCursorPosition = mEventData->mPrimaryCursorPosition != handlePosition;
+ mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateCursorPosition;
+ mEventData->mPrimaryCursorPosition = handlePosition;
+ }
+ else if( leftSelectionHandleEvent || rightSelectionHandleEvent )
+ {
+ // TODO: This is recalculating the selection box every time the text is scrolled with the selection handles.
+ // Think if something can be done to save power.
+
+ ChangeState( EventData::SELECTION_HANDLE_PANNING );
+
+ Vector2 position = mEventData->mDecorator->GetPosition( leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE );
+
+ // Position the selection handle close to either the left or right edge.
+ position.x = scrollRightDirection ? 0.f : mControlSize.width;
+
+ // Get the new handle position.
+ // The selection handle's position is in decorator coords. Need to transforms to text coords.
+ const CharacterIndex handlePosition = GetClosestCursorIndex( position.x - mEventData->mScrollPosition.x - mAlignmentOffset.x,
+ position.y - mEventData->mScrollPosition.y - mAlignmentOffset.y );
+
+ if( leftSelectionHandleEvent )
+ {
+ mEventData->mUpdateLeftSelectionPosition = handlePosition != mEventData->mLeftSelectionPosition;
+ mEventData->mLeftSelectionPosition = handlePosition;
+ }
+ else
+ {
+ mEventData->mUpdateRightSelectionPosition = handlePosition != mEventData->mRightSelectionPosition;
+ mEventData->mRightSelectionPosition = handlePosition;
+ }
+
+ if( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition )
+ {
+ RepositionSelectionHandles( mEventData->mLeftSelectionPosition,
+ mEventData->mRightSelectionPosition );
+
+ mEventData->mScrollAfterUpdatePosition = true;
+ }
+ }
+ mEventData->mDecoratorUpdated = true;
+ }
+ } // end ( HANDLE_SCROLLING == state )
+}
+
+void Controller::Impl::OnSelectEvent( const Event& event )
+{
+ if( NULL == mEventData )
+ {
+ // Nothing to do if there is no text.
+ return;
+ }
+
+ if( mEventData->mSelectionEnabled )
+ {
+ // The event.p2 and event.p3 are in decorator coords. Need to transforms to text coords.
+ const float xPosition = event.p2.mFloat - mEventData->mScrollPosition.x - mAlignmentOffset.x;
+ const float yPosition = event.p3.mFloat - mEventData->mScrollPosition.y - mAlignmentOffset.y;
+
+ const CharacterIndex leftPosition = mEventData->mLeftSelectionPosition;
+ const CharacterIndex rightPosition = mEventData->mRightSelectionPosition;
+
+ RepositionSelectionHandles( xPosition,
+ yPosition );
+
+ mEventData->mUpdateLeftSelectionPosition = leftPosition != mEventData->mLeftSelectionPosition;
+ mEventData->mUpdateRightSelectionPosition = rightPosition != mEventData->mRightSelectionPosition;
+
+ mEventData->mScrollAfterUpdatePosition = ( ( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition ) &&
+ ( mEventData->mLeftSelectionPosition != mEventData->mRightSelectionPosition ) );
}
}
-void Controller::Impl::RepositionSelectionHandles( float visualX, float visualY )
+void Controller::Impl::OnSelectAllEvent()
{
if( NULL == mEventData )
{
- // Nothing to do if there is no text input.
+ // Nothing to do if there is no text.
return;
}
- // TODO - Find which word was selected
+ if( mEventData->mSelectionEnabled )
+ {
+ RepositionSelectionHandles( 0u,
+ mLogicalModel->mText.Count() );
- const Vector<GlyphInfo>& glyphs = mVisualModel->mGlyphs;
- const Vector<Vector2>::SizeType glyphCount = glyphs.Count();
+ mEventData->mScrollAfterUpdatePosition = true;
+ mEventData->mUpdateLeftSelectionPosition = true;
+ mEventData->mUpdateRightSelectionPosition = true;
+ }
+}
- const Vector<Vector2>& positions = mVisualModel->mGlyphPositions;
- const Vector<Vector2>::SizeType positionCount = positions.Count();
+void Controller::Impl::RetrieveSelection( std::string& selectedText, bool deleteAfterRetreival )
+{
+ if( mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition )
+ {
+ // Nothing to select if handles are in the same place.
+ selectedText="";
+ return;
+ }
- // Guard against glyphs which did not fit inside the layout
- const Vector<Vector2>::SizeType count = (positionCount < glyphCount) ? positionCount : glyphCount;
+ //Get start and end position of selection
+ uint32_t startOfSelectedText = mEventData->mLeftSelectionPosition;
+ uint32_t lengthOfSelectedText = mEventData->mRightSelectionPosition - startOfSelectedText;
- if( count )
+ // Validate the start and end selection points
+ if( ( startOfSelectedText >= 0 ) && ( ( startOfSelectedText + lengthOfSelectedText ) <= mLogicalModel->mText.Count() ) )
{
- float primaryX = positions[0].x + mEventData->mScrollPosition.x;
- float secondaryX = positions[count-1].x + glyphs[count-1].width + mEventData->mScrollPosition.x;
+ //Get text as a UTF8 string
+ Vector<Character>& utf32Characters = mLogicalModel->mText;
+
+ Utf32ToUtf8( &utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText );
+
+ if ( deleteAfterRetreival ) // Only delete text if copied successfully
+ {
+ // Delete text between handles
+ Vector<Character>& currentText = mLogicalModel->mText;
+
+ Vector<Character>::Iterator first = currentText.Begin() + startOfSelectedText;
+ Vector<Character>::Iterator last = first + lengthOfSelectedText;
+ currentText.Erase( first, last );
+ }
+ mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition;
+ mEventData->mScrollAfterDelete = true;
+ mEventData->mDecoratorUpdated = true;
+ }
+}
- // TODO - multi-line selection
- const Vector<LineRun>& lines = mVisualModel->mLines;
- float height = lines.Count() ? lines[0].ascender + -lines[0].descender : 0.0f;
+bool Controller::Impl::CopyStringToClipboard( std::string& source )
+{
+ //Send string to clipboard
+ return ( mClipboard && mClipboard.SetItem( source ) );
+}
- mEventData->mDecorator->SetPosition( LEFT_SELECTION_HANDLE, primaryX, mEventData->mScrollPosition.y, height );
- mEventData->mDecorator->SetPosition( RIGHT_SELECTION_HANDLE, secondaryX, mEventData->mScrollPosition.y, height );
+void Controller::Impl::SendSelectionToClipboard( bool deleteAfterSending )
+{
+ std::string selectedText;
+ RetrieveSelection( selectedText, deleteAfterSending );
+ CopyStringToClipboard( selectedText );
+ ChangeState( EventData::EDITING );
+}
- mEventData->mDecorator->ClearHighlights();
- mEventData->mDecorator->AddHighlight( primaryX, mEventData->mScrollPosition.y, secondaryX, height + mEventData->mScrollPosition.y );
+void Controller::Impl::GetTextFromClipboard( unsigned int itemIndex, std::string& retreivedString )
+{
+ if ( mClipboard )
+ {
+ retreivedString = mClipboard.GetItem( itemIndex );
}
}
+void Controller::Impl::RepositionSelectionHandles( CharacterIndex selectionStart, CharacterIndex selectionEnd )
+{
+ if( selectionStart == selectionEnd )
+ {
+ // Nothing to select if handles are in the same place.
+ return;
+ }
+
+ mEventData->mDecorator->ClearHighlights();
+
+ mEventData->mLeftSelectionPosition = selectionStart;
+ mEventData->mRightSelectionPosition = selectionEnd;
+
+ const GlyphIndex* const charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin();
+ const Length* const glyphsPerCharacterBuffer = mVisualModel->mGlyphsPerCharacter.Begin();
+ const GlyphInfo* const glyphsBuffer = mVisualModel->mGlyphs.Begin();
+ const Vector2* const positionsBuffer = mVisualModel->mGlyphPositions.Begin();
+
+ // TODO: Better algorithm to create the highlight box.
+ // TODO: Multi-line.
+
+ const Vector<LineRun>& lines = mVisualModel->mLines;
+ const LineRun& firstLine = *lines.Begin();
+ const float height = firstLine.ascender + -firstLine.descender;
+
+ const bool indicesSwapped = ( selectionStart > selectionEnd );
+ if( indicesSwapped )
+ {
+ std::swap( selectionStart, selectionEnd );
+ }
+
+ GlyphIndex glyphStart = *( charactersToGlyphBuffer + selectionStart );
+ GlyphIndex glyphEnd = *( charactersToGlyphBuffer + ( selectionEnd - 1u ) ) + *( glyphsPerCharacterBuffer + ( selectionEnd - 1u ) ) - 1u;
+
+ mEventData->mDecorator->SwapSelectionHandlesEnabled( firstLine.direction != indicesSwapped );
+
+ const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset;
+
+ for( GlyphIndex index = glyphStart; index <= glyphEnd; ++index )
+ {
+ const GlyphInfo& glyph = *( glyphsBuffer + index );
+ const Vector2& position = *( positionsBuffer + index );
+
+ const float xPosition = position.x - glyph.xBearing + offset.x;
+ mEventData->mDecorator->AddHighlight( xPosition, offset.y, xPosition + glyph.advance, height );
+ }
+
+ CursorInfo primaryCursorInfo;
+ GetCursorPosition( mEventData->mLeftSelectionPosition,
+ primaryCursorInfo );
+
+ CursorInfo secondaryCursorInfo;
+ GetCursorPosition( mEventData->mRightSelectionPosition,
+ secondaryCursorInfo );
+
+ const Vector2 primaryPosition = primaryCursorInfo.primaryPosition + offset;
+ const Vector2 secondaryPosition = secondaryCursorInfo.primaryPosition + offset;
+
+ mEventData->mDecorator->SetPosition( LEFT_SELECTION_HANDLE, primaryPosition.x, primaryPosition.y, primaryCursorInfo.lineHeight );
+
+ mEventData->mDecorator->SetPosition( RIGHT_SELECTION_HANDLE, secondaryPosition.x, secondaryPosition.y, secondaryCursorInfo.lineHeight );
+
+ // Set the flag to update the decorator.
+ mEventData->mDecoratorUpdated = true;
+}
+
+void Controller::Impl::RepositionSelectionHandles( float visualX, float visualY )
+{
+ if( NULL == mEventData )
+ {
+ // Nothing to do if there is no text input.
+ return;
+ }
+
+ if( IsShowingPlaceholderText() )
+ {
+ // Nothing to do if there is the place-holder text.
+ return;
+ }
+
+ const Length numberOfGlyphs = mVisualModel->mGlyphs.Count();
+ const Length numberOfLines = mVisualModel->mLines.Count();
+ if( 0 == numberOfGlyphs ||
+ 0 == numberOfLines )
+ {
+ // Nothing to do if there is no text.
+ return;
+ }
+
+ // Find which word was selected
+ CharacterIndex selectionStart( 0 );
+ CharacterIndex selectionEnd( 0 );
+ FindSelectionIndices( visualX, visualY, selectionStart, selectionEnd );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "%p selectionStart %d selectionEnd %d\n", this, selectionStart, selectionEnd );
+
+ if( selectionStart == selectionEnd )
+ {
+ ChangeState( EventData::EDITING );
+ // Nothing to select. i.e. a white space, out of bounds
+ return;
+ }
+
+ RepositionSelectionHandles( selectionStart, selectionEnd );
+}
+
void Controller::Impl::ChangeState( EventData::State newState )
{
if( NULL == mEventData )
mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+ if( mEventData->mGrabHandlePopupEnabled )
+ {
+ TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::CUT | TextSelectionPopup::COPY );
+ if ( !IsClipboardEmpty() )
+ {
+ buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+ }
+
+ mEventData->mDecorator->SetEnabledPopupButtons( buttonsToShow );
+ mEventData->mDecorator->SetPopupActive( true );
+ }
+ mEventData->mDecoratorUpdated = true;
+ }
+ else if ( EventData::SELECTION_CHANGED == mEventData->mState )
+ {
+ if( mEventData->mGrabHandlePopupEnabled )
+ {
+ TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::CUT | TextSelectionPopup::COPY );
+ if ( !IsClipboardEmpty() )
+ {
+ buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+ }
+ mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
+ mEventData->mDecorator->SetEnabledPopupButtons( buttonsToShow );
+ mEventData->mDecorator->SetPopupActive( true );
+ }
mEventData->mDecoratorUpdated = true;
}
else if( EventData::EDITING == mEventData->mState )
mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
+ if( mEventData->mGrabHandlePopupEnabled )
+ {
+ mEventData->mDecorator->SetPopupActive( false );
+ }
mEventData->mDecoratorUpdated = true;
}
else if( EventData::EDITING_WITH_POPUP == mEventData->mState )
{
mEventData->mDecorator->StartCursorBlink();
}
- mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
if( mEventData->mSelectionEnabled )
{
- mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
- mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+ mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
+ mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
+ }
+ else
+ {
+ mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
}
if( mEventData->mGrabHandlePopupEnabled )
{
+ TextSelectionPopup::Buttons buttonsToShow = TextSelectionPopup::Buttons( TextSelectionPopup::SELECT | TextSelectionPopup::SELECT_ALL );
+
+ if ( !IsClipboardEmpty() )
+ {
+ buttonsToShow = TextSelectionPopup::Buttons ( ( buttonsToShow | TextSelectionPopup::PASTE ) );
+ }
+
+ mEventData->mDecorator->SetEnabledPopupButtons( buttonsToShow );
mEventData->mDecorator->SetPopupActive( true );
}
mEventData->mDecoratorUpdated = true;
}
+ else if ( EventData::SELECTION_HANDLE_PANNING == mEventData->mState )
+ {
+ mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_NONE );
+ mEventData->mDecorator->StopCursorBlink();
+ mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false );
+ mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, true );
+ mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, true );
+ if( mEventData->mGrabHandlePopupEnabled )
+ {
+ mEventData->mDecorator->SetPopupActive( false );
+ }
+ mEventData->mDecoratorUpdated = true;
+ }
+ else if ( EventData::GRAB_HANDLE_PANNING == mEventData->mState )
+ {
+ mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
+ if( mEventData->mCursorBlinkEnabled )
+ {
+ mEventData->mDecorator->StartCursorBlink();
+ }
+ mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
+ mEventData->mDecorator->SetHandleActive( LEFT_SELECTION_HANDLE, false );
+ mEventData->mDecorator->SetHandleActive( RIGHT_SELECTION_HANDLE, false );
+ if( mEventData->mGrabHandlePopupEnabled )
+ {
+ mEventData->mDecorator->SetPopupActive( false );
+ }
+ mEventData->mDecoratorUpdated = true;
+ }
}
}
}
}
+ if( lineIndex == 0 )
+ {
+ return 0;
+ }
+
return lineIndex-1;
}
+void Controller::Impl::FindSelectionIndices( float visualX, float visualY, CharacterIndex& startIndex, CharacterIndex& endIndex )
+{
+ CharacterIndex hitCharacter = GetClosestCursorIndex( visualX, visualY );
+ if( hitCharacter >= mLogicalModel->mText.Count() )
+ {
+ // Selection out of bounds.
+ return;
+ }
+
+ startIndex = hitCharacter;
+ endIndex = hitCharacter;
+
+ if( !TextAbstraction::IsWhiteSpace( mLogicalModel->mText[hitCharacter] ) )
+ {
+ // Find the start and end of the text
+ for( startIndex = hitCharacter; startIndex > 0; --startIndex )
+ {
+ Character charCode = mLogicalModel->mText[ startIndex-1 ];
+ if( TextAbstraction::IsWhiteSpace( charCode ) )
+ {
+ break;
+ }
+ }
+ const CharacterIndex pastTheEnd = mLogicalModel->mText.Count();
+ for( endIndex = hitCharacter + 1u; endIndex < pastTheEnd; ++endIndex )
+ {
+ Character charCode = mLogicalModel->mText[ endIndex ];
+ if( TextAbstraction::IsWhiteSpace( charCode ) )
+ {
+ break;
+ }
+ }
+ }
+}
+
CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
float visualY )
{
const Vector2& position = *( positionsBuffer + glyphLogicalOrderIndex );
- const float glyphX = -glyphMetrics.xBearing + position.x + 0.5f * glyphMetrics.advance;
+ // Find the mid-point of the area containing the glyph
+ const float glyphCenter = -glyphMetrics.xBearing + position.x + 0.5f * glyphMetrics.advance;
- if( visualX < glyphX )
+ if( visualX < glyphCenter )
{
matched = true;
break;
visualIndex = endCharacter;
}
- return hasRightToLeftCharacters ? *( visualToLogicalCursorBuffer + visualIndex ) : visualIndex;
+ logicalIndex = hasRightToLeftCharacters ? *( visualToLogicalCursorBuffer + visualIndex ) : visualIndex;
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "%p closest visualIndex %d logicalIndex %d\n", this, visualIndex, logicalIndex );
+ return logicalIndex;
}
void Controller::Impl::GetCursorPosition( CharacterIndex logical,
// 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;
+ const bool isLastPosition = mLogicalModel->mText.Count() == logical;
if( isFirstPosition && isLastPosition )
{
}
}
-void Controller::Impl::ScrollToMakeCursorVisible()
+void Controller::Impl::ScrollToMakePositionVisible( const Vector2& position )
{
- if( NULL == mEventData )
- {
- // Nothing to do if there is no text input.
- return;
- }
-
- const Vector2& primaryCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
-
Vector2 offset;
bool updateDecorator = false;
- if( primaryCursorPosition.x < 0.f )
+ if( position.x < 0.f )
{
- offset.x = -primaryCursorPosition.x;
+ offset.x = -position.x;
mEventData->mScrollPosition.x += offset.x;
updateDecorator = true;
}
- else if( primaryCursorPosition.x > mControlSize.width )
+ else if( position.x > mControlSize.width )
{
- offset.x = mControlSize.width - primaryCursorPosition.x;
+ offset.x = mControlSize.width - position.x;
mEventData->mScrollPosition.x += offset.x;
updateDecorator = true;
}
// TODO : calculate the vertical scroll.
}
+void Controller::Impl::ScrollTextToMatchCursor()
+{
+ // Get the current cursor position in decorator coords.
+ const Vector2& currentCursorPosition = mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
+
+ // Calculate the new cursor position.
+ CursorInfo cursorInfo;
+ GetCursorPosition( mEventData->mPrimaryCursorPosition,
+ cursorInfo );
+
+ // Calculate the offset to match the cursor position before the character was deleted.
+ mEventData->mScrollPosition.x = currentCursorPosition.x - cursorInfo.primaryPosition.x - mAlignmentOffset.x;
+
+ ClampHorizontalScroll( mVisualModel->GetActualSize() );
+ bool updateCursorPosition = true;
+
+ const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset;
+ const Vector2 cursorPosition = cursorInfo.primaryPosition + offset;
+
+ if( updateCursorPosition )
+ {
+ // Sets the cursor position.
+ mEventData->mDecorator->SetPosition( PRIMARY_CURSOR,
+ cursorPosition.x,
+ cursorPosition.y,
+ cursorInfo.primaryCursorHeight,
+ cursorInfo.lineHeight );
+
+ // Sets the grab handle position.
+ mEventData->mDecorator->SetPosition( GRAB_HANDLE,
+ cursorPosition.x,
+ cursorPosition.y,
+ cursorInfo.lineHeight );
+
+ if( cursorInfo.isSecondaryCursor )
+ {
+ mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_BOTH );
+ mEventData->mDecorator->SetPosition( SECONDARY_CURSOR,
+ cursorInfo.secondaryPosition.x + offset.x,
+ cursorInfo.secondaryPosition.y + offset.y,
+ cursorInfo.secondaryCursorHeight,
+ cursorInfo.lineHeight );
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Secondary cursor position: %f,%f\n", cursorInfo.secondaryPosition.x + offset.x, cursorInfo.secondaryPosition.y + offset.y );
+ }
+ else
+ {
+ mEventData->mDecorator->SetActiveCursor( ACTIVE_CURSOR_PRIMARY );
+ }
+ }
+}
+
void Controller::Impl::RequestRelayout()
{
mControlInterface.RequestTextRelayout();
*/
// EXTERNAL INCLUDES
-#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/devel-api/adaptor-framework/clipboard.h>
#include <dali/devel-api/adaptor-framework/imf-manager.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/layouts/layout-engine.h>
PAN_EVENT,
GRAB_HANDLE_EVENT,
LEFT_SELECTION_HANDLE_EVENT,
- RIGHT_SELECTION_HANDLE_EVENT
+ RIGHT_SELECTION_HANDLE_EVENT,
+ SELECT,
+ SELECT_ALL
};
union Param
{
INACTIVE,
SELECTING,
+ SELECTION_CHANGED,
EDITING,
- EDITING_WITH_POPUP
+ EDITING_WITH_POPUP,
+ GRAB_HANDLE_PANNING,
+ SELECTION_HANDLE_PANNING
};
EventData( DecoratorPtr decorator );
CharacterIndex mPreEditStartPosition; ///< Used to remove the pre-edit text if necessary.
Length mPreEditLength; ///< Used to remove the pre-edit text if necessary.
- bool mIsShowingPlaceholderText : 1; ///< True if the place-holder text is being displayed.
- bool mPreEditFlag : 1; ///< True if the model contains text in pre-edit state.
- 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.
- bool mUpdateLeftSelectionPosition : 1; ///< True if the visual position of the left selection handle must be recalculated.
- bool mUpdateRightSelectionPosition : 1; ///< True if the visual position of the right selection handle must be recalculated.
- bool mScrollAfterUpdateCursorPosition : 1; ///< Whether to scroll after the cursor position is updated.
+ bool mIsShowingPlaceholderText : 1; ///< True if the place-holder text is being displayed.
+ bool mPreEditFlag : 1; ///< True if the model contains text in pre-edit state.
+ 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.
+ bool mUpdateLeftSelectionPosition : 1; ///< True if the visual position of the left selection handle must be recalculated.
+ bool mUpdateRightSelectionPosition : 1; ///< True if the visual position of the right selection handle must be recalculated.
+ bool mScrollAfterUpdatePosition : 1; ///< Whether to scroll after the cursor position is updated.
+ bool mScrollAfterDelete : 1; ///< Whether to scroll after delete characters.
};
struct ModifyEvent
mFontDefaults( NULL ),
mEventData( NULL ),
mFontClient(),
+ mClipboard(),
mView(),
mLayoutEngine(),
mModifyEvents(),
mVisualModel = VisualModel::New();
mFontClient = TextAbstraction::FontClient::Get();
+ mClipboard = Clipboard::Get();
mView.SetVisualModel( mVisualModel );
ClearPreEditFlag();
}
+ bool IsClipboardEmpty()
+ {
+ bool result( mClipboard && mClipboard.NumberOfItems() );
+ return !result; // // If NumberOfItems greater than 0, return false
+ }
+
void UpdateModel( OperationsMask operationsRequired );
/**
void OnHandleEvent( const Event& event );
+ void OnSelectEvent( const Event& event );
+
+ void OnSelectAllEvent();
+
+ void RetrieveSelection( std::string& selectedText, bool deleteAfterRetreival );
+
+ bool CopyStringToClipboard( std::string& source );
+
+ void SendSelectionToClipboard( bool deleteAfterSending );
+
+ void GetTextFromClipboard( unsigned int itemIndex, std::string& retreivedString );
+
+ void RepositionSelectionHandles( CharacterIndex selectionStart, CharacterIndex selectionEnd );
void RepositionSelectionHandles( float visualX, float visualY );
void ChangeState( EventData::State newState );
LineIndex GetClosestLine( float y ) const;
+ void FindSelectionIndices( float visualX, float visualY, CharacterIndex& startIndex, CharacterIndex& endIndex );
+
/**
* @brief Retrieves the cursor's logical position for a given touch point x,y
*
void ClampVerticalScroll( const Vector2& actualSize );
/**
+ * @brief Scrolls the text to make a position visible.
+ *
+ * @pre mEventData must not be NULL. (there is a text-input or selection capabilities).
+ *
+ * @param[in] position A position in decorator coords.
+ *
+ * This method is called after inserting text, moving the cursor with the grab handle or the keypad,
+ * or moving the selection handles.
+ */
+ void ScrollToMakePositionVisible( const Vector2& position );
+
+ /**
* @brief Scrolls the text to make the cursor visible.
*
- * This method is called after inserting, deleting or moving the cursor with the keypad.
+ * This method is called after deleting text.
*/
- void ScrollToMakeCursorVisible();
+ void ScrollTextToMatchCursor();
ControlInterface& mControlInterface; ///< Reference to the text controller.
LogicalModelPtr mLogicalModel; ///< Pointer to the logical model.
FontDefaults* mFontDefaults; ///< Avoid allocating this when the user does not specify a font.
EventData* mEventData; ///< Avoid allocating everything for text input until EnableTextInput().
TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
+ Clipboard mClipboard; ///< Handle to the system clipboard
View mView; ///< The view interface to the rendering back-end.
LayoutEngine mLayoutEngine; ///< The layout engine.
std::vector<ModifyEvent> mModifyEvents; ///< Temporary stores the text set until the next relayout.
const std::string EMPTY_STRING("");
+float ConvertToEven( float value )
+{
+ int intValue(static_cast<int>( value ));
+ return static_cast<float>(intValue % 2 == 0) ? intValue : (intValue + 1);
+}
+
} // namespace
namespace Dali
// Remove the previously set text
ResetText();
+ CharacterIndex lastCursorIndex = 0u;
+
if( !text.empty() )
{
// Convert text into UTF-32
DALI_ASSERT_DEBUG( text.size() >= characterCount && "Invalid UTF32 conversion length" );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", this, text.size(), mImpl->mLogicalModel->mText.Count() );
- // Reset the cursor position
- if( mImpl->mEventData )
- {
- mImpl->mEventData->mPrimaryCursorPosition = characterCount;
- }
+ // To reset the cursor position
+ lastCursorIndex = characterCount;
// Update the rest of the model during size negotiation
mImpl->QueueModifyEvent( ModifyEvent::TEXT_REPLACED );
ShowPlaceholderText();
}
+ // Resets the cursor position.
+ ResetCursorPosition( lastCursorIndex );
+
+ // Scrolls the text to make the cursor visible.
+ ResetScrollPosition();
+
mImpl->RequestRelayout();
if( mImpl->mEventData )
numberOfChars = currentText.Count() - cursorIndex;
}
- if( cursorIndex >= 0 &&
- (cursorIndex + numberOfChars) <= currentText.Count() )
+ if( (cursorIndex + numberOfChars) <= currentText.Count() )
{
Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
Vector<Character>::Iterator last = first + numberOfChars;
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z );
}
+ naturalSize.x = ConvertToEven( naturalSize.x );
+ naturalSize.y = ConvertToEven( naturalSize.y );
+
return naturalSize;
}
if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
{
bool glyphsRemoved( false );
- if( 0u != mImpl->mVisualModel->GetNumberOfGlyphPositions() )
+ if( 0u != mImpl->mVisualModel->mGlyphPositions.Count() )
{
- mImpl->mVisualModel->SetGlyphPositions( NULL, 0u );
+ mImpl->mVisualModel->mGlyphPositions.Clear();
glyphsRemoved = true;
}
// Not worth to relayout if width or height is equal to zero.
mImpl->mLogicalModel->mText.Clear();
ClearModelData();
- // Reset the cursor position
- if( mImpl->mEventData )
- {
- mImpl->mEventData->mPrimaryCursorPosition = 0;
- }
-
// We have cleared everything including the placeholder-text
mImpl->PlaceholderCleared();
mImpl->mOperationsPending = ALL_OPERATIONS;
}
+void Controller::ResetCursorPosition( CharacterIndex cursorIndex )
+{
+ // Reset the cursor position
+ if( NULL != mImpl->mEventData )
+ {
+ mImpl->mEventData->mPrimaryCursorPosition = cursorIndex;
+
+ // Update the cursor if it's in editing mode.
+ if( ( EventData::EDITING == mImpl->mEventData->mState ) ||
+ ( EventData::EDITING_WITH_POPUP == mImpl->mEventData->mState ) )
+ {
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ }
+ }
+}
+
+void Controller::ResetScrollPosition()
+{
+ if( NULL != mImpl->mEventData )
+ {
+ // Reset the scroll position.
+ mImpl->mEventData->mScrollPosition = Vector2::ZERO;
+ mImpl->mEventData->mScrollAfterUpdatePosition = true;
+ }
+}
+
void Controller::TextReplacedEvent()
{
// Reset buffers.
// Queue a cursor reposition event; this must wait until after DoRelayout()
mImpl->mEventData->mUpdateCursorPosition = true;
- mImpl->mEventData->mScrollAfterUpdateCursorPosition = true;
+ mImpl->mEventData->mScrollAfterUpdatePosition = true;
}
void Controller::TextDeletedEvent()
REORDER );
// Queue a cursor reposition event; this must wait until after DoRelayout()
- mImpl->mEventData->mUpdateCursorPosition = true;
- mImpl->mEventData->mScrollAfterUpdateCursorPosition = true;
+ mImpl->mEventData->mScrollAfterDelete = true;
}
bool Controller::DoRelayout( const Size& size,
// after the first time the text has been laid out.
// Fill the vectors again.
- Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
+ Length numberOfGlyphs = mImpl->mVisualModel->mGlyphs.Count();
if( 0u == numberOfGlyphs )
{
if( 0u != bidirectionalInfo.Count() )
{
// Get the lines
- const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines();
+ const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
// Reorder the lines.
Vector<BidirectionalLineInfoRun> lineBidirectionalInfoRuns;
}
} // REORDER
- // TODO: I'm working on a patch that changes the LayoutEngine::Align() method.
- // The layoutParameters is not needed and this call can be moved outside the if().
- // Then there is no need to do the layout again to change the alignment.
- if( ALIGN & operations )
- {
- mImpl->mLayoutEngine.Align( layoutParameters,
- layoutSize,
- lines,
- glyphPositions );
- }
-
// Sets the actual size.
if( UPDATE_ACTUAL_SIZE & operations )
{
layoutSize = mImpl->mVisualModel->GetActualSize();
}
+ if( ALIGN & operations )
+ {
+ // The laid-out lines.
+ Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
+
+ mImpl->mLayoutEngine.Align( layoutSize,
+ lines );
+
+ viewUpdated = true;
+ }
+
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", ( viewUpdated ? "true" : "false" ) );
return viewUpdated;
}
mImpl->mLayoutEngine.SetHorizontalAlignment( alignment );
// Set the flag to redo the alignment operation.
- // TODO : Is not needed re-layout and reorder again but with the current implementation it is.
- // Im working on a different patch to fix an issue with the alignment. When that patch
- // is in, this issue can be fixed.
- const OperationsMask layoutOperations = static_cast<OperationsMask>( LAYOUT |
- UPDATE_ACTUAL_SIZE |
- ALIGN |
- REORDER );
-
- mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | layoutOperations );
+ mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | ALIGN );
mImpl->RequestRelayout();
}
}
else if( Dali::DALI_KEY_BACKSPACE == keyCode )
{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p DALI_KEY_BACKSPACE\n", this );
-
- // IMF manager is no longer handling key-events
- mImpl->ClearPreEditFlag();
-
- // Remove the character before the current cursor position
- bool removed = RemoveText( -1, 1 );
-
- if( removed )
- {
- if( 0u == mImpl->mLogicalModel->mText.Count() )
- {
- ShowPlaceholderText();
- mImpl->mEventData->mUpdateCursorPosition = true;
- }
- else
- {
- mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
- }
-
- textChanged = true;
- }
+ textChanged = BackspaceKeyEvent();
}
else
{
mImpl->ClearPreEditFlag();
InsertText( keyString, COMMIT );
-
textChanged = true;
}
void Controller::InsertText( const std::string& text, Controller::InsertType type )
{
- bool removedPreEdit( false );
+ bool removedPrevious( false );
bool maxLengthReached( false );
DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "Unexpected InsertText" )
Vector<Character> utf32Characters;
Length characterCount( 0u );
- if( ! text.empty() )
+ // Remove the previous IMF pre-edit (predicitive text)
+ if( mImpl->mEventData &&
+ mImpl->mEventData->mPreEditFlag &&
+ 0 != mImpl->mEventData->mPreEditLength )
{
- // The placeholder text is no longer needed
- if( mImpl->IsShowingPlaceholderText() )
- {
- ResetText();
- }
+ CharacterIndex offset = mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition;
+ removedPrevious = RemoveText( -static_cast<int>(offset), mImpl->mEventData->mPreEditLength );
+
+ mImpl->mEventData->mPrimaryCursorPosition = mImpl->mEventData->mPreEditStartPosition;
+ mImpl->mEventData->mPreEditLength = 0;
+ }
+ else
+ {
+ // Remove the previous Selection
+ removedPrevious = RemoveSelectedText();
+ }
+ if( ! text.empty() )
+ {
// Convert text into UTF-32
utf32Characters.Resize( text.size() );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", text.size(), utf32Characters.Count() );
}
- if( 0u != utf32Characters.Count() )
+ if( 0u != utf32Characters.Count() ) // Check if Utf8ToUtf32 conversion succeeded
{
+ // The placeholder text is no longer needed
+ if( mImpl->IsShowingPlaceholderText() )
+ {
+ ResetText();
+ }
+
// Handle the IMF (predicitive text) state changes
if( mImpl->mEventData )
{
- if( mImpl->mEventData->mPreEditFlag &&
- 0 != mImpl->mEventData->mPreEditLength )
- {
- // Remove previous pre-edit text
- CharacterIndex offset = mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition;
- removedPreEdit = RemoveText( -static_cast<int>(offset), mImpl->mEventData->mPreEditLength );
-
- mImpl->mEventData->mPrimaryCursorPosition = mImpl->mEventData->mPreEditStartPosition;
- mImpl->mEventData->mPreEditLength = 0;
- }
-
if( COMMIT == type )
{
// IMF manager is no longer handling key-events
}
}
- const Length numberOfCharactersInModel = mImpl->mLogicalModel->GetNumberOfCharacters();
+ const Length numberOfCharactersInModel = mImpl->mLogicalModel->mText.Count();
// Restrict new text to fit within Maximum characters setting
Length maxSizeOfNewText = std::min ( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition );
}
- if( removedPreEdit ||
- 0 != utf32Characters.Count() )
+ if( 0u == mImpl->mLogicalModel->mText.Count() &&
+ mImpl->IsPlaceholderAvailable() )
+ {
+ // Show place-holder if empty after removing the pre-edit text
+ ShowPlaceholderText();
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ mImpl->ClearPreEditFlag();
+ }
+ else if( removedPrevious ||
+ 0 != utf32Characters.Count() )
{
// Queue an inserted event
mImpl->QueueModifyEvent( ModifyEvent::TEXT_INSERTED );
}
}
+bool Controller::RemoveSelectedText()
+{
+ bool textRemoved( false );
+
+ if ( EventData::SELECTING == mImpl->mEventData->mState ||
+ EventData::SELECTION_CHANGED == mImpl->mEventData->mState )
+ {
+ std::string removedString;
+ mImpl->RetrieveSelection( removedString, true );
+
+ if( !removedString.empty() )
+ {
+ textRemoved = true;
+ mImpl->ChangeState( EventData::EDITING );
+ }
+ }
+
+ return textRemoved;
+}
+
void Controller::TapEvent( unsigned int tapCount, float x, float y )
{
DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected TapEvent" );
if( NULL != mImpl->mEventData )
{
+ const bool isShowingPlaceholderText = mImpl->IsShowingPlaceholderText();
if( 1u == tapCount )
{
bool tapDuringEditMode( EventData::EDITING == mImpl->mEventData->mState );
- if( ! mImpl->IsShowingPlaceholderText() &&
- EventData::EDITING == mImpl->mEventData->mState )
+ if( !isShowingPlaceholderText && tapDuringEditMode )
{
- // Grab handle is not shown until a tap is received whilst EDITING
- if( tapDuringEditMode )
- {
- mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
- }
+ mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, true );
mImpl->mEventData->mDecorator->SetPopupActive( false );
}
mImpl->ChangeState( EventData::EDITING );
+
+ // Handles & cursors must be repositioned after Relayout() i.e. after the Model has been updated
+ if( mImpl->mEventData )
+ {
+ Event event( Event::TAP_EVENT );
+ event.p1.mUint = tapCount;
+ event.p2.mFloat = x;
+ event.p3.mFloat = y;
+ mImpl->mEventData->mEventQueue.push_back( event );
+
+ mImpl->RequestRelayout();
+ }
}
- else if( mImpl->mEventData->mSelectionEnabled &&
+ else if( !isShowingPlaceholderText &&
+ mImpl->mEventData->mSelectionEnabled &&
( 2u == tapCount ) )
{
- mImpl->ChangeState( EventData::SELECTING );
+ SelectEvent( x, y, false );
}
}
- // Handles & cursors must be repositioned after Relayout() i.e. after the Model has been updated
- if( mImpl->mEventData )
- {
- Event event( Event::TAP_EVENT );
- event.p1.mUint = tapCount;
- event.p2.mFloat = x;
- event.p3.mFloat = y;
- mImpl->mEventData->mEventQueue.push_back( event );
-
- mImpl->RequestRelayout();
- }
-
// Reset keyboard as tap event has occurred.
mImpl->ResetImfManager();
}
}
}
-void Controller::HandleEvent( HandleType handleType, HandleState state, float x, float y )
+void Controller::SelectEvent( float x, float y, bool selectAll )
+{
+ if( mImpl->mEventData )
+ {
+ if ( mImpl->mEventData->mState == EventData::SELECTING )
+ {
+ mImpl->ChangeState( EventData::SELECTION_CHANGED );
+ }
+ else
+ {
+ mImpl->ChangeState( EventData::SELECTING );
+ }
+
+ if( selectAll )
+ {
+ Event event( Event::SELECT_ALL );
+ mImpl->mEventData->mEventQueue.push_back( event );
+ }
+ else
+ {
+ Event event( Event::SELECT );
+ event.p2.mFloat = x;
+ event.p3.mFloat = y;
+ mImpl->mEventData->mEventQueue.push_back( event );
+ }
+
+ mImpl->RequestRelayout();
+ }
+}
+
+void Controller::GetTargetSize( Vector2& targetSize )
{
- DALI_ASSERT_DEBUG( mImpl->mEventData && "Controller::HandleEvent. Unexpected HandleEvent" );
+ targetSize = mImpl->mControlSize;
+}
+
+void Controller::AddDecoration( Actor& actor, bool needsClipping )
+{
+ mImpl->mControlInterface.AddDecoration( actor, needsClipping );
+}
+
+void Controller::DecorationEvent( HandleType handleType, HandleState state, float x, float y )
+{
+ DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected DecorationEvent" );
if( mImpl->mEventData )
{
}
}
+void Controller::TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Buttons button )
+{
+ if( NULL == mImpl->mEventData )
+ {
+ return;
+ }
+
+ switch( button )
+ {
+ case Toolkit::TextSelectionPopup::CUT:
+ {
+ mImpl->SendSelectionToClipboard( true ); // Synchronous call to modify text
+ mImpl->mOperationsPending = ALL_OPERATIONS;
+ if( 0u != mImpl->mLogicalModel->mText.Count() ||
+ !mImpl->IsPlaceholderAvailable() )
+ {
+ mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
+ }
+ else
+ {
+ ShowPlaceholderText();
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ }
+ mImpl->RequestRelayout();
+ mImpl->mControlInterface.TextChanged();
+ break;
+ }
+ case Toolkit::TextSelectionPopup::COPY:
+ {
+ mImpl->SendSelectionToClipboard( false ); // Text not modified
+ mImpl->RequestRelayout(); // Handles, Selection Highlight, Popup
+ break;
+ }
+ case Toolkit::TextSelectionPopup::PASTE:
+ {
+ std::string stringToPaste("");
+ mImpl->GetTextFromClipboard( 0, stringToPaste ); // Paste latest item from system clipboard
+ InsertText( stringToPaste, Text::Controller::COMMIT );
+ mImpl->ChangeState( EventData::EDITING );
+ mImpl->RequestRelayout();
+ break;
+ }
+ case Toolkit::TextSelectionPopup::SELECT:
+ {
+ const Vector2& currentCursorPosition = mImpl->mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
+
+ if( mImpl->mEventData->mSelectionEnabled )
+ {
+ // Creates a SELECT event.
+ SelectEvent( currentCursorPosition.x, currentCursorPosition.y, false );
+ }
+ break;
+ }
+ case Toolkit::TextSelectionPopup::SELECT_ALL:
+ {
+ // Creates a SELECT_ALL event
+ SelectEvent( 0.f, 0.f, true );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::CLIPBOARD:
+ {
+ break;
+ }
+ case Toolkit::TextSelectionPopup::NONE:
+ {
+ // Nothing to do.
+ break;
+ }
+ }
+}
+
ImfManager::ImfCallbackData Controller::OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
{
bool update( false );
delete mImpl;
}
+bool Controller::BackspaceKeyEvent()
+{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p DALI_KEY_BACKSPACE\n", this );
+
+ // IMF manager is no longer handling key-events
+ mImpl->ClearPreEditFlag();
+
+ bool removed( false );
+
+ if ( EventData::SELECTING == mImpl->mEventData->mState ||
+ EventData::SELECTION_CHANGED == mImpl->mEventData->mState )
+ {
+ removed = RemoveSelectedText();
+ }
+ else if( mImpl->mEventData->mPrimaryCursorPosition > 0 )
+ {
+ // Remove the character before the current cursor position
+ removed = RemoveText( -1, 1 );
+ }
+
+ if( removed )
+ {
+ if( 0u != mImpl->mLogicalModel->mText.Count() ||
+ !mImpl->IsPlaceholderAvailable() )
+ {
+ mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
+ }
+ else
+ {
+ ShowPlaceholderText();
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ }
+ }
+
+ return removed;
+}
+
void Controller::ShowPlaceholderText()
{
if( mImpl->IsPlaceholderAvailable() )
#include <dali/public-api/object/ref-object.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/font-run.h>
#include <dali-toolkit/internal/text/layouts/layout-engine.h>
* It provides a view of the text that can be used by rendering back-ends.
*
* For selectable/editable UI controls, the controller handles input events from the UI control
- * and decorations (grab handles etc) via an observer interface.
+ * and decorations (grab handles etc) via the Decorator::ControllerInterface interface.
+ *
+ * The text selection popup button callbacks are as well handled via the TextSelectionPopupCallbackInterface interface.
*/
-class Controller : public RefObject, public Decorator::Observer
+class Controller : public RefObject, public Decorator::ControllerInterface, public TextSelectionPopupCallbackInterface
{
public:
void GetText( std::string& text ) const;
/**
- * @brief Replaces any placeholder text previously set.
+ * @brief Remove a given number of characters
*
* @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
* @param[in] numberOfChars The number of characters to delete from the cursorOffset.
void ResetText();
/**
+ * @brief Used to reset the cursor position after setting a new text.
+ *
+ * @param[in] cursorIndex Where to place the cursor.
+ */
+ void ResetCursorPosition( CharacterIndex cursorIndex );
+
+ /**
+ * @brief Used to reset the scroll position after setting a new text.
+ */
+ void ResetScrollPosition();
+
+ /**
* @brief Used to process an event queued from SetText()
*/
void TextReplacedEvent();
// Text-input Event Queuing
/**
- * @brief Caller by editable UI controls when keyboard focus is gained.
+ * @brief Called by editable UI controls when keyboard focus is gained.
*/
void KeyboardFocusGainEvent();
/**
- * @brief Caller by editable UI controls when focus is lost.
+ * @brief Called by editable UI controls when focus is lost.
*/
void KeyboardFocusLostEvent();
/**
- * @brief Caller by editable UI controls when key events are received.
+ * @brief Called by editable UI controls when key events are received.
*
* @param[in] event The key event.
* @param[in] type Used to distinguish between regular key events and IMF events.
bool KeyEvent( const Dali::KeyEvent& event );
/**
- * @brief Caller by editable UI controls when key events are received.
+ * @brief Called by editable UI controls when key events are received.
*
* @param[in] text The text to insert.
* @param[in] type Used to distinguish between regular key events and IMF events.
void InsertText( const std::string& text, InsertType type );
/**
- * @brief Caller by editable UI controls when a tap gesture occurs.
+ * @brief Checks if text is selected and if so removes it.
+ * @return true if text was removed
+ */
+ bool RemoveSelectedText();
+
+ /**
+ * @brief Called 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.
+ * @brief Called 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::HandleEvent()
+ * @brief Creates a selection event.
+ *
+ * It could be called from the TapEvent (double tap) or when the text selection popup's sellect all button is pressed.
+ *
+ * @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] selectAll Whether the whole text is selected.
*/
- virtual void HandleEvent( HandleType handle, HandleState state, float x, float y );
+ void SelectEvent( float x, float y, bool selectAll );
/**
* @brief Event received from IMF manager
*/
ImfManager::ImfCallbackData OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent );
+ /**
+ * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::GetTargetSize()
+ */
+ virtual void GetTargetSize( Vector2& targetSize );
+
+ /**
+ * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::AddDecoration()
+ */
+ virtual void AddDecoration( Actor& actor, bool needsClipping );
+
+ /**
+ * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::DecorationEvent()
+ */
+ virtual void DecorationEvent( HandleType handle, HandleState state, float x, float y );
+
+ /**
+ * @copydoc Dali::Toolkit::TextSelectionPopup::TextPopupButtonCallbackInterface::TextPopupButtonTouched()
+ */
+ virtual void TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Buttons button );
+
protected:
/**
private:
/**
+ * @brief Helper to KeyEvent() to handle the backspace case.
+ *
+ * @return True if a character was deleted.
+ */
+ bool BackspaceKeyEvent();
+
+ /**
* @brief Helper to clear font-specific data.
*/
void ShowPlaceholderText();
// If ellipsis is enabled, the number of glyphs the layout engine has laid out may be less than 'numberOfGlyphs'.
// Check the last laid out line to know if the layout engine elided some text.
- const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines();
+ const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
if( numberOfLines > 0u )
{
const LineRun& lastLine = *( mImpl->mVisualModel->mLines.Begin() + ( numberOfLines - 1u ) );
glyphIndex,
numberOfLaidOutGlyphs );
+ // Get the lines for the given range of glyphs.
+ // The lines contain the alignment offset which needs to be added to the glyph's position.
+ LineIndex firstLine = 0u;
+ Length numberOfLines = 0u;
+ mImpl->mVisualModel->GetNumberOfLines( glyphIndex,
+ numberOfLaidOutGlyphs,
+ firstLine,
+ numberOfLines );
+
+ Vector<LineRun> lines;
+ lines.Resize( numberOfLines );
+ LineRun* lineBuffer = lines.Begin();
+
+ mImpl->mVisualModel->GetLinesOfGlyphRange( lineBuffer,
+ glyphIndex,
+ numberOfLaidOutGlyphs );
+
+ // Get the first line for the given glyph range.
+ LineIndex lineIndex = firstLine;
+ LineRun* line = lineBuffer + lineIndex;
+
+ // Index of the last glyph of the line.
+ GlyphIndex lastGlyphIndexOfLine = line->glyphIndex + line->numberOfGlyphs - 1u;
+
+ // Add the alignment offset to the glyph's position.
+ for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index )
+ {
+ ( *( glyphPositions + index ) ).x += line->alignmentOffset;
+
+ if( lastGlyphIndexOfLine == index )
+ {
+ // Get the next line.
+ ++lineIndex;
+
+ if( lineIndex < numberOfLines )
+ {
+ line = lineBuffer + lineIndex;
+ lastGlyphIndexOfLine = line->glyphIndex + line->numberOfGlyphs - 1u;
+ }
+ }
+ }
+
if( 1u == numberOfLaidOutGlyphs )
{
// not a point try to do ellipsis with only one laid out character.
{
const GlyphInfo& glyphToRemove = *( glyphs + index );
- // Need to reshape the glyph as the font may be different in size.
- const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph( mImpl->mFontClient.GetPointSize( glyphToRemove.fontId ) );
-
- if( !firstPenSet )
+ if( 0u != glyphToRemove.fontId )
{
- const Vector2& position = *( glyphPositions + index );
+ // i.e. The font id of the glyph shaped from the '\n' character is zero.
- // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
- penY = position.y + glyphToRemove.yBearing;
+ // Need to reshape the glyph as the font may be different in size.
+ const GlyphInfo& ellipsisGlyph = mImpl->mFontClient.GetEllipsisGlyph( mImpl->mFontClient.GetPointSize( glyphToRemove.fontId ) );
- // Calculates the first penX which will be used if rtl text is elided.
- firstPenX = position.x - glyphToRemove.xBearing;
- if( firstPenX < -ellipsisGlyph.xBearing )
+ if( !firstPenSet )
{
- // Avoids to exceed the bounding box when rtl text is elided.
- firstPenX = -ellipsisGlyph.xBearing;
- }
+ const Vector2& position = *( glyphPositions + index );
- removedGlypsWidth = -ellipsisGlyph.xBearing;
+ // Calculates the penY of the current line. It will be used to position the ellipsis glyph.
+ penY = position.y + glyphToRemove.yBearing;
- firstPenSet = true;
- }
+ // Calculates the first penX which will be used if rtl text is elided.
+ firstPenX = position.x - glyphToRemove.xBearing;
+ if( firstPenX < -ellipsisGlyph.xBearing )
+ {
+ // Avoids to exceed the bounding box when rtl text is elided.
+ firstPenX = -ellipsisGlyph.xBearing;
+ }
- removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) );
+ removedGlypsWidth = -ellipsisGlyph.xBearing;
- // Calculate the width of the ellipsis glyph and check if it fits.
- const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
- if( ellipsisGlyphWidth < removedGlypsWidth )
- {
- GlyphInfo& glyphInfo = *( glyphs + index );
- Vector2& position = *( glyphPositions + index );
- position.x -= glyphInfo.xBearing;
-
- // Replace the glyph by the ellipsis glyph.
- glyphInfo = ellipsisGlyph;
+ firstPenSet = true;
+ }
- // Change the 'x' and 'y' position of the ellipsis glyph.
+ removedGlypsWidth += std::min( glyphToRemove.advance, ( glyphToRemove.xBearing + glyphToRemove.width ) );
- if( position.x > firstPenX )
+ // Calculate the width of the ellipsis glyph and check if it fits.
+ const float ellipsisGlyphWidth = ellipsisGlyph.width + ellipsisGlyph.xBearing;
+ if( ellipsisGlyphWidth < removedGlypsWidth )
{
- position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
- }
+ GlyphInfo& glyphInfo = *( glyphs + index );
+ Vector2& position = *( glyphPositions + index );
+ position.x -= ( 0.f > glyphInfo.xBearing ) ? glyphInfo.xBearing : 0.f;
- position.x += ellipsisGlyph.xBearing;
- position.y = penY - ellipsisGlyph.yBearing;
+ // Replace the glyph by the ellipsis glyph.
+ glyphInfo = ellipsisGlyph;
- inserted = true;
+ // Change the 'x' and 'y' position of the ellipsis glyph.
+
+ if( position.x > firstPenX )
+ {
+ position.x = firstPenX + removedGlypsWidth - ellipsisGlyphWidth;
+ }
+
+ position.x += ellipsisGlyph.xBearing;
+ position.y = penY - ellipsisGlyph.yBearing;
+
+ inserted = true;
+ }
}
- else
+
+ if( !inserted )
{
if( index > 0u )
{
{
VisualModel& model = *mImpl->mVisualModel;
- Length glyphCount = model.GetNumberOfGlyphs();
- Length positionCount = model.GetNumberOfGlyphPositions();
+ const Length glyphCount = model.mGlyphs.Count();
+ const Length positionCount = model.mGlyphPositions.Count();
DALI_ASSERT_DEBUG( positionCount <= glyphCount && "Invalid glyph positions in Model" );
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.
}
}
-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,
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.
return index;
}
-void VisualModel::ReplaceLines( GlyphIndex glyphIndex,
- Length numberOfGlyphsToRemove,
- const LineRun* const lines,
- Length numberOfGlyphsToInsert )
-{
-}
-
void VisualModel::SetNaturalSize( const Vector2& size )
{
mNaturalSize = size;
// 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.
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.
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.
// 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.
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.
Length numberOfGlyphs,
LineIndex& firstLine,
Length& numberOfLines ) const;
+
/**
* @brief Retrieves the lines where the given range of glyphs is laid out.
*
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.
*/
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
/**
case Toolkit::Control::Property::BACKGROUND_IMAGE:
{
- if ( value.HasKey( "image" ) )
+ Image image = Scripting::NewImage( value );
+ if ( image )
{
- Property::Map imageMap = value.GetValue( "image" ).Get< Property::Map >();
- Image image = Scripting::NewImage( imageMap );
-
- if ( image )
- {
- controlImpl.SetBackgroundImage( image );
- }
+ controlImpl.SetBackgroundImage( image );
}
- else if ( value.Get< Property::Map >().Empty() )
+ else
{
// An empty map means the background is no longer required
controlImpl.ClearBackground();
Image image = back->actor.GetRendererAt(0).GetMaterial().GetSamplerAt(0).GetImage();
if ( image )
{
- Property::Map imageMap;
- Scripting::CreatePropertyMap( image, imageMap );
- map[ "image" ] = imageMap;
+ Scripting::CreatePropertyMap( image, map );
}
}
void Control::Initialize()
{
+ // Call deriving classes so initialised before styling is applied to them.
+ OnInitialize();
+
if( mImpl->mFlags & REQUIRES_STYLE_CHANGE_SIGNALS )
{
Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
// Register for style changes
styleManager.StyleChangeSignal().Connect( this, &Control::OnStyleChange );
- // SetTheme
+ // Apply the current style
GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) );
}
{
SetKeyboardNavigationSupport( true );
}
-
- // Calling deriving classes
- OnInitialize();
}
void Control::OnInitialize()
* @param handle
* @return implementation
*/
-Internal::Control& GetImplementation( Dali::Toolkit::Control& handle );
+DALI_IMPORT_API Internal::Control& GetImplementation( Dali::Toolkit::Control& handle );
/**
* @brief Get implementation from the handle
* @param handle
* @return implementation
*/
-const Internal::Control& GetImplementation( const Dali::Toolkit::Control& handle );
+DALI_IMPORT_API const Internal::Control& GetImplementation( const Dali::Toolkit::Control& handle );
} // namespace Internal
// Create the image
PixelBuffer* pixbuf = imageData.GetBuffer();
+ if( !pixbuf )
+ {
+ return image;
+ }
+
Vector4 outerColor = color;
if ( border )
{
{
enum
{
- SCROLL_DIRECTION = PROPERTY_START_INDEX, ///< name "scroll-direction", @see SetScrollDirection(), type std::string
- INDICATOR_HEIGHT_POLICY, ///< name "indicator-height-policy", @see SetIndicatorHeightPolicy(), type std::string
- INDICATOR_FIXED_HEIGHT, ///< name "indicator-fixed-height", @see SetIndicatorFixedHeight(), type float
- INDICATOR_SHOW_DURATION, ///< name "indicator-show-duration", @see SetIndicatorShowDuration(), type float
- INDICATOR_HIDE_DURATION, ///< name "indicator-hide-duration", @see SetIndicatorHideDuration(), type float
- SCROLL_POSITION_INTERVALS ///< name "scroll-position-intervals", type float
+ SCROLL_DIRECTION = PROPERTY_START_INDEX, ///< name "scroll-direction", @see SetScrollDirection(), type std::string
+ INDICATOR_HEIGHT_POLICY, ///< name "indicator-height-policy", @see SetIndicatorHeightPolicy(), type std::string
+ INDICATOR_FIXED_HEIGHT, ///< name "indicator-fixed-height", @see SetIndicatorFixedHeight(), type float
+ INDICATOR_SHOW_DURATION, ///< name "indicator-show-duration", @see SetIndicatorShowDuration(), type float
+ INDICATOR_HIDE_DURATION, ///< name "indicator-hide-duration", @see SetIndicatorHideDuration(), type float
+ SCROLL_POSITION_INTERVALS ///< name "scroll-position-intervals",@see SetScrollPositionIntervals() type Property::Array
};
};
GetImpl(*this).GetItemsRange(range);
}
+ItemView::LayoutActivatedSignalType& ItemView::LayoutActivatedSignal()
+{
+ return GetImpl(*this).LayoutActivatedSignal();
+}
+
} // namespace Toolkit
} // namespace Dali
*
* Multiple ItemLayouts may be provided, to determine the logical position of each item a layout.
* Actors are provided from an external ItemFactory, to display the currently visible items.
+ *
+ * Signals
+ * | %Signal Name | Method |
+ * |----------------------------------|--------------------------------------------|
+ * | layout-activated | @ref LayoutActivatedSignal() |
*/
+
class DALI_IMPORT_API ItemView : public Scrollable
{
public:
};
};
+ // Signals
+
+ typedef Signal< void () > LayoutActivatedSignalType;
+
public:
/**
*/
void GetItemsRange(ItemRange& range);
+public: // Signals
+
+ /**
+ * @brief Signal emitted when layout activation is finished.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void YourCallbackName();
+ * @endcode
+ * @pre The Object has been initialized.
+ * @return The signal to connect to.
+ */
+ ItemView::LayoutActivatedSignalType& LayoutActivatedSignal();
+
public: // Not intended for application developers
/**
namespace Toolkit
{
-const std::string TableView::CELL_INDICES_PROPERTY_NAME("cell-indices");
-const std::string TableView::ROW_SPAN_PROPERTY_NAME("row-span");
-const std::string TableView::COLUMN_SPAN_PROPERTY_NAME("column-span");
-
TableView::TableView()
{
}
void TableView::SetFitHeight( unsigned int rowIndex )
{
- GetImpl(*this).SetRowPolicy( rowIndex, Internal::TableView::FIT );
+ GetImpl(*this).SetFitHeight( rowIndex );
}
bool TableView::IsFitHeight( unsigned int rowIndex ) const
{
- return ( GetImpl(*this).GetRowPolicy( rowIndex ) == Internal::TableView::FIT );
+ return GetImpl(*this).IsFitHeight( rowIndex );
}
void TableView::SetFitWidth( unsigned int columnIndex )
{
- GetImpl(*this).SetColumnPolicy( columnIndex, Internal::TableView::FIT );
+ GetImpl(*this).SetFitWidth( columnIndex );
}
bool TableView::IsFitWidth( unsigned int columnIndex ) const
{
- return ( GetImpl(*this).GetColumnPolicy( columnIndex ) == Internal::TableView::FIT );
+ return GetImpl(*this).IsFitWidth( columnIndex );
}
void TableView::SetFixedHeight( unsigned int rowIndex, float height )
* TableView constrains the x and y position and width and height of the child actors.
* z position and depth are left intact so that 3D model actors can also be laid out
* in a grid without loosing their depth scaling.
+ *
+ * @nosubgrouping
+ *
+ * Per-child Custom properties for script supporting.
+ *
+ * When an actor is add to the tableView through Actor::Add() instead of TableView::AddChild,
+ * the following custom properties of the actor are checked to decide the actor position inside the table
+ *
+ * These properties are registered dynamically to the child and is non-animatable.
+ *
+ * | %Property Name | Type |
+ * |---------------------------|--------------------|
+ * | cell-index | Vector2 |
+ * | row-span | float | // type float (Currently builder is unable to differentiate integer and float from Json string)
+ * | column-span | float | // type float (Currently builder is unable to differentiate integer and float from Json string)
+ * | cell-horizontal-alignment | string | // available values: left, center, right
+ * | cell-vertical-alignment | string | // available values: top, center, bottom
+ *
+ * @code
+ * "name":"gallery-1",
+ * "type":"ImageActor",
+ * "image": {
+ * "filename": "{DALI_IMAGE_DIR}gallery-small-1.jpg"
+ * },
+ * "custom-properties": {
+ * "cell-index":[1,1], // property to specify the top-left cell this child occupies, if not set, the first available cell is used
+ * "row-span":3, // property to specify how many rows this child occupies, if not set, default value is 1
+ * "column-span": 2, // property to specify how many columns this child occupies, if nor set, default value is 1
+ * "cell-horizontal-alignment": "left", // property to specify how to align horizontally inside the cells, if not set, default value is 'left'
+ * "cell-vertical-alignment": "center" // property to specify how to align vertically inside the cells, if not set, default value is 'top'
+ * }
+ * @endcode
*/
class DALI_IMPORT_API TableView : public Control
{
* "layout-rows":
{
"0": { "policy": "fixed", "value": 40 }, //@see SetFixedHight
- "2": { "policy": "relative", "value": 0.33 } //@see SetRelativeHeight
+ "2": { "policy": "relative", "value": 0.33 }, //@see SetRelativeHeight
+ "3": { "policy": "fit", "value":0.0 } //@see SetFitHeight, the value is not used, its height is decided by the children in this row
}
* @endcode
*
* "layout-columns":
{
"0": { "policy": "fixed", "value": 40 }, //@see SetFixedWidth
+ "1": { "policy": "fit", "value":0.0 } //@see SetFitHeight, the value is not used, its width is decided by the children in this column
"2": { "policy": "relative", "value": 0.33 } //@see SetRelativeWidth
}
* @endcode
};
};
- // Custom properties for where to put the actor, these properties should be registered to the child which would be added to the table
- static const std::string CELL_INDICES_PROPERTY_NAME; ///< Property, name "cell-indices", type Vector2
- static const std::string ROW_SPAN_PROPERTY_NAME; ///< Property, name "row-span", type float (Currently builder is unable to differentiate integer and float from Json string)
- static const std::string COLUMN_SPAN_PROPERTY_NAME; ///< Property, name "column-span", type float (Currently builder is unable to differentiate integer and float from Json string)
-
/**
* @brief Describes how the size of a row / column been set
*/
{
FIXED, ///< Fixed with the given value.
RELATIVE, ///< Calculated as percentage of the remainder after subtracting Padding and Fixed height/width
- FILL ///< Get the remainder of the 100% (after subtracting Padding, Fixed and Relative height/ width) divided evenly between 'fill' rows/columns
+ FILL, ///< Default policy, get the remainder of the 100% (after subtracting Padding, Fixed and Relative height/ width) divided evenly between 'fill' rows/columns
+ FIT ///< Fit around its children.
};
/**
unsigned int GetColumns();
/**
- * @brief Set the alignment on a cell
+ * @brief Set the alignment on a cell.
+ *
+ * Cells without calling this function have the default values of LEFT and TOP respectively.
*
- * @param[in] position The cell to set alignment on
- * @param[in] horizontal The horizontal alignment
- * @param[in] vertical The vertical alignment
+ * @param[in] position The cell to set alignment on.
+ * @param[in] horizontal The horizontal alignment.
+ * @param[in] vertical The vertical alignment.
*/
void SetCellAlignment( CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical );
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 43;
+const unsigned int TOOLKIT_MICRO_VERSION = 46;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
"font-style":"Regular",
"point-size":18
},
+ "textselectionpopup":
+ {
+ "popup-max-size":[400,100],
+ "popup-min-size":[100,65],
+ "background-color":[0.0,0.0,0.0,1.0]
+ },
"textfield":
{
"font-family":"HelveticaNeue",
{
"point-size":10
},
-
+ "textselectionpopup":
+ {
+ "popup-max-size":[400,100],
+ "popup-min-size":[100,65],
+ "background-color":[0.0,0.0,0.0,1.0]
+ },
"scrollview":
{
"overshoot-effect-color":"B018"
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.0.43
+Version: 1.0.46
Release: 1
Group: System/Libraries
License: Apache-2.0
break;
}
case Dali::Property::NONE:
- case Dali::Property::TYPE_COUNT:
default:
{
break;