From: Adeel Kazmi Date: Thu, 25 Jun 2015 15:30:15 +0000 (-0700) Subject: Merge "Add support for new accessibility actions" into devel/master X-Git-Tag: dali_1.0.47~19 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=a3353d4f3763da656966e8e9a1c223c7e9585a13;hp=94517504b052e71c97105d13625d7f2ce5933889 Merge "Add support for new accessibility actions" into devel/master --- diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 53f4806..a3a263f 100644 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -10,6 +10,7 @@ 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) diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp new file mode 100644 index 0000000..4b89f25 --- /dev/null +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-MultiLanguage.cpp @@ -0,0 +1,248 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include + + +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& text, const Vector& lineBreakInfo, Vector& scripts ); +// void MultilanguageSupport::ValidateFonts( const Vector& text, const Vector& scripts, Vector& fonts ); + +////////////////////////////////////////////////////////// + +namespace +{ + +struct ScriptsData +{ + std::string description; ///< Description of the experiment. + std::string text; ///< Input text. + Vector 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 utf32; + utf32.Resize( data.text.size() ); + + const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), + data.text.size(), + &utf32[0u] ); + utf32.Resize( numberOfCharacters ); + + // 2) Set the line break info. + Vector lineBreakInfo; + lineBreakInfo.Resize( numberOfCharacters ); + + SetLineBreakInfo( utf32, lineBreakInfo ); + + // 3) Set the script info. + Vector 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 utf32; + utf32.Resize( data.text.size() ); + + const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast( data.text.c_str() ), + data.text.size(), + &utf32[0u] ); + utf32.Resize( numberOfCharacters ); + + // 2) Set the line break info. + Vector lineBreakInfo; + lineBreakInfo.Resize( numberOfCharacters ); + + SetLineBreakInfo( utf32, lineBreakInfo ); + + // 3) Set the script info. + Vector scripts; + multilanguageSupport.SetScripts( utf32, + lineBreakInfo, + scripts ); + + Vector 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 scriptRuns00; + + // Hello world. + Vector 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; +} diff --git a/automated-tests/src/dali-toolkit/CMakeLists.txt b/automated-tests/src/dali-toolkit/CMakeLists.txt index aeb79d4..d150b93 100644 --- a/automated-tests/src/dali-toolkit/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit/CMakeLists.txt @@ -49,6 +49,7 @@ SET(TC_SOURCES utc-Dali-ItemLayout.cpp utc-Dali-ItemView.cpp utc-Dali-KeyboardFocusManager.cpp + utc-Dali-Magnifier.cpp utc-Dali-MaskEffect.cpp utc-Dali-NinePatchMaskEffect.cpp utc-Dali-Popup.cpp diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp index 6d8ddff..164ab9e 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp @@ -115,6 +115,10 @@ int UtcDaliBuilderAnimationP(void) // JSON with a quit event when the actor is touched std::string json( "{" + " \"constants\":" + " {" + " \"ALPHA_FUNCTION\":\"EASE_IN_OUT\"" + " }," " \"paths\":" " {" " \"path0\":" @@ -133,7 +137,7 @@ int UtcDaliBuilderAnimationP(void) " \"actor\": \"greeting\"," " \"property\": \"position\"," " \"value\": [300, 300, -1000]," - " \"alpha-function\": \"EASE_IN_OUT\"," + " \"alpha-function\": \"{ALPHA_FUNCTION}\"," " \"relative\": true," " \"time-period\": {" " \"delay\": 0," @@ -248,6 +252,12 @@ int UtcDaliBuilderAnimationP(void) 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 ); @@ -273,6 +283,11 @@ int UtcDaliBuilderAnimationN(void) // JSON with a quit event when the actor is touched std::string json( "{" + " \"constants\":" + " {" + " \"TEXT\": \"Touch Me\"," + " \"NAME\": \"greeting\" " + " }," " \"paths\":" " {" " \"path0\":" @@ -288,7 +303,7 @@ int UtcDaliBuilderAnimationN(void) " \"disconnect-action\": \"BAKE\"," " \"properties\":" " [{" - " \"actor\": \"greeting\"," + " \"actor\": \"{NAME}\"," " \"property\": \"positioninvalid\"," " \"value\": [300, 300, -1000]," " \"alpha-function\": \"EASE_IN_OUT\"," @@ -306,7 +321,7 @@ int UtcDaliBuilderAnimationN(void) " \"disconnect-action\": \"BAKE\"," " \"properties\":" " [{" - " \"actor\": \"greeting\"," + " \"actor\": \"{NAME}\"," " \"property\": \"positioninvalid\"," " \"value\": [300, 300, -1000]," " \"alpha-function\": \"EGGS_OVER_EASY\"," @@ -347,6 +362,11 @@ int UtcDaliBuilderAnimationN(void) " \"action\": \"play\"," " \"animation\": \"animate\"" " }]" + " }," + " {" + " \"name\": \"greeting2\"," + " \"type\": \"TextLabel\"," + " \"text\": \"Touch me\"" " }]" "}"); @@ -359,12 +379,28 @@ int UtcDaliBuilderAnimationN(void) // 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); - DALI_TEST_CHECK(true); END_TEST; @@ -387,6 +423,7 @@ int UtcDaliBuilderConstantsP(void) "\"stage\":" "[{" " \"type\": \"ImageActor\"," + " \"name\": \"{NAME}\"," " \"size\": [100,100,1]," " \"parent-origin\": \"TOP_LEFT\"," " \"anchor-point\": \"{ANCHOR}\"," @@ -403,9 +440,29 @@ int UtcDaliBuilderConstantsP(void) 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; } @@ -416,6 +473,10 @@ int UtcDaliBuilderTemplatesAndStylesP(void) // 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" @@ -434,7 +495,7 @@ int UtcDaliBuilderTemplatesAndStylesP(void) " \"type\": \"ImageActor\",\n" " \"styles\": [\"image-style\"],\n" " \"name\": \"image\",\n" - " \"size\": [100,100,1],\n" + " \"size\": \"{SIZE}\",\n" " \"signals\": [{\n" " \"name\": \"touched\",\n" " \"action\": \"quit\"\n" @@ -446,19 +507,67 @@ int UtcDaliBuilderTemplatesAndStylesP(void) " }\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; } @@ -732,3 +841,617 @@ int UtcDaliBuilderPropertyNotificationP(void) 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() == 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; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Magnifier.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Magnifier.cpp new file mode 100644 index 0000000..1d6ba1b --- /dev/null +++ b/automated-tests/src/dali-toolkit/utc-Dali-Magnifier.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp index 6254e7a..9c1e054 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TableView.cpp @@ -693,13 +693,14 @@ int UtcDaliTableViewCustomProperties(void) // Create a 10x10 table-view TableView tableView = TableView::New(10,10); - Constraint constraint = Constraint::New( 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); @@ -708,9 +709,9 @@ int UtcDaliTableViewCustomProperties(void) 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 #include #include +#include +#include #include #include #include @@ -38,22 +40,49 @@ void dali_textfield_cleanup(void) 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; @@ -72,6 +101,38 @@ static void TestMaxLengthReachedCallback( TextField control ) 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) @@ -165,21 +226,36 @@ 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; } @@ -191,48 +267,123 @@ int UtcDaliTextFieldSetPropertyP(void) 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( TextField::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::TEXT ), std::string(""), TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::PLACEHOLDER_TEXT ), std::string(""), TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::PLACEHOLDER_TEXT_FOCUSED ), std::string(""), TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::FONT_FAMILY ), std::string(""), TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::FONT_STYLE ), std::string(""), TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::POINT_SIZE ), 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::MAX_LENGTH ), 50u, TEST_LOCATION ); DALI_TEST_EQUALS( field.GetProperty( TextField::Property::EXCEED_POLICY ), TextField::EXCEED_POLICY_CLIP, TEST_LOCATION ); - - // Check cursor properties - field.SetProperty( TextField::Property::ENABLE_CURSOR_BLINK, true ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::PLACEHOLDER_TEXT_COLOR ), PLACEHOLDER_TEXT_COLOR, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::BLACK, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLACK, TEST_LOCATION ); DALI_TEST_EQUALS( field.GetProperty( TextField::Property::ENABLE_CURSOR_BLINK ), true, TEST_LOCATION ); - field.SetProperty( TextField::Property::PRIMARY_CURSOR_COLOR, Color::RED ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::RED, TEST_LOCATION ); - field.SetProperty( TextField::Property::SECONDARY_CURSOR_COLOR, Color::BLUE ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLUE, TEST_LOCATION ); - field.SetProperty( TextField::Property::CURSOR_BLINK_DURATION, 10.0f ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::CURSOR_BLINK_DURATION ), 10.0f, TEST_LOCATION ); - - // Blink interval - field.SetProperty( TextField::Property::CURSOR_BLINK_INTERVAL, 1.0f ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::CURSOR_BLINK_INTERVAL ), 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::CURSOR_BLINK_INTERVAL ), CURSOR_BLINK_INTERVAL * TO_SECONDS, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::CURSOR_BLINK_DURATION ), 0.f, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SCROLL_THRESHOLD ), SCROLL_THRESHOLD, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SCROLL_SPEED ), SCROLL_SPEED, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SELECTION_HIGHLIGHT_COLOR ), LIGHT_BLUE, TEST_LOCATION ); - // Decoration bounding box - field.SetProperty( TextField::Property::DECORATION_BOUNDING_BOX, Rect( 0, 0, 1, 1 ) ); - DALI_TEST_EQUALS( field.GetProperty >( TextField::Property::DECORATION_BOUNDING_BOX ), Rect( 0, 0, 1, 1 ), TEST_LOCATION ); - - // Check that the Alignment properties can be correctly set - field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "BEGIN" ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION ); - field.SetProperty( TextField::Property::VERTICAL_ALIGNMENT, "CENTER" ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::VERTICAL_ALIGNMENT ), "CENTER", TEST_LOCATION ); + // Check the render backend property. + field.SetProperty( TextField::Property::RENDERING_BACKEND, Text::RENDERING_BASIC ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::RENDERING_BACKEND ), Text::RENDERING_BASIC, TEST_LOCATION ); - // Set text + // Check text property. field.SetProperty( TextField::Property::TEXT, "Setting Text" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::TEXT ), std::string("Setting Text"), TEST_LOCATION ); - // Set placeholder text (currently not implemented) - field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "Setting Text" ); + // Check placeholder text properties. + field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "Setting Placeholder Text" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::PLACEHOLDER_TEXT ), std::string("Setting Placeholder Text"), TEST_LOCATION ); - // Set Grab Handle image - field.SetProperty( TextField::Property::GRAB_HANDLE_IMAGE, "" ); + field.SetProperty( TextField::Property::PLACEHOLDER_TEXT_FOCUSED, "Setting Placeholder Text Focused" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::PLACEHOLDER_TEXT_FOCUSED ), std::string("Setting Placeholder Text Focused"), TEST_LOCATION ); + + // Check font properties. + field.SetProperty( TextField::Property::FONT_FAMILY, "Setting font family" ); + DALI_TEST_EQUALS( field.GetProperty( 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( TextField::Property::FONT_STYLE ), std::string("Setting font style"), TEST_LOCATION ); + field.SetProperty( TextField::Property::POINT_SIZE, 10.f ); + DALI_TEST_EQUALS( field.GetProperty( 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( TextField::Property::MAX_LENGTH ), maxNumberOfCharacters, TEST_LOCATION ); + // Check exceed policy + // Set a different exceed policy is not implemented. + + // Check that the Alignment properties can be correctly set + field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "END" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::HORIZONTAL_ALIGNMENT ), "END", TEST_LOCATION ); + field.SetProperty( TextField::Property::VERTICAL_ALIGNMENT, "CENTER" ); + DALI_TEST_EQUALS( field.GetProperty( 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( 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( 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( TextField::Property::SHADOW_OFFSET ), Vector2( 1.f, 1.f ), TEST_LOCATION ); + field.SetProperty( TextField::Property::SHADOW_COLOR, Color::GREEN ); + DALI_TEST_EQUALS( field.GetProperty( 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( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::RED, TEST_LOCATION ); + field.SetProperty( TextField::Property::SECONDARY_CURSOR_COLOR, Color::BLUE ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLUE, TEST_LOCATION ); + + field.SetProperty( TextField::Property::ENABLE_CURSOR_BLINK, false ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::ENABLE_CURSOR_BLINK ), false, TEST_LOCATION ); + field.SetProperty( TextField::Property::CURSOR_BLINK_INTERVAL, 1.f ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::CURSOR_BLINK_INTERVAL ), 1.f, TEST_LOCATION ); + field.SetProperty( TextField::Property::CURSOR_BLINK_DURATION, 10.f ); + DALI_TEST_EQUALS( field.GetProperty( 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( 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( 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( TextField::Property::GRAB_HANDLE_IMAGE ), "image1", TEST_LOCATION ); + field.SetProperty( TextField::Property::GRAB_HANDLE_PRESSED_IMAGE, "image2" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::GRAB_HANDLE_PRESSED_IMAGE ), "image2", TEST_LOCATION ); + field.SetProperty( TextField::Property::SELECTION_HANDLE_IMAGE_LEFT, "image3" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SELECTION_HANDLE_IMAGE_LEFT ), "image3", TEST_LOCATION ); + field.SetProperty( TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT, "image4" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT ), "image4", TEST_LOCATION ); + field.SetProperty( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT, "image5" ); + DALI_TEST_EQUALS( field.GetProperty( 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( 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( TextField::Property::SELECTION_HIGHLIGHT_COLOR ), Color::GREEN, TEST_LOCATION ); + + // Decoration bounding box + field.SetProperty( TextField::Property::DECORATION_BOUNDING_BOX, Rect( 0, 0, 1, 1 ) ); + DALI_TEST_EQUALS( field.GetProperty >( TextField::Property::DECORATION_BOUNDING_BOX ), Rect( 0, 0, 1, 1 ), TEST_LOCATION ); + END_TEST; } @@ -246,6 +397,10 @@ int utcDaliTextFieldBasicRenderP(void) 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 @@ -271,6 +426,11 @@ int utcDaliTextFieldAtlasRenderP(void) 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 @@ -293,7 +453,7 @@ int utcDaliTextFieldTextChangedP(void) TextField field = TextField::New(); DALI_TEST_CHECK( field ); - Stage::GetCurrent().Add(field); + Stage::GetCurrent().Add( field ); field.TextChangedSignal().Connect(&TestTextChangedCallback); @@ -305,16 +465,8 @@ int utcDaliTextFieldTextChangedP(void) 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; @@ -328,13 +480,13 @@ int utcDaliTextFieldTextChangedN(void) 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; } @@ -347,7 +499,7 @@ int utcDaliTextFieldMaxCharactersReachedP(void) 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 ); @@ -357,17 +509,8 @@ int utcDaliTextFieldMaxCharactersReachedP(void) 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 ); @@ -382,7 +525,7 @@ int utcDaliTextFieldMaxCharactersReachedN(void) 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 ); @@ -392,18 +535,294 @@ int utcDaliTextFieldMaxCharactersReachedN(void) 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( 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( 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( 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; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index 8f59dd7..dd5d091 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -51,6 +51,8 @@ const char* const PROPERTY_NAME_UNDERLINE_ENABLED = "underline-enabled"; 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) @@ -149,13 +151,6 @@ 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( TextLabel::Property::RENDERING_BACKEND ), Text::RENDERING_SHARED_ATLAS, TEST_LOCATION ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_ENABLED ), false, TEST_LOCATION ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_HEIGHT ), 0.0f, TEST_LOCATION ); END_TEST; } @@ -163,18 +158,55 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) { 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( TextLabel::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::TEXT ), std::string(""), TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::FONT_FAMILY ), std::string(""), TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::FONT_STYLE ), std::string(""), TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::POINT_SIZE ), 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::MULTI_LINE ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_ENABLED ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_COLOR ), Color::BLACK, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_HEIGHT ), 0.0f, TEST_LOCATION ); + + label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Text::RENDERING_BASIC ); + DALI_TEST_EQUALS( label.GetProperty( 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( TextLabel::Property::TEXT ), "Setting Text", TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( 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( 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( TextLabel::Property::FONT_STYLE ), std::string("Setting font style"), TEST_LOCATION ); + label.SetProperty( TextLabel::Property::POINT_SIZE, 10.f ); + DALI_TEST_EQUALS( label.GetProperty( 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( 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( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION ); - label.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "TOP" ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION ); + label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "CENTER", TEST_LOCATION ); + label.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" ); + DALI_TEST_EQUALS( label.GetProperty( 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( TextLabel::Property::TEXT_COLOR ), Color::BLUE, TEST_LOCATION ); + // The underline color is changed as well. + DALI_TEST_EQUALS( label.GetProperty( 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 ) ); @@ -190,13 +222,10 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) label.SetProperty( TextLabel::Property::UNDERLINE_HEIGHT, 1.0f ); DALI_TEST_EQUALS( label.GetProperty( 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( TextLabel::Property::TEXT_COLOR ), Color::BLUE, TEST_LOCATION ); + TextLabel label2 = TextLabel::New( "New text" ); + DALI_TEST_CHECK( label2 ); + DALI_TEST_EQUALS( label2.GetProperty( TextLabel::Property::TEXT ), std::string("New text"), TEST_LOCATION ); - // Toggle multi-line - label.SetProperty( TextLabel::Property::MULTI_LINE, true ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::MULTI_LINE ), true, TEST_LOCATION ); END_TEST; } @@ -207,6 +236,11 @@ int UtcDaliToolkitTextlabelBasicRenderP(void) 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 ); @@ -231,6 +265,11 @@ int UtcDaliToolkitTextlabelAtlasRenderP(void) 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 ); @@ -238,6 +277,7 @@ int UtcDaliToolkitTextlabelAtlasRenderP(void) 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 @@ -252,3 +292,27 @@ int UtcDaliToolkitTextlabelAtlasRenderP(void) 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( TextLabel::Property::TEXT ), scripts, TEST_LOCATION ); + + application.SendNotification(); + application.Render(); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextSelectionPopup.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextSelectionPopup.cpp index b248e01..7aeb471 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextSelectionPopup.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextSelectionPopup.cpp @@ -41,7 +41,7 @@ int UtcDaliToolkitTextSelectionPopupNewP(void) DALI_TEST_CHECK( !textSelectionPopup ); - textSelectionPopup = TextSelectionPopup::New(); + textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL ); DALI_TEST_CHECK( textSelectionPopup ); END_TEST; @@ -61,7 +61,7 @@ int UtcDaliToolkitTextSelectionPopupCopyConstructorP(void) ToolkitTestApplication application; TextSelectionPopup textSelectionPopup; - textSelectionPopup = TextSelectionPopup::New(); + textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL ); TextSelectionPopup copy( textSelectionPopup ); DALI_TEST_CHECK( copy == textSelectionPopup ); @@ -85,7 +85,7 @@ int UtcDaliToolkitTextSelectionPopupAssignmentOperatorP(void) { ToolkitTestApplication application; TextSelectionPopup textSelectionPopup; - textSelectionPopup = TextSelectionPopup::New(); + textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL ); TextSelectionPopup copy; copy = textSelectionPopup; @@ -97,7 +97,7 @@ int UtcDaliToolkitTextSelectionPopupDownCastP(void) { ToolkitTestApplication application; TextSelectionPopup textSelectionPopup; - textSelectionPopup = TextSelectionPopup::New(); + textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL ); TextSelectionPopup cast = TextSelectionPopup::DownCast( textSelectionPopup ); diff --git a/dali-toolkit/devel-api/controls/magnifier/magnifier.cpp b/dali-toolkit/devel-api/controls/magnifier/magnifier.cpp index e51ee1e..40da8c8 100644 --- a/dali-toolkit/devel-api/controls/magnifier/magnifier.cpp +++ b/dali-toolkit/devel-api/controls/magnifier/magnifier.cpp @@ -36,8 +36,6 @@ namespace Toolkit // Magnifier /////////////////////////////////////////////////////////////////////////////////////////////////// -const std::string Magnifier::SOURCE_POSITION_PROPERTY_NAME( "source-position" ); - Magnifier::Magnifier() { } @@ -86,32 +84,6 @@ void Magnifier::SetSourceActor(Actor actor) 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 diff --git a/dali-toolkit/devel-api/controls/magnifier/magnifier.h b/dali-toolkit/devel-api/controls/magnifier/magnifier.h index 95c5a2b..181320d 100644 --- a/dali-toolkit/devel-api/controls/magnifier/magnifier.h +++ b/dali-toolkit/devel-api/controls/magnifier/magnifier.h @@ -45,9 +45,33 @@ class DALI_IMPORT_API Magnifier : public Control { 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: @@ -96,41 +120,6 @@ 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 /** diff --git a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h new file mode 100644 index 0000000..e903b77 --- /dev/null +++ b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h @@ -0,0 +1,55 @@ +#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 + +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__ diff --git a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.cpp b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.cpp index f41f667..5b85fac 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.cpp +++ b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.cpp @@ -29,9 +29,11 @@ namespace Dali namespace Toolkit { -TextSelectionPopup TextSelectionPopup::New() +TextSelectionPopup TextSelectionPopup::New( Buttons enabledButtons, + TextSelectionPopupCallbackInterface* callbackInterface ) { - return Internal::TextSelectionPopup::New(); + return Internal::TextSelectionPopup::New( enabledButtons, + callbackInterface ); } TextSelectionPopup::TextSelectionPopup() diff --git a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h index 69df315..3d6d5d0 100644 --- a/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h +++ b/dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h @@ -27,6 +27,8 @@ namespace Dali namespace Toolkit { +class TextSelectionPopupCallbackInterface; + namespace Internal DALI_INTERNAL { class TextSelectionPopup; @@ -46,6 +48,17 @@ class DALI_IMPORT_API TextSelectionPopup : public Control { 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. */ @@ -62,12 +75,11 @@ public: { enum { - - POPUP_MAX_SIZE = PROPERTY_START_INDEX, ///< name "popup-max-size", The maximum size the Popup can be, type VECTOR2 - POPUP_MIN_SIZE, ///< name "popup-min-size", The minimum size the Popup can be, type VECTOR2 - OPTION_MAX_SIZE, ///< name "option-max-size", The maximum size an option can be, type VECTOR2 - OPTION_MIN_SIZE, ///< name "option-min-size", The minimum size an option can be, type VECTOR2 - OPTION_DIVIDER_SIZE, ///< name "option-divider-size", The size of the divider between options type VECTOR2 + 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 @@ -78,10 +90,13 @@ public: }; /** - * 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. diff --git a/dali-toolkit/internal/builder/builder-actor.cpp b/dali-toolkit/internal/builder/builder-actor.cpp index 6ef44c0..fbe8c33 100644 --- a/dali-toolkit/internal/builder/builder-actor.cpp +++ b/dali-toolkit/internal/builder/builder-actor.cpp @@ -87,7 +87,7 @@ Actor SetupActor( const TreeNode& child, Actor& actor, const Replacement& consta { if( Property::INVALID_INDEX == index ) { - actor.RegisterProperty( key, value ); + actor.RegisterProperty( key, value, Property::READ_WRITE ); } else { diff --git a/dali-toolkit/internal/controls/alignment/alignment-impl.cpp b/dali-toolkit/internal/controls/alignment/alignment-impl.cpp index 7161df5..f080ba3 100644 --- a/dali-toolkit/internal/controls/alignment/alignment-impl.cpp +++ b/dali-toolkit/internal/controls/alignment/alignment-impl.cpp @@ -45,331 +45,67 @@ BaseHandle Create() 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 ) @@ -482,67 +218,73 @@ void Alignment::OnRelayout( const Vector2& size, RelayoutContainer& container ) 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 ); } } } diff --git a/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp b/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp index 15de6ea..bdc59ae 100644 --- a/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp +++ b/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp @@ -24,12 +24,36 @@ #include #include #include +#include +#include -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. @@ -92,16 +116,7 @@ struct RenderTaskViewportSizeConstraint } }; -} - -namespace Dali -{ - -namespace Toolkit -{ - -namespace Internal -{ +} // unnamed namespace /////////////////////////////////////////////////////////////////////////////////////////////////// // Magnifier @@ -124,7 +139,6 @@ Dali::Toolkit::Magnifier Magnifier::New() Magnifier::Magnifier() : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ), - mPropertySourcePosition(Property::INVALID_INDEX), mDefaultCameraDistance(1000.f), mActorSize(Vector3::ZERO), mMagnificationFactor(1.0f) @@ -136,15 +150,9 @@ void Magnifier::SetSourceActor(Actor actor) 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: @@ -161,7 +169,7 @@ void Magnifier::Initialize() Stage().GetCurrent().Add(mSourceActor); mSourceActor.SetParentOrigin(ParentOrigin::CENTER); Constraint constraint = Constraint::New( 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 @@ -317,6 +325,56 @@ void Magnifier::Update() 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 diff --git a/dali-toolkit/internal/controls/magnifier/magnifier-impl.h b/dali-toolkit/internal/controls/magnifier/magnifier-impl.h index d4fea4e..d8b990f 100644 --- a/dali-toolkit/internal/controls/magnifier/magnifier-impl.h +++ b/dali-toolkit/internal/controls/magnifier/magnifier-impl.h @@ -62,27 +62,30 @@ public: 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); @@ -91,6 +94,24 @@ public: */ 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: /** @@ -132,7 +153,6 @@ private: 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 diff --git a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp index 742ef5e..2250801 100644 --- a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp +++ b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp @@ -31,12 +31,25 @@ using namespace Dali; 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 ) { @@ -141,11 +154,27 @@ 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 ) @@ -169,10 +198,7 @@ bool TableView::AddChild( Actor& child, const Toolkit::TableView::CellPosition& 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() ) @@ -544,44 +570,44 @@ Size TableView::GetCellPadding() 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 ) @@ -590,7 +616,7 @@ 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(); @@ -609,7 +635,7 @@ void TableView::SetFixedWidth( unsigned int columnIndex, float width ) RowColumnData& data = mColumnData[ columnIndex ]; data.size = width; - data.sizePolicy = FIXED; + data.sizePolicy = Toolkit::TableView::FIXED; mRowColumnDirty = true; RelayoutRequest(); @@ -628,8 +654,7 @@ void TableView::SetRelativeHeight( unsigned int rowIndex, float heightPercentage RowColumnData& data = mRowData[ rowIndex ]; data.fillRatio = heightPercentage; - data.userFillRatio = true; - data.sizePolicy = FILL; + data.sizePolicy = Toolkit::TableView::RELATIVE; mRowColumnDirty = true; RelayoutRequest(); @@ -648,8 +673,7 @@ void TableView::SetRelativeWidth( unsigned int columnIndex, float widthPercentag RowColumnData& data = mColumnData[ columnIndex ]; data.fillRatio = widthPercentage; - data.userFillRatio = true; - data.sizePolicy = FILL; + data.sizePolicy = Toolkit::TableView::RELATIVE; mRowColumnDirty = true; RelayoutRequest(); @@ -723,45 +747,89 @@ void TableView::OnRelayout( const Vector2& size, RelayoutContainer& container ) { 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 ); + } + } + } + } } } @@ -807,12 +875,12 @@ void TableView::SetProperty( BaseObject* object, Property::Index index, const Pr } 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; } } @@ -869,29 +937,49 @@ void TableView::OnControlChildAdd( Actor& child ) 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(); + 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(); + 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( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) ).Get() ); + cellPosition.rowSpan = static_cast( child.GetProperty( child.GetPropertyIndex(ROW_SPAN_PROPERTY_NAME) ).Get() ); } - 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( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) ).Get() ); + cellPosition.columnSpan = static_cast( child.GetProperty( child.GetPropertyIndex(COLUMN_SPAN_PROPERTY_NAME) ).Get() ); } - 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 indices = child.GetProperty( child.GetPropertyIndex(CELL_INDEX_PROPERTY_NAME) ).Get(); cellPosition.rowIndex = static_cast( indices.x ); cellPosition.columnIndex = static_cast( indices.y ); AddChild( child, cellPosition ); + SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment); // Do not continue + RelayoutRequest(); return; } @@ -909,9 +997,12 @@ void TableView::OnControlChildAdd( Actor& child ) 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; } } @@ -926,7 +1017,10 @@ void TableView::OnControlChildAdd( Actor& child ) 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 ) @@ -1048,18 +1142,19 @@ bool TableView::RemoveAllInstances( const 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 ) { Property::Map* map = value.GetMap(); if( map ) { - unsigned int rowIndex(0); + unsigned int index(0); for ( unsigned int i = 0, count = map->Count(); i < count; ++i ) { Property::Value& item = map->GetValue(i); Property::Map* childMap = item.GetMap(); - std::istringstream( map->GetKey(i) ) >> rowIndex; + std::istringstream( map->GetKey(i) ) >> index; if( childMap ) { Property::Value* policy = childMap->Find( "policy" ); @@ -1074,14 +1169,19 @@ void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl, LAYOUT_POLICY_STRING_TABLE_COUNT, policy ) ) { - if( policy == Toolkit::TableView::FIXED ) + if( policy == Toolkit::TableView::FIXED ) { - (tableViewImpl.*funcFixed)( rowIndex, value->Get() ); + (tableViewImpl.*funcFixed)( index, value->Get() ); } else if( policy == Toolkit::TableView::RELATIVE ) { - (tableViewImpl.*funcRelative)( rowIndex, value->Get() ); + (tableViewImpl.*funcRelative)( index, value->Get() ); + } + else if( policy == Toolkit::TableView::FIT ) + { + (tableViewImpl.*funcFit)( index ); } + // do nothing for FILL policy } } } @@ -1105,63 +1205,56 @@ Property::Value TableView::GetColumnWidthsPropertyValue() void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map ) { - const char* name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED, - LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT ); - std::string fixedPolicy; - if( name ) - { - fixedPolicy = name; - } - name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE, - LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT ); - std::string relativePolicy; - if( name ) - { - relativePolicy = name; - } + 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; } } @@ -1319,7 +1412,7 @@ float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimensi } // Apply padding - cellSize -= mPadding.width * 2.0f; + cellSize -= mPadding.height * 2.0f; if( cellSize < 0.0f ) { cellSize = 0.0f; @@ -1384,16 +1477,13 @@ void TableView::ComputeRelativeSizes( RowColumnArray& data ) { 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 ); } } @@ -1427,8 +1517,9 @@ float TableView::CalculateTotalFixedSize( const RowColumnArray& data ) 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; @@ -1475,7 +1566,7 @@ void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimen { 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; @@ -1513,7 +1604,7 @@ void TableView::CalculateRelativeSizes( RowColumnArray& data, float size ) { RowColumnData& dataInstance = data[ i ]; - if( dataInstance.sizePolicy == FILL ) + if( dataInstance.sizePolicy == Toolkit::TableView::FILL || dataInstance.sizePolicy == Toolkit::TableView::RELATIVE) { dataInstance.size = dataInstance.fillRatio * size; } @@ -1524,7 +1615,7 @@ bool TableView::FindFit( const RowColumnArray& data ) { 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; } diff --git a/dali-toolkit/internal/controls/table-view/table-view-impl.h b/dali-toolkit/internal/controls/table-view/table-view-impl.h index d1d8aef..62e0a6f 100644 --- a/dali-toolkit/internal/controls/table-view/table-view-impl.h +++ b/dali-toolkit/internal/controls/table-view/table-view-impl.h @@ -41,16 +41,6 @@ class TableView : public Control 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. */ @@ -127,36 +117,24 @@ public: 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 @@ -299,8 +277,8 @@ private: // Implementation RowColumnData() : size( 0.0f ), fillRatio( 0.0f ), - sizePolicy( FILL ), - userFillRatio( false ) + position(0.0f), + sizePolicy( Toolkit::TableView::FILL ) { } @@ -310,18 +288,18 @@ private: // Implementation * @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 RowColumnArray; @@ -447,13 +425,15 @@ private: // scripting support /** * 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 ); /** @@ -518,7 +498,7 @@ private: private: // Data - Array2d mCellData; ///< Data for each cell: Actor, alignment settings etc + Array2d mCellData; ///< Data for each cell: Actor, alignment settings etc RowColumnArray mRowData; ///< Data for each row RowColumnArray mColumnData; ///< Data for each column @@ -526,7 +506,7 @@ private: // Data 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 diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index 305d61c..126518d 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -873,7 +873,8 @@ void TextField::OnInitialize() mController = Text::Controller::New( *this ); - mDecorator = Text::Decorator::New( *mController ); + mDecorator = Text::Decorator::New( *mController, + *mController ); mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX ); diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp index be7834a..91ef03b 100644 --- a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp @@ -19,7 +19,7 @@ #include // INTERNAL INCLUDES -#include +#include #include #include @@ -48,7 +48,7 @@ namespace 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_ICON_PRESSED( Dali::Vector4( 0.12f, 0.56f, 1.0f, 1.0f ) ); 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" ); @@ -89,7 +89,7 @@ const char* const OPTION_CLIPBOARD("option-clipboard"); BaseHandle Create() { - return Toolkit::TextSelectionPopup::New(); + return Toolkit::TextSelectionPopup::New( Toolkit::TextSelectionPopup::NONE, NULL ); } // Setup properties, signals and actions using the type-registry. @@ -112,14 +112,18 @@ DALI_TYPE_REGISTRATION_END() } // namespace -Dali::Toolkit::TextSelectionPopup TextSelectionPopup::New() + +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(); @@ -165,37 +169,37 @@ void TextSelectionPopup::SetProperty( BaseObject* object, Property::Index index, case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE: { ResourceImage image = ResourceImage::New( value.Get< std::string >() ); - impl.SetButtonImage( CLIPBOARD, 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.SetButtonImage( CUT, 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.SetButtonImage( COPY, 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.SetButtonImage( PASTE, 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.SetButtonImage( SELECT, 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.SetButtonImage( SELECT_ALL, image ); + impl.SetButtonImage( Toolkit::TextSelectionPopup::SELECT_ALL, image ); break; } } // switch @@ -236,7 +240,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I } case Toolkit::TextSelectionPopup::Property::POPUP_CLIPBOARD_BUTTON_ICON_IMAGE: { - ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( CLIPBOARD ) ); + ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::CLIPBOARD ) ); if( image ) { value = image.GetUrl(); @@ -245,7 +249,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I } case Toolkit::TextSelectionPopup::Property::POPUP_CUT_BUTTON_ICON_IMAGE: { - ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( CUT ) ); + ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::CUT ) ); if( image ) { value = image.GetUrl(); @@ -254,7 +258,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I } case Toolkit::TextSelectionPopup::Property::POPUP_COPY_BUTTON_ICON_IMAGE: { - ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( COPY ) ); + ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::COPY ) ); if( image ) { value = image.GetUrl(); @@ -263,7 +267,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I } case Toolkit::TextSelectionPopup::Property::POPUP_PASTE_BUTTON_ICON_IMAGE: { - ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( PASTE ) ); + ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::PASTE ) ); if( image ) { value = image.GetUrl(); @@ -272,7 +276,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I } case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_BUTTON_ICON_IMAGE: { - ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( SELECT ) ); + ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::SELECT ) ); if( image ) { value = image.GetUrl(); @@ -281,7 +285,7 @@ Property::Value TextSelectionPopup::GetProperty( BaseObject* object, Property::I } case Toolkit::TextSelectionPopup::Property::POPUP_SELECT_ALL_BUTTON_ICON_IMAGE: { - ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( SELECT_ALL ) ); + ResourceImage image = ResourceImage::DownCast( impl.GetButtonImage( Toolkit::TextSelectionPopup::SELECT_ALL ) ); if( image ) { value = image.GetUrl(); @@ -298,6 +302,66 @@ void TextSelectionPopup::OnInitialize() CreatePopup(); } +bool TextSelectionPopup::OnCutButtonPressed( Toolkit::Button button ) +{ + if( mCallbackInterface ) + { + mCallbackInterface->TextPopupButtonTouched( Toolkit::TextSelectionPopup::CUT ); + } + + return true; +} + +bool TextSelectionPopup::OnCopyButtonPressed( Toolkit::Button button ) +{ + if( mCallbackInterface ) + { + mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::COPY ); + } + + return true; +} + +bool TextSelectionPopup::OnPasteButtonPressed( Toolkit::Button button ) +{ + if( mCallbackInterface ) + { + mCallbackInterface->TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::PASTE ); + } + + return true; +} + +bool TextSelectionPopup::OnSelectButtonPressed( Toolkit::Button button ) +{ + 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 ) @@ -373,37 +437,37 @@ Size TextSelectionPopup::GetDimensionToCustomise( const PopupCustomisations& set return Size::ZERO; } -void TextSelectionPopup::SetButtonImage( Buttons button, Dali::Image image ) +void TextSelectionPopup::SetButtonImage( Toolkit::TextSelectionPopup::Buttons button, Dali::Image image ) { switch ( button ) { break; - case CLIPBOARD: + case Toolkit::TextSelectionPopup::CLIPBOARD: { mClipboardIconImage = image; } break; - case CUT : + case Toolkit::TextSelectionPopup::CUT : { mCutIconImage = image; } break; - case COPY : + case Toolkit::TextSelectionPopup::COPY : { mCopyIconImage = image; } break; - case PASTE : + case Toolkit::TextSelectionPopup::PASTE : { mPasteIconImage = image; } break; - case SELECT : + case Toolkit::TextSelectionPopup::SELECT : { mSelectIconImage = image; } break; - case SELECT_ALL : + case Toolkit::TextSelectionPopup::SELECT_ALL : { mSelectAllIconImage = image; } @@ -415,36 +479,36 @@ void TextSelectionPopup::SetButtonImage( Buttons button, Dali::Image image ) } // switch } -Dali::Image TextSelectionPopup::GetButtonImage( Buttons button ) +Dali::Image TextSelectionPopup::GetButtonImage( Toolkit::TextSelectionPopup::Buttons button ) { switch ( button ) { - case CLIPBOARD : + case Toolkit::TextSelectionPopup::CLIPBOARD : { return mClipboardIconImage; } break; - case CUT : + case Toolkit::TextSelectionPopup::CUT : { return mCutIconImage; } break; - case COPY : + case Toolkit::TextSelectionPopup::COPY : { return mCopyIconImage; } break; - case PASTE : + case Toolkit::TextSelectionPopup::PASTE : { return mPasteIconImage; } break; - case SELECT : + case Toolkit::TextSelectionPopup::SELECT : { return mSelectIconImage; } break; - case SELECT_ALL : + case Toolkit::TextSelectionPopup::SELECT_ALL : { return mSelectAllIconImage; } @@ -467,42 +531,47 @@ Dali::Image TextSelectionPopup::GetButtonImage( Buttons button ) { mCutIconImage = ResourceImage::New( OPTION_ICON_CUT ); } - mOrderListOfButtons.push_back( ButtonRequirement( CUT, mCutOptionPriority, OPTION_CUT, POPUP_CUT_STRING , mCutIconImage, false ) ); + 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( COPY, mCopyOptionPriority, OPTION_COPY, POPUP_COPY_STRING, mCopyIconImage, false ) ); + 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( PASTE, mPasteOptionPriority, OPTION_PASTE, POPUP_PASTE_STRING, mPasteIconImage, false ) ); + 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( SELECT, mSelectOptionPriority, OPTION_SELECT_WORD, POPUP_SELECT_STRING, 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( SELECT_ALL, mSelectAllOptionPriority, OPTION_SELECT_ALL, POPUP_SELECT_ALL_STRING, 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( CLIPBOARD, mClipboardOptionPriority, OPTION_CLIPBOARD, POPUP_CLIPBOARD_STRING, mClipboardIconImage, false ) ); + 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::AddOption( const std::string& name, const std::string& caption, const Image iconImage, bool showDivider, bool showIcons, bool showCaption ) + void TextSelectionPopup::AddOption( const ButtonRequirement& button, bool showDivider, bool showIcons, bool showCaption ) { + + const std::string& name = button.name; + const std::string& caption = button.caption; + Image iconImage = button.icon; + // 1. Create the backgrounds for the popup option both normal and pressed. // Both containers will be added to a button. @@ -515,7 +584,7 @@ Dali::Image TextSelectionPopup::GetButtonImage( Buttons button ) optionPressedContainer.SetDrawMode( DrawMode::OVERLAY ); optionPressedContainer.SetFitHeight( 0 ); optionPressedContainer.SetFitWidth( 0 ); - optionPressedContainer.SetBackgroundColor(Color::RED); //todo member variable + optionPressedContainer.SetBackgroundColor( mPressedColor ); #ifdef DECORATOR_DEBUG optionContainer.SetName("optionContainer"); @@ -536,7 +605,7 @@ Dali::Image TextSelectionPopup::GetButtonImage( Buttons button ) Padding padding; padding.left = 24.0f; padding.right = 24.0f; - padding.top = 13.0f; + padding.top = 14.0f; padding.bottom = 14.0f; captionTextLabel.SetPadding( padding ); pressedCaptionTextLabel.SetPadding( padding ); @@ -554,7 +623,6 @@ Dali::Image TextSelectionPopup::GetButtonImage( Buttons button ) icon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); pressedIcon.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); icon.SetColor( mIconColor ); - pressedIcon.SetColor( mIconPressedColor ); if ( showCaption & showIcons ) { @@ -576,7 +644,45 @@ Dali::Image TextSelectionPopup::GetButtonImage( Buttons button ) option.SetName( name ); option.SetAnimationTime( 0.0f ); option.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); - //option.ClickedSignal().Connect( this, &TextInputPopup::OnButtonPressed ); + + 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 ); @@ -626,7 +732,7 @@ Dali::Image TextSelectionPopup::GetButtonImage( Buttons button ) if ( button.enabled ) { numberOfOptionsAdded++; - AddOption( button.name, button.caption, button.icon, ( numberOfOptionsAdded < numberOfOptionsRequired ) , showIcons, showCaptions ); + AddOption( button, ( numberOfOptionsAdded < numberOfOptionsRequired ) , showIcons, showCaptions ); } } } @@ -648,15 +754,17 @@ Dali::Image TextSelectionPopup::GetButtonImage( Buttons button ) } } -TextSelectionPopup::TextSelectionPopup() +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 ), + mPressedColor( DEFAULT_OPTION_ICON_PRESSED ), mSelectOptionPriority( 1 ), mSelectAllOptionPriority ( 2 ), mCutOptionPriority ( 3 ), diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h index 34c2235..c409983 100644 --- a/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h @@ -20,6 +20,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -55,21 +56,10 @@ class TextSelectionPopup : public Control { public: - enum Buttons - { - CUT, - COPY, - PASTE, - SELECT, - SELECT_ALL, - CLIPBOARD, - ENUM_END - }; - struct ButtonRequirement { ButtonRequirement() - : id( ENUM_END ), + : id( Toolkit::TextSelectionPopup::NONE ), priority( 0u ), name(), caption(), @@ -77,7 +67,7 @@ public: enabled( false ) {} - ButtonRequirement( Buttons buttonId, + ButtonRequirement( Toolkit::TextSelectionPopup::Buttons buttonId, std::size_t buttonPriority, const std::string& buttonName, const std::string& buttonCaption, @@ -91,7 +81,7 @@ public: enabled( buttonEnabled ) {} - Buttons id; + Toolkit::TextSelectionPopup::Buttons id; std::size_t priority; std::string name; std::string caption; @@ -107,9 +97,13 @@ public: }; /** - * @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 @@ -140,6 +134,48 @@ private: // From Control private: // Implementation /** + * @brief When the cut button is pressed. + * @param[in] button the button pressed + * @return @e true to consume the event. + */ + bool OnCutButtonPressed( Toolkit::Button button ); + + /** + * @brief When the copy button is pressed. + * @param[in] button the button pressed + * @return @e true to consume the event. + */ + bool OnCopyButtonPressed( Toolkit::Button button ); + + /** + * @brief When the paste button is pressed. + * @param[in] button the button pressed + * @return @e true to consume the event. + */ + bool OnPasteButtonPressed( Toolkit::Button button ); + + /** + * @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 @@ -160,7 +196,7 @@ private: // Implementation * @param[in] button The button the image should be used for from the Buttons Enum. * @param[in] image The image to use. */ - void SetButtonImage( Buttons button, Dali::Image image ); + void SetButtonImage( Toolkit::TextSelectionPopup::Buttons button, Dali::Image image ); /** * @brief Retrieves the image of the given button used by the popup @@ -168,11 +204,11 @@ private: // Implementation * @param[in] button The button to get the image from * @return The image used for that button. */ - Dali::Image GetButtonImage( Buttons button ); + Dali::Image GetButtonImage( Toolkit::TextSelectionPopup::Buttons button ); void CreateOrderedListOfPopupOptions(); - void AddOption( const std::string& name, const std::string& caption, const Image iconImage, bool showDivider, bool showIcons, bool showCaption ); + void AddOption( const ButtonRequirement& button, bool showDivider, bool showIcons, bool showCaption ); std::size_t GetNumberOfEnabledOptions(); @@ -183,7 +219,7 @@ private: // Implementation /** * Construct a new TextField. */ - TextSelectionPopup(); + TextSelectionPopup( TextSelectionPopupCallbackInterface* callbackInterface ); /** * A reference counted object may only be deleted by calling Unreference() @@ -220,9 +256,12 @@ private: // Data std::vector mOrderListOfButtons; // List of buttons in the order to be displayed and a flag to indicate if needed. + 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 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 @@ -232,8 +271,8 @@ private: // Data 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 }; diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp index 4b25f77..cb1e205 100644 --- a/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include namespace Dali @@ -43,8 +41,6 @@ namespace { const Dali::Vector2 DEFAULT_MAX_SIZE( 400.0f, 65.0f ); ///< The maximum size of the Toolbar. -} // namespace - BaseHandle Create() { return Toolkit::TextSelectionToolbar::New(); @@ -58,6 +54,8 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextSelectionToolbar, "max-size", VECTOR2, DALI_TYPE_REGISTRATION_END() +} // namespace + Dali::Toolkit::TextSelectionToolbar TextSelectionToolbar::New() { // Create the implementation, temporarily owned by this handle on stack @@ -120,6 +118,13 @@ 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; @@ -130,16 +135,35 @@ 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. - mStencilLayer = Layer::New(); - mStencilLayer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS ); - mStencilLayer.SetParentOrigin( ParentOrigin::CENTER ); - mStencilLayer.SetMaximumSize( mMaxSize ); + // 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 ); @@ -147,21 +171,32 @@ void TextSelectionToolbar::SetUp() stencil.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, 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 ); + mScrollView = Toolkit::ScrollView::New(); + SetUpScrollView( mScrollView ); - // Toolbar needs at least one option, adding further options with increase it's size + // 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 ); + mTableOfButtons.SetParentOrigin( ParentOrigin::CENTER_LEFT ); + mTableOfButtons.SetAnchorPoint( AnchorPoint::CENTER_LEFT ); + + + stencilLayer.Add( stencil ); + stencilLayer.Add( mScrollView ); + mScrollView.Add( mTableOfButtons ); + self.Add( stencilLayer ); - mStencilLayer.Add( stencil ); - mStencilLayer.Add( scrollview ); - scrollview.Add( mTableOfButtons ); - self.Add( mStencilLayer ); + stencilLayer.RaiseToTop(); +} - mStencilLayer.RaiseToTop(); +void TextSelectionToolbar::OnScrollStarted( const Vector2& position ) +{ + mTableOfButtons.SetSensitive( false ); +} + +void TextSelectionToolbar::OnScrollCompleted( const Vector2& position ) +{ + mTableOfButtons.SetSensitive( true ); } void TextSelectionToolbar::AddOption( Actor& option ) @@ -197,6 +232,7 @@ TextSelectionToolbar::TextSelectionToolbar() TextSelectionToolbar::~TextSelectionToolbar() { + mRulerX.Reset(); } diff --git a/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h b/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h index fb85e95..3593e79 100644 --- a/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.h @@ -20,6 +20,7 @@ // INTERNAL INCLUDES #include +#include #include #include @@ -88,9 +89,13 @@ private: // From Control /** * @copydoc Control::OnInitialize() */ - virtual void 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) */ @@ -103,10 +108,28 @@ private: // From Control 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 /** @@ -127,9 +150,9 @@ private: 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 - + 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. diff --git a/dali-toolkit/internal/text/bidirectional-support.cpp b/dali-toolkit/internal/text/bidirectional-support.cpp index 135f71b..cf9ec63 100644 --- a/dali-toolkit/internal/text/bidirectional-support.cpp +++ b/dali-toolkit/internal/text/bidirectional-support.cpp @@ -162,13 +162,6 @@ void SetBidirectionalInfo( const Vector& text, } } -void ReplaceBidirectionalInfo( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ -} - void ReorderLines( const Vector& bidirectionalInfo, Vector& lineRuns, Vector& lineInfoRuns ) @@ -234,14 +227,6 @@ void ReorderLines( const Vector& bidirectionalInf } } -void ReorderLines( LogicalModel& logicalModel, - const VisualModel& visualModel, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ -} - bool GetMirroredText( const Vector& text, Vector& mirroredText ) { diff --git a/dali-toolkit/internal/text/bidirectional-support.h b/dali-toolkit/internal/text/bidirectional-support.h index f51e5e7..2f3b251 100644 --- a/dali-toolkit/internal/text/bidirectional-support.h +++ b/dali-toolkit/internal/text/bidirectional-support.h @@ -53,25 +53,6 @@ void SetBidirectionalInfo( const Vector& text, Vector& bidirectionalInfo ); /** - * Replaces the bidirectional info from the logical model. - * - * @pre The @p model needs to have a text set. - * @pre The @p model needs to have the line break info set. - * - * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. - * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. - * - * @param[in,out] model The text's logical model. - * @param[in] characterIndex Index to the first character. - * @param[in] numberOfCharactersToRemove The number of characters removed from the text. - * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. - */ -void ReplaceBidirectionalInfo( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); - -/** * Sets the visual to logical map tables. * * Any map tables previously set are removed. @@ -90,28 +71,6 @@ void ReorderLines( const Vector& bidirectionalInf Vector& lineInfoRuns ); /** - * Replaces the visual to logical and logical to visual map tables. - * - * @pre The @p logicalModel needs to have a text set. - * @pre The @p logicalModel needs to have the line break info set. - * @pre The @p visualModel needs to have the laid-out lines info set. - * - * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. - * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. - * - * @param[in,out] logicalModel The text's logical model. - * @param[in] visualModel The text's visual model. - * @param[in] characterIndex Index to the first character. - * @param[in] numberOfCharactersToRemove The number of characters removed from the text. - * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. - */ -void ReorderLines( LogicalModel& logicalModel, - const VisualModel& visualModel, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); - -/** * @brief Replaces any character which could be mirrored. * * @param[in] text The text. diff --git a/dali-toolkit/internal/text/clipping/text-clipper.cpp b/dali-toolkit/internal/text/clipping/text-clipper.cpp index 8b0f77f..e9c6e8f 100644 --- a/dali-toolkit/internal/text/clipping/text-clipper.cpp +++ b/dali-toolkit/internal/text/clipping/text-clipper.cpp @@ -79,6 +79,8 @@ void Clipper::Refresh( const Vector2& size ) offscreenSize.height, Pixel::RGBA8888 ); + mOffscreenRootActor.SetSize( size ); + mImageActor.SetSize( offscreenSize ); mImageActor.SetImage( frameBufferImage ); mRenderTask.SetTargetFrameBuffer( frameBufferImage ); diff --git a/dali-toolkit/internal/text/decorator/text-decorator.cpp b/dali-toolkit/internal/text/decorator/text-decorator.cpp index b2fcda0..31c62c5 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.cpp +++ b/dali-toolkit/internal/text/decorator/text-decorator.cpp @@ -75,11 +75,15 @@ namespace 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::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. @@ -193,6 +197,7 @@ struct Decorator::Impl : public ConnectionTracker grabDisplacementY( 0.f ), active( false ), visible( false ), + pressed( false ), flipped( false ) { } @@ -206,13 +211,31 @@ struct Decorator::Impl : public ConnectionTracker float grabDisplacementY; bool active : 1; bool visible : 1; + bool pressed : 1; bool flipped : 1; }; - Impl( ControllerInterface& controller ) + 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() ), mHighlightColor( LIGHT_BLUE ), + mHighlightPosition( Vector2::ZERO ), mActiveCursor( ACTIVE_CURSOR_NONE ), mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ), mCursorBlinkDuration( 0.0f ), @@ -225,7 +248,8 @@ struct Decorator::Impl : public ConnectionTracker mCursorBlinkStatus( true ), mPrimaryCursorVisible( false ), mSecondaryCursorVisible( false ), - mSwapSelectionHandles( false ) + mSwapSelectionHandles( false ), + mNotifyEndOfScroll( false ) { } @@ -247,17 +271,6 @@ struct Decorator::Impl : public ConnectionTracker 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 ); @@ -284,18 +297,6 @@ struct Decorator::Impl : public ConnectionTracker { 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 ) @@ -322,29 +323,6 @@ struct Decorator::Impl : public ConnectionTracker Vector2 primaryPosition = primary.position; Vector2 secondaryPosition = secondary.position; - if( LEFT_SELECTION_HANDLE == mHandleScrolling ) - { - if( mScrollDirection == SCROLL_RIGHT ) - { - primaryPosition.x = 0.f; - } - else - { - primaryPosition.x = size.width; - } - } - else if( RIGHT_SELECTION_HANDLE == mHandleScrolling ) - { - if( mScrollDirection == SCROLL_RIGHT ) - { - secondaryPosition.x = 0.f; - } - else - { - secondaryPosition.x = size.width; - } - } - const bool isPrimaryVisible = ( primaryPosition.x <= size.width ) && ( primaryPosition.x >= 0.f ); const bool isSecondaryVisible = ( secondaryPosition.x <= size.width ) && ( secondaryPosition.x >= 0.f ); @@ -358,22 +336,12 @@ struct Decorator::Impl : public ConnectionTracker { primary.actor.SetPosition( primaryPosition.x, primaryPosition.y + primary.lineHeight ); - - const bool flip = mSwapSelectionHandles ^ primary.flipped; - primary.actor.SetImage( flip ? mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] : mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] ); - - primary.actor.SetAnchorPoint( flip ? AnchorPoint::TOP_LEFT : AnchorPoint::TOP_RIGHT ); } if( isSecondaryVisible ) { secondary.actor.SetPosition( secondaryPosition.x, secondaryPosition.y + secondary.lineHeight ); - - const bool flip = mSwapSelectionHandles ^ secondary.flipped; - - secondary.actor.SetImage( ( mSwapSelectionHandles ^ secondary.flipped ) ? mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] : mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] ); - secondary.actor.SetAnchorPoint( flip ? AnchorPoint::TOP_RIGHT : AnchorPoint::TOP_LEFT ); } } primary.actor.SetVisible( isPrimaryVisible ); @@ -391,22 +359,24 @@ struct Decorator::Impl : public ConnectionTracker 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 ); } } } @@ -421,21 +391,43 @@ struct Decorator::Impl : public ConnectionTracker 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; + } + + 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 ); + + float minHandleYPosition = std::min ( mHandle[LEFT_SELECTION_HANDLE].position.y, mHandle[RIGHT_SELECTION_HANDLE].position.y ); - mCopyPastePopup.OnRelayoutSignal().Disconnect( this, &Decorator::Impl::PopUpRelayoutComplete ); + 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 popupPosition( 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 ); - Vector3 popupSize = Vector3( mCopyPastePopup.GetRelayoutSize( Dimension::WIDTH ), mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT ), 0.0f ); + GetConstrainedPopupPosition( mCopyPastePopup.position, popupSize, AnchorPoint::CENTER, mActiveLayer, mBoundingBox ); - GetConstrainedPopupPosition( popupPosition, 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 ) @@ -594,7 +586,11 @@ struct Decorator::Impl : public ConnectionTracker { 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] ); @@ -610,8 +606,9 @@ struct Decorator::Impl : public ConnectionTracker 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 ); @@ -626,7 +623,11 @@ struct Decorator::Impl : public ConnectionTracker { 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] ); @@ -642,8 +643,9 @@ struct Decorator::Impl : public ConnectionTracker 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 ); @@ -820,8 +822,10 @@ struct Decorator::Impl : public ConnectionTracker 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(); mController.DecorationEvent( type, HANDLE_STOP_SCROLLING, x, y ); @@ -830,7 +834,23 @@ struct Decorator::Impl : public ConnectionTracker { 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; } } @@ -862,15 +882,23 @@ struct Decorator::Impl : public ConnectionTracker { 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 ); + } } } @@ -878,16 +906,68 @@ struct Decorator::Impl : public ConnectionTracker 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; } @@ -928,11 +1008,11 @@ struct Decorator::Impl : public ConnectionTracker // 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. @@ -941,11 +1021,11 @@ struct Decorator::Impl : public ConnectionTracker 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 ); } @@ -982,6 +1062,34 @@ struct Decorator::Impl : public ConnectionTracker } requiredPopupPosition.x = requiredPopupPosition.x + xOffSetToKeepWithinBounds; + + // Prevent pixel mis-alignment by rounding down. + requiredPopupPosition.x = static_cast( requiredPopupPosition.x ); + requiredPopupPosition.y = static_cast( 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 ) @@ -1005,6 +1113,16 @@ struct Decorator::Impl : public ConnectionTracker 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. * @@ -1064,7 +1182,10 @@ struct Decorator::Impl : public ConnectionTracker 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; @@ -1075,10 +1196,10 @@ struct Decorator::Impl : public ConnectionTracker CursorImpl mCursor[CURSOR_COUNT]; HandleImpl mHandle[HANDLE_TYPE_COUNT]; QuadContainer mHighlightQuadList; ///< Sub-selections that combine to create the complete selection highlight - Vector2 mHighlightPosition; ///< The position of the highlight actor. Rect mBoundingBox; Vector4 mHighlightColor; ///< Color of the highlight + Vector2 mHighlightPosition; ///< The position of the highlight actor. unsigned int mActiveCursor; unsigned int mCursorBlinkInterval; @@ -1088,18 +1209,20 @@ struct Decorator::Impl : public ConnectionTracker 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( ControllerInterface& controller ) +DecoratorPtr Decorator::New( ControllerInterface& controller, + TextSelectionPopupCallbackInterface& callbackInterface ) { - return DecoratorPtr( new Decorator(controller) ); + return DecoratorPtr( new Decorator( controller, + callbackInterface ) ); } void Decorator::SetBoundingBox( const Rect& boundingBox ) @@ -1259,6 +1382,8 @@ const Vector2& Decorator::GetPosition( HandleType handleType ) const void Decorator::SwapSelectionHandlesEnabled( bool enable ) { mImpl->mSwapSelectionHandles = enable; + + mImpl->FlipSelectionHandleImages(); } void Decorator::AddHighlight( float x1, float y1, float x2, float y2 ) @@ -1292,6 +1417,16 @@ bool Decorator::IsPopupActive() const 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 ) @@ -1314,15 +1449,21 @@ float Decorator::GetScrollSpeed() const return mImpl->GetScrollSpeed(); } +void Decorator::NotifyEndOfScroll() +{ + mImpl->NotifyEndOfScroll(); +} + Decorator::~Decorator() { delete mImpl; } -Decorator::Decorator( ControllerInterface& controller ) +Decorator::Decorator( ControllerInterface& controller, + TextSelectionPopupCallbackInterface& callbackInterface ) : mImpl( NULL ) { - mImpl = new Decorator::Impl( controller ); + mImpl = new Decorator::Impl( controller, callbackInterface ); } } // namespace Text diff --git a/dali-toolkit/internal/text/decorator/text-decorator.h b/dali-toolkit/internal/text/decorator/text-decorator.h index 873bdcc..f38c467 100644 --- a/dali-toolkit/internal/text/decorator/text-decorator.h +++ b/dali-toolkit/internal/text/decorator/text-decorator.h @@ -24,6 +24,9 @@ #include #include +// INTERNAL INCLUDES +#include + namespace Dali { @@ -35,6 +38,8 @@ class Vector4; namespace Toolkit { +class TextSelectionPopupCallbackInterface; + namespace Internal { class Control; @@ -149,9 +154,12 @@ public: * @brief Create a new instance of a Decorator. * * @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( ControllerInterface& controller ); + static DecoratorPtr New( ControllerInterface& controller, + TextSelectionPopupCallbackInterface& callbackInterface ); /** * @brief Set the bounding box which handles, popup and similar decorations will not exceed. @@ -414,6 +422,18 @@ public: 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. @@ -447,18 +467,9 @@ public: 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: @@ -472,8 +483,10 @@ private: /** * @brief Private constructor. * @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( ControllerInterface& controller ); + Decorator( ControllerInterface& controller, + TextSelectionPopupCallbackInterface& callbackInterface ); // Undefined Decorator( const Decorator& handle ); diff --git a/dali-toolkit/internal/text/logical-model-impl.cpp b/dali-toolkit/internal/text/logical-model-impl.cpp index 2faca97..7dbe628 100644 --- a/dali-toolkit/internal/text/logical-model-impl.cpp +++ b/dali-toolkit/internal/text/logical-model-impl.cpp @@ -35,112 +35,6 @@ LogicalModelPtr LogicalModel::New() return LogicalModelPtr( new LogicalModel() ); } -void LogicalModel::SetText( const Character* const text, - Length numberOfCharacters ) -{ - if( 0u == numberOfCharacters ) - { - mText.Clear(); - } - else - { - mText.Resize( numberOfCharacters ); - memcpy( mText.Begin(), text, numberOfCharacters * sizeof( Character ) ); - } -} - -Length LogicalModel::GetNumberOfCharacters() const -{ - return mText.Count(); -} - -void LogicalModel::GetText( Character* text, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - memcpy( text, mText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) ); -} - -Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const -{ - return mText[characterIndex]; -} - -void LogicalModel::ReplaceText( CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - const Character* const text, - Length numberOfCharactersToInsert ) -{ -} - -void LogicalModel::SetScripts( const ScriptRun* const scripts, - Length numberOfRuns ) -{ - if( 0u == numberOfRuns ) - { - mScriptRuns.Clear(); - } - else - { - mScriptRuns.Resize( numberOfRuns ); - memcpy( mScriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) ); - } -} - -void LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex, - Length numberOfCharacters, - ScriptRunIndex& firstScriptRun, - Length& numberOfScriptRuns ) const -{ - // Initialize the number of scripts and the index to the first script. - firstScriptRun = 0u; - numberOfScriptRuns = 0; - bool firstScriptFound = false; - - const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters; - - // Traverse the scripts and count those scripts within the range of characters. - for( Vector::ConstIterator it = mScriptRuns.Begin(), - endIt = mScriptRuns.End(); - it != endIt; - ++it ) - { - const ScriptRun& script = *it; - - if( ( script.characterRun.characterIndex + script.characterRun.numberOfCharacters > characterIndex ) && - ( lastCharacterIndex > script.characterRun.characterIndex ) ) - { - firstScriptFound = true; - ++numberOfScriptRuns; - } - else if( lastCharacterIndex <= script.characterRun.characterIndex ) - { - // nothing else to do. - break; - } - - if( !firstScriptFound ) - { - ++firstScriptRun; - } - } -} - -void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - ScriptRunIndex firstScriptRun = 0u; - Length numberOfScriptRuns = 0u; - - GetNumberOfScriptRuns( characterIndex, - numberOfCharacters, - firstScriptRun, - numberOfScriptRuns ); - - memcpy( scriptRuns, mScriptRuns.Begin() + firstScriptRun, numberOfScriptRuns * sizeof( ScriptRun ) ); -} - Script LogicalModel::GetScript( CharacterIndex characterIndex ) const { // If this operation is too slow, consider a binary search. @@ -159,265 +53,6 @@ Script LogicalModel::GetScript( CharacterIndex characterIndex ) const return TextAbstraction::UNKNOWN; } -void LogicalModel::ReplaceScripts( CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - const ScriptRun* const scriptRuns, - Length numberOfCharactersToInsert ) -{ -} - -void LogicalModel::SetFonts( const FontRun* const fonts, - Length numberOfRuns ) -{ - if( 0u == numberOfRuns ) - { - mFontRuns.Clear(); - } - else - { - mFontRuns.Resize( numberOfRuns ); - memcpy( mFontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) ); - } -} - -void LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex, - Length numberOfCharacters, - FontRunIndex& firstFontRun, - Length& numberOfFontRuns ) const -{ - // Initialize the number of fonts and the index to the first font. - firstFontRun = 0u; - numberOfFontRuns = 0; - bool firstFontFound = false; - - const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters; - - // Traverse the fonts and count those fonts within the range of characters. - for( Vector::ConstIterator it = mFontRuns.Begin(), - endIt = mFontRuns.End(); - it != endIt; - ++it ) - { - const FontRun& font = *it; - - if( ( font.characterRun.characterIndex + font.characterRun.numberOfCharacters > characterIndex ) && - ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) ) - { - firstFontFound = true; - ++numberOfFontRuns; - } - else if( lastCharacterIndex <= font.characterRun.characterIndex ) - { - // nothing else to do. - break; - } - - if( !firstFontFound ) - { - ++firstFontRun; - } - } -} - -void LogicalModel::GetFontRuns( FontRun* fontRuns, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - FontRunIndex firstFontRun = 0u; - Length numberOfFontRuns = 0u; - - GetNumberOfFontRuns( characterIndex, - numberOfCharacters, - firstFontRun, - numberOfFontRuns ); - - memcpy( fontRuns, mFontRuns.Begin() + firstFontRun, numberOfFontRuns * sizeof( FontRun ) ); -} - -FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const -{ - for( Length index = 0u, length = mFontRuns.Count(); index < length; ++index ) - { - const FontRun* const fontRun = mFontRuns.Begin() + index; - - if( ( fontRun->characterRun.characterIndex <= characterIndex ) && - ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) ) - { - return fontRun->fontId; - } - } - - return 0u; -} - -void LogicalModel::ReplaceFonts( CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - const FontRun* const fontRuns, - Length numberOfCharactersToInsert ) -{ -} - -void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo, - Length length ) -{ - if( 0u == length ) - { - mLineBreakInfo.Clear(); - } - else - { - mLineBreakInfo.Resize( length ); - memcpy( mLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) ); - } -} - -void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo, - CharacterIndex characterIndex, - Length numberOfItems ) const -{ - memcpy( lineBreakInfo, mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) ); -} - -LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const -{ - return *( mLineBreakInfo.Begin() + characterIndex ); -} - -void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex, - Length numberOfItemsToRemove, - const LineBreakInfo* const lineBreakInfo, - Length numberOfItemsToInsert ) -{ -} - -void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo, - Length length ) -{ - if( 0u == length ) - { - mWordBreakInfo.Clear(); - } - else - { - mWordBreakInfo.Resize( length ); - memcpy( mWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) ); - } -} - -void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo, - CharacterIndex characterIndex, - Length numberOfItems ) const -{ - memcpy( wordBreakInfo, mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) ); -} - -WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const -{ - return *( mWordBreakInfo.Begin() + characterIndex ); -} - -void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex, - Length numberOfItemsToRemove, - const WordBreakInfo* const wordBreakInfo, - Length numberOfItemsToInsert ) -{ -} - -void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo, - Length numberOfRuns ) -{ - if( 0u == numberOfRuns ) - { - mBidirectionalParagraphInfo.Clear(); - } - else - { - mBidirectionalParagraphInfo.Resize( numberOfRuns ); - memcpy( mBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) ); - } -} - -void LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex, - Length numberOfCharacters, - BidirectionalRunIndex& firstBidirectionalRun, - Length& numberOfFontRuns ) const -{ - // Initialize the number of bidi paragraphs and the index to the first paragraph. - firstBidirectionalRun = 0u; - numberOfFontRuns = 0; - bool firstParagraphFound = false; - - // Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters. - for( Vector::ConstIterator it = mBidirectionalParagraphInfo.Begin(), - endIt = mBidirectionalParagraphInfo.End(); - it != endIt; - ++it ) - { - const BidirectionalParagraphInfoRun& bidi = *it; - - if( ( bidi.characterRun.characterIndex + bidi.characterRun.numberOfCharacters > characterIndex ) && - ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) ) - { - firstParagraphFound = true; - ++numberOfFontRuns; - } - - if( !firstParagraphFound ) - { - ++firstBidirectionalRun; - } - } -} - -void LogicalModel::GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - BidirectionalRunIndex firstBidirectionalRun = 0u; - Length numberOfFontRuns = 0u; - - GetNumberOfBidirectionalInfoRuns( characterIndex, - numberOfCharacters, - firstBidirectionalRun, - numberOfFontRuns ); - - memcpy( bidirectionalInfo, mBidirectionalParagraphInfo.Begin() + firstBidirectionalRun, numberOfFontRuns * sizeof( BidirectionalParagraphInfoRun ) ); -} - -void ReplaceBidirectionalInfo( CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - const BidirectionalParagraphInfoRun* const bidirectionalInfo, - Length numberOfCharactersToInsert ) -{ -} - -void LogicalModel::SetCharacterDirections( const CharacterDirection* const directions, - Length numberOfCharacters ) -{ - if( 0u == numberOfCharacters ) - { - mCharacterDirections.Clear(); - } - else - { - mCharacterDirections.Resize( numberOfCharacters ); - memcpy( mCharacterDirections.Begin(), directions, numberOfCharacters * sizeof( CharacterDirection ) ); - } -} - -void LogicalModel::GetCharacterDirections( CharacterDirection* directions, - CharacterIndex characterIndex, - Length numberOfCharacters ) const -{ - if( 0u == mCharacterDirections.Count() ) - { - // Nothing to retrieve if the model has no right to left characters. - return; - } - - memcpy( directions, mCharacterDirections.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterDirection ) ); -} - CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const { if( characterIndex >= mCharacterDirections.Count() ) @@ -597,25 +232,6 @@ void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const } } -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() ) @@ -628,20 +244,6 @@ CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualChar 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() { } diff --git a/dali-toolkit/internal/text/logical-model-impl.h b/dali-toolkit/internal/text/logical-model-impl.h index 73d9230..269247f 100644 --- a/dali-toolkit/internal/text/logical-model-impl.h +++ b/dali-toolkit/internal/text/logical-model-impl.h @@ -62,110 +62,9 @@ public: */ 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. @@ -174,322 +73,9 @@ public: */ 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(). @@ -516,31 +102,6 @@ public: 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. @@ -549,32 +110,6 @@ public: */ 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: /** diff --git a/dali-toolkit/internal/text/multi-language-support-impl.cpp b/dali-toolkit/internal/text/multi-language-support-impl.cpp index 2d2352e..3fa8f6f 100644 --- a/dali-toolkit/internal/text/multi-language-support-impl.cpp +++ b/dali-toolkit/internal/text/multi-language-support-impl.cpp @@ -332,24 +332,17 @@ void MultilanguageSupport::SetScripts( const Vector& text, // 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& text, @@ -593,13 +586,6 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--MultilanguageSupport::ValidateFonts\n" ); } -void MultilanguageSupport::ValidateFonts( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ -} - } // namespace Internal } // namespace Text diff --git a/dali-toolkit/internal/text/multi-language-support-impl.h b/dali-toolkit/internal/text/multi-language-support-impl.h index 0f7e177..ee91aae 100644 --- a/dali-toolkit/internal/text/multi-language-support-impl.h +++ b/dali-toolkit/internal/text/multi-language-support-impl.h @@ -98,27 +98,12 @@ public: Vector& scripts ); /** - * @copydoc Dali::MultilanguageSupport::ReplaceScripts() - */ - void ReplaceScripts( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); - - /** * @copydoc Dali::MultilanguageSupport::ValidateFonts( const Vector& text, const Vector& scripts, Vector& fonts ) */ void ValidateFonts( const Vector& text, const Vector& scripts, Vector& fonts ); - /** - * @copydoc Dali::MultilanguageSupport::ValidateFonts( LogicalModel& model, CharacterIndex characterIndex, Length numberOfCharactersToRemove, Length numberOfCharactersToInsert ) - */ - void ValidateFonts( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); private: Vector mDefaultFontPerScriptCache; ///< Caches the default font for a script. Vector mValidFontsPerScriptCache; ///< Caches valid fonts for a script. diff --git a/dali-toolkit/internal/text/multi-language-support.cpp b/dali-toolkit/internal/text/multi-language-support.cpp index 4416dba..8c28dd5 100644 --- a/dali-toolkit/internal/text/multi-language-support.cpp +++ b/dali-toolkit/internal/text/multi-language-support.cpp @@ -57,17 +57,6 @@ void MultilanguageSupport::SetScripts( const Vector& text, scripts ); } -void MultilanguageSupport::ReplaceScripts( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ - GetImplementation( *this ).ReplaceScripts( model, - characterIndex, - numberOfCharactersToRemove, - numberOfCharactersToInsert ); -} - void MultilanguageSupport::ValidateFonts( const Vector& text, const Vector& scripts, Vector& fonts ) @@ -77,17 +66,6 @@ void MultilanguageSupport::ValidateFonts( const Vector& text, fonts ); } -void MultilanguageSupport::ValidateFonts( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ - GetImplementation( *this ).ValidateFonts( model, - characterIndex, - numberOfCharactersToRemove, - numberOfCharactersToInsert ); -} - } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/multi-language-support.h b/dali-toolkit/internal/text/multi-language-support.h index b70f672..a22676c 100644 --- a/dali-toolkit/internal/text/multi-language-support.h +++ b/dali-toolkit/internal/text/multi-language-support.h @@ -99,24 +99,6 @@ public: Vector& scripts ); /** - * Replaces the scrips of the given range of characters. - * - * @pre The @p model needs to have a text set. - * - * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. - * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. - * - * @param[in,out] model The text's logical model. - * @param[in] characterIndex Index to the first character. - * @param[in] numberOfCharactersToRemove The number of characters removed from the text. - * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. - */ - void ReplaceScripts( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); - - /** * @brief Validates the character's font of the whole text. * * It may update fonts set by application developers. @@ -136,28 +118,6 @@ public: void ValidateFonts( const Vector& text, const Vector& scripts, Vector& fonts ); - - /** - * Validates the character's font of the given range of characters. - * - * It may update fonts set by the mark-up processor. - * It sets default fonts based on the script to those characters without a font set. - * - * @pre The @p model needs to have a text set. - * @pre The @p model needs to have the scripts set. - * - * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. - * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. - * - * @param[in,out] model The text's logical model. - * @param[in] characterIndex Index to the first character. - * @param[in] numberOfCharactersToRemove The number of characters removed from the text. - * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. - */ - void ValidateFonts( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); }; } // namespace Text diff --git a/dali-toolkit/internal/text/segmentation.cpp b/dali-toolkit/internal/text/segmentation.cpp index 3889793..466991b 100644 --- a/dali-toolkit/internal/text/segmentation.cpp +++ b/dali-toolkit/internal/text/segmentation.cpp @@ -84,13 +84,6 @@ void SetLineBreakInfo( const Vector& text, #endif } -void ReplaceLineBreakInfo( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ -} - void SetWordBreakInfo( const Vector& text, Vector& wordBreakInfo ) { @@ -126,13 +119,6 @@ void SetWordBreakInfo( const Vector& text, #endif } -void ReplaceWordBreakInfo( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ -} - } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/segmentation.h b/dali-toolkit/internal/text/segmentation.h index 949b1c9..4bbe5d5 100644 --- a/dali-toolkit/internal/text/segmentation.h +++ b/dali-toolkit/internal/text/segmentation.h @@ -51,24 +51,6 @@ void SetLineBreakInfo( const Vector& text, Vector& lineBreakInfo ); /** - * Replaces line break info. - * - * @pre The @p model needs to have a text set. - * - * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. - * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. - * - * @param[in,out] model The text's logical model. - * @param[in] characterIndex Index to the first character. - * @param[in] numberOfCharactersToRemove The number of characters removed from the text. - * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. - */ -void ReplaceLineBreakInfo( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); - -/** * Sets word break info. * * - 0 is a WORD_BREAK. Text can be broken into a new word. @@ -80,24 +62,6 @@ void ReplaceLineBreakInfo( LogicalModel& model, void SetWordBreakInfo( const Vector& text, Vector& wordBreakInfo ); -/** - * Replaces word break info. - * - * @pre The @p model needs to have a text set. - * - * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. - * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. - * - * @param[in,out] model The text's logical model. - * @param[in] characterIndex Index to the first character. - * @param[in] numberOfCharactersToRemove The number of characters removed from the text. - * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. - */ -void ReplaceWordBreakInfo( LogicalModel& model, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); - } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/shaper.cpp b/dali-toolkit/internal/text/shaper.cpp index c236d28..9ca8e9f 100644 --- a/dali-toolkit/internal/text/shaper.cpp +++ b/dali-toolkit/internal/text/shaper.cpp @@ -225,14 +225,6 @@ void ShapeText( const Vector& text, glyphToCharacterMap.Resize( totalNumberOfGlyphs ); } -void ShapeText( const LogicalModel& logicalModel, - VisualModel& visualModel, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ -} - } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/shaper.h b/dali-toolkit/internal/text/shaper.h index d423cc5..f07cf49 100644 --- a/dali-toolkit/internal/text/shaper.h +++ b/dali-toolkit/internal/text/shaper.h @@ -56,29 +56,6 @@ void ShapeText( const Vector& text, Vector& glyphToCharacterMap, Vector& charactersPerGlyph ); -/** - * Replaces the shape info of the given range of characters. - * - * @pre The @p model needs to have a text set. - * @pre The @p model needs to have the scripts set. - * @pre The @p model needs to have the fonts set. - * @pre The @p model needs to have the bidirectional info set. - * - * If the @p numberOfCharactersToRemove is zero, this operation is like an insert. - * If the @p numberOfCharactersToInsert is zero, this operation is like a remove. - * - * @param[in] logicalModel The text's logical model. - * @param[in,out] visualModel The text's logical model. - * @param[in] characterIndex Index to the first character. - * @param[in] numberOfCharactersToRemove The number of characters removed from the text. - * @param[in] numberOfCharactersToInsert The number of characters inserted in the text. - */ -void ShapeText( const LogicalModel& logicalModel, - VisualModel& visualModel, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ); - } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index f41bddd..7a51b86 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -160,28 +160,38 @@ bool Controller::Impl::ProcessInputEvents() { 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; + } } } } @@ -442,7 +452,7 @@ void Controller::Impl::OnCursorKeyEvent( const Event& event ) } else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode ) { - if( mLogicalModel->GetNumberOfCharacters() > mEventData->mPrimaryCursorPosition ) + if( mLogicalModel->mText.Count() > mEventData->mPrimaryCursorPosition ) { mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition ); } @@ -484,20 +494,6 @@ void Controller::Impl::OnTapEvent( const Event& event ) mEventData->mUpdateCursorPosition = true; mEventData->mScrollAfterUpdatePosition = true; } - else if( mEventData->mSelectionEnabled && - ( 2u == tapCount ) ) - { - // 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; - - RepositionSelectionHandles( xPosition, - yPosition ); - - mEventData->mScrollAfterUpdatePosition = true; - mEventData->mUpdateLeftSelectionPosition = true; - mEventData->mUpdateRightSelectionPosition = true; - } } } @@ -573,7 +569,8 @@ void Controller::Impl::OnHandleEvent( const Event& event ) { ChangeState ( EventData::SELECTION_HANDLE_PANNING ); - if( handleNewPosition != mEventData->mLeftSelectionPosition ) + if( ( handleNewPosition != mEventData->mLeftSelectionPosition ) && + ( handleNewPosition != mEventData->mRightSelectionPosition ) ) { mEventData->mLeftSelectionPosition = handleNewPosition; @@ -587,7 +584,8 @@ void Controller::Impl::OnHandleEvent( const Event& event ) { ChangeState ( EventData::SELECTION_HANDLE_PANNING ); - if( handleNewPosition != mEventData->mRightSelectionPosition ) + if( ( handleNewPosition != mEventData->mRightSelectionPosition ) && + ( handleNewPosition != mEventData->mLeftSelectionPosition ) ) { mEventData->mRightSelectionPosition = handleNewPosition; @@ -629,12 +627,13 @@ void Controller::Impl::OnHandleEvent( const Event& event ) if( handleStopScrolling ) { - mEventData->mUpdateLeftSelectionPosition = mEventData->mLeftSelectionPosition != handlePosition; + mEventData->mUpdateLeftSelectionPosition = ( mEventData->mLeftSelectionPosition != handlePosition ) && ( mEventData->mRightSelectionPosition != handlePosition); mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateLeftSelectionPosition; - mEventData->mLeftSelectionPosition = handlePosition; if( mEventData->mUpdateLeftSelectionPosition ) { + mEventData->mLeftSelectionPosition = handlePosition; + RepositionSelectionHandles( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition ); } @@ -646,12 +645,12 @@ void Controller::Impl::OnHandleEvent( const Event& event ) if( handleStopScrolling ) { - mEventData->mUpdateRightSelectionPosition = mEventData->mRightSelectionPosition != handlePosition; + mEventData->mUpdateRightSelectionPosition = ( mEventData->mRightSelectionPosition != handlePosition ) && ( mEventData->mLeftSelectionPosition != handlePosition ); mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateRightSelectionPosition; - mEventData->mRightSelectionPosition = handlePosition; if( mEventData->mUpdateRightSelectionPosition ) { + mEventData->mRightSelectionPosition = handlePosition; RepositionSelectionHandles( mEventData->mLeftSelectionPosition, mEventData->mRightSelectionPosition ); } @@ -664,55 +663,196 @@ void Controller::Impl::OnHandleEvent( const Event& event ) { const float xSpeed = event.p2.mFloat; const Vector2& actualSize = mVisualModel->GetActualSize(); + const Vector2 currentScrollPosition = mEventData->mScrollPosition; mEventData->mScrollPosition.x += xSpeed; ClampHorizontalScroll( actualSize ); - 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 ) + if( Vector2::ZERO == ( currentScrollPosition - mEventData->mScrollPosition ) ) { - ChangeState( EventData::GRAB_HANDLE_PANNING ); + // Notify the decorator there is no more text to scroll. + // The decorator won't send more scroll events. + mEventData->mDecorator->NotifyEndOfScroll(); } - else if( leftSelectionHandleEvent || rightSelectionHandleEvent ) + else { - // 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. + 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; - ChangeState( EventData::SELECTION_HANDLE_PANNING ); + if( Event::GRAB_HANDLE_EVENT == event.type ) + { + ChangeState( EventData::GRAB_HANDLE_PANNING ); - const Vector2& position = mEventData->mDecorator->GetPosition( leftSelectionHandleEvent ? Text::LEFT_SELECTION_HANDLE : Text::RIGHT_SELECTION_HANDLE ); + Vector2 position = mEventData->mDecorator->GetPosition( GRAB_HANDLE ); - // 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 ); + // Position the grag handle close to either the left or right edge. + position.x = scrollRightDirection ? 0.f : mControlSize.width; - if( leftSelectionHandleEvent ) - { - mEventData->mUpdateLeftSelectionPosition = handlePosition != mEventData->mLeftSelectionPosition; - mEventData->mLeftSelectionPosition = handlePosition; + // 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 + else if( leftSelectionHandleEvent || rightSelectionHandleEvent ) { - mEventData->mUpdateRightSelectionPosition = handlePosition != mEventData->mRightSelectionPosition; - mEventData->mRightSelectionPosition = handlePosition; - } + // 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. - if( mEventData->mUpdateLeftSelectionPosition || mEventData->mUpdateRightSelectionPosition ) - { - RepositionSelectionHandles( mEventData->mLeftSelectionPosition, - mEventData->mRightSelectionPosition ); + 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; } - 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::OnSelectAllEvent() +{ + if( NULL == mEventData ) + { + // Nothing to do if there is no text. + return; + } + + if( mEventData->mSelectionEnabled ) + { + RepositionSelectionHandles( 0u, + mLogicalModel->mText.Count() ); + + mEventData->mScrollAfterUpdatePosition = true; + mEventData->mUpdateLeftSelectionPosition = true; + mEventData->mUpdateRightSelectionPosition = true; + } +} + +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; + } + + //Get start and end position of selection + uint32_t startOfSelectedText = mEventData->mLeftSelectionPosition; + uint32_t lengthOfSelectedText = mEventData->mRightSelectionPosition - startOfSelectedText; + + // Validate the start and end selection points + if( ( startOfSelectedText >= 0 ) && ( ( startOfSelectedText + lengthOfSelectedText ) <= mLogicalModel->mText.Count() ) ) + { + //Get text as a UTF8 string + Vector& utf32Characters = mLogicalModel->mText; + + Utf32ToUtf8( &utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText ); + + if ( deleteAfterRetreival ) // Only delete text if copied successfully + { + // Delete text between handles + Vector& currentText = mLogicalModel->mText; + + Vector::Iterator first = currentText.Begin() + startOfSelectedText; + Vector::Iterator last = first + lengthOfSelectedText; + currentText.Erase( first, last ); + } + mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition; + mEventData->mScrollAfterDelete = true; + mEventData->mDecoratorUpdated = true; + } +} + +bool Controller::Impl::CopyStringToClipboard( std::string& source ) +{ + //Send string to clipboard + return ( mClipboard && mClipboard.SetItem( source ) ); +} + +void Controller::Impl::SendSelectionToClipboard( bool deleteAfterSending ) +{ + std::string selectedText; + RetrieveSelection( selectedText, deleteAfterSending ); + CopyStringToClipboard( selectedText ); + ChangeState( EventData::EDITING ); +} + +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; @@ -727,9 +867,10 @@ void Controller::Impl::RepositionSelectionHandles( CharacterIndex selectionStart // TODO: Multi-line. const Vector& lines = mVisualModel->mLines; - const float height = lines[0].ascender + -lines[0].descender; + const LineRun& firstLine = *lines.Begin(); + const float height = firstLine.ascender + -firstLine.descender; - const bool indicesSwapped = selectionStart > selectionEnd; + const bool indicesSwapped = ( selectionStart > selectionEnd ); if( indicesSwapped ) { std::swap( selectionStart, selectionEnd ); @@ -738,7 +879,7 @@ void Controller::Impl::RepositionSelectionHandles( CharacterIndex selectionStart GlyphIndex glyphStart = *( charactersToGlyphBuffer + selectionStart ); GlyphIndex glyphEnd = *( charactersToGlyphBuffer + ( selectionEnd - 1u ) ) + *( glyphsPerCharacterBuffer + ( selectionEnd - 1u ) ) - 1u; - mEventData->mDecorator->SwapSelectionHandlesEnabled( indicesSwapped ); + mEventData->mDecorator->SwapSelectionHandlesEnabled( firstLine.direction != indicesSwapped ); const Vector2 offset = mEventData->mScrollPosition + mAlignmentOffset; @@ -840,6 +981,28 @@ void Controller::Impl::ChangeState( EventData::State newState ) 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; @@ -879,6 +1042,14 @@ void Controller::Impl::ChangeState( EventData::State newState ) } 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; @@ -1075,7 +1246,7 @@ 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 ) { diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 81125da..880004a 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -19,8 +19,9 @@ */ // EXTERNAL INCLUDES -#include +#include #include +#include // INTERNAL INCLUDES #include @@ -47,7 +48,9 @@ struct Event PAN_EVENT, GRAB_HANDLE_EVENT, LEFT_SELECTION_HANDLE_EVENT, - RIGHT_SELECTION_HANDLE_EVENT + RIGHT_SELECTION_HANDLE_EVENT, + SELECT, + SELECT_ALL }; union Param @@ -99,6 +102,7 @@ struct EventData { INACTIVE, SELECTING, + SELECTION_CHANGED, EDITING, EDITING_WITH_POPUP, GRAB_HANDLE_PANNING, @@ -197,6 +201,7 @@ struct Controller::Impl mFontDefaults( NULL ), mEventData( NULL ), mFontClient(), + mClipboard(), mView(), mLayoutEngine(), mModifyEvents(), @@ -211,6 +216,7 @@ struct Controller::Impl mVisualModel = VisualModel::New(); mFontClient = TextAbstraction::FontClient::Get(); + mClipboard = Clipboard::Get(); mView.SetVisualModel( mVisualModel ); @@ -305,6 +311,12 @@ struct Controller::Impl ClearPreEditFlag(); } + bool IsClipboardEmpty() + { + bool result( mClipboard && mClipboard.NumberOfItems() ); + return !result; // // If NumberOfItems greater than 0, return false + } + void UpdateModel( OperationsMask operationsRequired ); /** @@ -323,6 +335,18 @@ struct Controller::Impl 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 ); @@ -422,6 +446,7 @@ struct Controller::Impl 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 mModifyEvents; ///< Temporary stores the text set until the next relayout. diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 3b36ed3..b55a543 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -47,6 +47,12 @@ const float MAX_FLOAT = std::numeric_limits::max(); const std::string EMPTY_STRING(""); +float ConvertToEven( float value ) +{ + int intValue(static_cast( value )); + return static_cast(intValue % 2 == 0) ? intValue : (intValue + 1); +} + } // namespace namespace Dali @@ -533,6 +539,9 @@ Vector3 Controller::GetNaturalSize() 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; } @@ -590,9 +599,9 @@ bool Controller::Relayout( const Size& size ) if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) ) { bool glyphsRemoved( false ); - if( 0u != mImpl->mVisualModel->GetNumberOfGlyphPositions() ) + 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. @@ -790,7 +799,7 @@ 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 ) { @@ -850,7 +859,7 @@ bool Controller::DoRelayout( const Size& size, if( 0u != bidirectionalInfo.Count() ) { // Get the lines - const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines(); + const Length numberOfLines = mImpl->mVisualModel->mLines.Count(); // Reorder the lines. Vector lineBidirectionalInfoRuns; @@ -1112,9 +1121,6 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) int keyCode = keyEvent.keyCode; const std::string& keyString = keyEvent.keyPressed; - // Hide the grab handle. - mImpl->mEventData->mDecorator->SetHandleActive( GRAB_HANDLE, false ); - // Pre-process to separate modifying events from non-modifying input events. if( Dali::DALI_KEY_ESCAPE == keyCode ) { @@ -1132,29 +1138,7 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) } 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() || - !mImpl->IsPlaceholderAvailable() ) - { - mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED ); - } - else - { - ShowPlaceholderText(); - mImpl->mEventData->mUpdateCursorPosition = true; - } - - textChanged = true; - } + textChanged = BackspaceKeyEvent(); } else { @@ -1164,7 +1148,6 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) mImpl->ClearPreEditFlag(); InsertText( keyString, COMMIT ); - textChanged = true; } @@ -1184,7 +1167,7 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) 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" ) @@ -1195,14 +1178,25 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ Vector 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(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() ); @@ -1218,22 +1212,17 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ 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(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 @@ -1256,7 +1245,7 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ } } - 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 ); @@ -1281,8 +1270,16 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ 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 ); @@ -1299,6 +1296,26 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ } } +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" ); @@ -1312,36 +1329,32 @@ void Controller::TapEvent( unsigned int tapCount, float x, float y ) 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( !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(); } @@ -1362,6 +1375,36 @@ void Controller::PanEvent( Gesture::State state, const Vector2& displacement ) } } +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 ) { targetSize = mImpl->mControlSize; @@ -1420,6 +1463,77 @@ void Controller::DecorationEvent( HandleType handleType, HandleState state, floa } } +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 ); @@ -1491,6 +1605,43 @@ Controller::~Controller() 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() ) diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 66bf3a0..2f83407 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -30,6 +30,7 @@ #include // INTERNAL INCLUDES +#include #include #include #include @@ -67,9 +68,11 @@ enum PlaceholderType * 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 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::ControllerInterface +class Controller : public RefObject, public Decorator::ControllerInterface, public TextSelectionPopupCallbackInterface { public: @@ -135,7 +138,7 @@ 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. @@ -474,17 +477,17 @@ public: // 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. @@ -492,7 +495,7 @@ public: 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. @@ -500,7 +503,13 @@ public: 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. @@ -508,7 +517,7 @@ public: 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. @@ -516,6 +525,17 @@ public: void PanEvent( Gesture::State state, const Vector2& displacement ); /** + * @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. + */ + void SelectEvent( float x, float y, bool selectAll ); + + /** * @brief Event received from IMF manager * * @param[in] imfManager The IMF manager. @@ -539,6 +559,11 @@ public: */ 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: /** @@ -549,6 +574,13 @@ 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(); diff --git a/dali-toolkit/internal/text/text-view.cpp b/dali-toolkit/internal/text/text-view.cpp index 91ecadf..34c3f32 100644 --- a/dali-toolkit/internal/text/text-view.cpp +++ b/dali-toolkit/internal/text/text-view.cpp @@ -67,7 +67,7 @@ Length View::GetGlyphs( GlyphInfo* glyphs, // 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 ) ); @@ -302,8 +302,8 @@ Length View::GetNumberOfGlyphs() const { 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" ); diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp index beeb08b..a354fdc 100644 --- a/dali-toolkit/internal/text/visual-model-impl.cpp +++ b/dali-toolkit/internal/text/visual-model-impl.cpp @@ -36,47 +36,6 @@ VisualModelPtr VisualModel::New() return VisualModelPtr( new VisualModel() ); } -void VisualModel::SetGlyphs( const GlyphInfo* const glyphs, - const CharacterIndex* const characterIndices, - const Length* const 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. @@ -157,11 +116,6 @@ void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters ) } } -Length VisualModel::GetNumberOfGlyphs() const -{ - return mGlyphs.Count(); -} - void VisualModel::GetGlyphs( GlyphInfo* glyphs, GlyphIndex glyphIndex, Length numberOfGlyphs ) const @@ -169,81 +123,6 @@ void VisualModel::GetGlyphs( GlyphInfo* glyphs, 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* const 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 @@ -251,44 +130,6 @@ void VisualModel::GetGlyphPositions( Vector2* glyphPositions, 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, @@ -343,13 +184,6 @@ void VisualModel::GetLinesOfGlyphRange( LineRun* lines, 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. @@ -383,13 +217,6 @@ LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex ) return index; } -void VisualModel::ReplaceLines( GlyphIndex glyphIndex, - Length numberOfGlyphsToRemove, - const LineRun* const lines, - Length numberOfGlyphsToInsert ) -{ -} - void VisualModel::SetNaturalSize( const Vector2& size ) { mNaturalSize = size; diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h index 227019f..f290ba5 100644 --- a/dali-toolkit/internal/text/visual-model-impl.h +++ b/dali-toolkit/internal/text/visual-model-impl.h @@ -63,22 +63,6 @@ public: // 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* const glyphs, - const CharacterIndex* const characterIndices, - const Length* const charactersPerGlyph, - Length numberOfGlyphs ); - - /** * @brief Creates the character to glyph conversion table. * * @pre The glyphs per character table needs to be created first. @@ -95,13 +79,6 @@ public: 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. @@ -113,101 +90,9 @@ public: 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. @@ -221,25 +106,6 @@ public: // 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* const 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. @@ -251,69 +117,9 @@ public: 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. @@ -325,6 +131,7 @@ public: Length numberOfGlyphs, LineIndex& firstLine, Length& numberOfLines ) const; + /** * @brief Retrieves the lines where the given range of glyphs is laid out. * @@ -339,15 +146,6 @@ public: 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. @@ -356,22 +154,6 @@ public: */ 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 /** diff --git a/dali-toolkit/public-api/controls/table-view/table-view.cpp b/dali-toolkit/public-api/controls/table-view/table-view.cpp index c92f36e..126c254 100644 --- a/dali-toolkit/public-api/controls/table-view/table-view.cpp +++ b/dali-toolkit/public-api/controls/table-view/table-view.cpp @@ -29,10 +29,6 @@ namespace Dali 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() { } @@ -137,22 +133,22 @@ Size TableView::GetCellPadding() 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 ) diff --git a/dali-toolkit/public-api/controls/table-view/table-view.h b/dali-toolkit/public-api/controls/table-view/table-view.h index 46e3437..fb59939 100644 --- a/dali-toolkit/public-api/controls/table-view/table-view.h +++ b/dali-toolkit/public-api/controls/table-view/table-view.h @@ -41,6 +41,38 @@ class TableView; * 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 { @@ -64,7 +96,8 @@ public: * "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 * @@ -74,6 +107,7 @@ public: * "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 @@ -90,11 +124,6 @@ public: }; }; - // 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 */ @@ -102,7 +131,8 @@ public: { 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. }; /** @@ -382,11 +412,13 @@ public: 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 ); diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 38e9672..aed0470 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -31,7 +31,7 @@ namespace Toolkit const unsigned int TOOLKIT_MAJOR_VERSION = 1; const unsigned int TOOLKIT_MINOR_VERSION = 0; -const unsigned int TOOLKIT_MICRO_VERSION = 45; +const unsigned int TOOLKIT_MICRO_VERSION = 46; const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 6ba1b7f..c804f61 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali-toolkit Summary: The OpenGLES Canvas Core Library Toolkit -Version: 1.0.45 +Version: 1.0.46 Release: 1 Group: System/Libraries License: Apache-2.0