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)
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/segmentation.h>
+#include <dali-toolkit/internal/text/multi-language-support.h>
+#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions with different scripts.
+// Constructor, destructor and MultilanguageSupport::Get()
+// void MultilanguageSupport::SetScripts( const Vector<Character>& text, const Vector<LineBreakInfo>& lineBreakInfo, Vector<ScriptRun>& scripts );
+// void MultilanguageSupport::ValidateFonts( const Vector<Character>& text, const Vector<ScriptRun>& scripts, Vector<FontRun>& fonts );
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct ScriptsData
+{
+ std::string description; ///< Description of the experiment.
+ std::string text; ///< Input text.
+ Vector<ScriptRun> scriptRuns; ///< Expected script runs.
+};
+
+struct ValidateFontsData
+{
+ std::string description; ///< Description of the experiment.
+ std::string text; ///< Input text.
+};
+
+//////////////////////////////////////////////////////////
+
+bool ScriptsTest( const ScriptsData& data )
+{
+ MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+
+ // 1) Convert to utf32
+ Vector<Character> utf32;
+ utf32.Resize( data.text.size() );
+
+ const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+ data.text.size(),
+ &utf32[0u] );
+ utf32.Resize( numberOfCharacters );
+
+ // 2) Set the line break info.
+ Vector<LineBreakInfo> lineBreakInfo;
+ lineBreakInfo.Resize( numberOfCharacters );
+
+ SetLineBreakInfo( utf32, lineBreakInfo );
+
+ // 3) Set the script info.
+ Vector<ScriptRun> scripts;
+ multilanguageSupport.SetScripts( utf32,
+ lineBreakInfo,
+ scripts );
+
+ // 4) Compare the results.
+
+ if( scripts.Count() != data.scriptRuns.Count() )
+ {
+ tet_infoline("ScriptsTest: different number of scripts.");
+ return false;
+ }
+
+ for( unsigned int index = 0u; index < scripts.Count(); ++index )
+ {
+ const ScriptRun& scriptRun1 = scripts[index];
+ const ScriptRun& scriptRun2 = data.scriptRuns[index];
+
+ if( scriptRun1.characterRun.characterIndex != scriptRun2.characterRun.characterIndex )
+ {
+ tet_infoline("ScriptsTest: different character index.");
+ return false;
+ }
+
+ if( scriptRun1.characterRun.numberOfCharacters != scriptRun2.characterRun.numberOfCharacters )
+ {
+ tet_infoline("ScriptsTest: different number of characters.");
+ return false;
+ }
+
+ if( scriptRun1.script != scriptRun2.script )
+ {
+ tet_infoline("ScriptsTest: different script.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateFontTest( const ValidateFontsData& data )
+{
+ MultilanguageSupport multilanguageSupport = MultilanguageSupport::Get();
+
+ // 1) Convert to utf32
+ Vector<Character> utf32;
+ utf32.Resize( data.text.size() );
+
+ const uint32_t numberOfCharacters = Utf8ToUtf32( reinterpret_cast<const uint8_t* const>( data.text.c_str() ),
+ data.text.size(),
+ &utf32[0u] );
+ utf32.Resize( numberOfCharacters );
+
+ // 2) Set the line break info.
+ Vector<LineBreakInfo> lineBreakInfo;
+ lineBreakInfo.Resize( numberOfCharacters );
+
+ SetLineBreakInfo( utf32, lineBreakInfo );
+
+ // 3) Set the script info.
+ Vector<ScriptRun> scripts;
+ multilanguageSupport.SetScripts( utf32,
+ lineBreakInfo,
+ scripts );
+
+ Vector<FontRun> fonts;
+ // 4) Validate the fonts
+ multilanguageSupport.ValidateFonts( utf32,
+ scripts,
+ fonts );
+
+ return true;
+}
+
+} // namespace
+
+int UtcDaliTextMultiLanguageConstructor(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextMultiLanguageConstructor");
+
+ MultilanguageSupport multilanguageSupport;
+ DALI_TEST_CHECK( !multilanguageSupport );
+
+ MultilanguageSupport multilanguageSupport1 = MultilanguageSupport::Get();
+ DALI_TEST_CHECK( multilanguageSupport1 );
+
+ // To increase coverage.
+ MultilanguageSupport multilanguageSupport2 = MultilanguageSupport::Get();
+ DALI_TEST_CHECK( multilanguageSupport2 );
+
+ DALI_TEST_CHECK( multilanguageSupport1 == multilanguageSupport2 );
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextMultiLanguageSetScripts(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextMultiLanguageSetScripts" );
+
+ // Void text.
+ Vector<ScriptRun> scriptRuns00;
+
+ // Hello world.
+ Vector<ScriptRun> scriptRuns01;
+ ScriptRun scriptRun0100 =
+ {
+ 0u,
+ 11u,
+ TextAbstraction::LATIN
+ };
+ scriptRuns01.PushBack( scriptRun0100 );
+
+ const ScriptsData data[] =
+ {
+ {
+ "void text",
+ "",
+ scriptRuns00,
+ },
+ {
+ "Easy latin script",
+ "Hello world",
+ scriptRuns01,
+ },
+ };
+ const unsigned int numberOfTests = 2u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !ScriptsTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliTextMultiLanguageValidateFonts01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextMultiLanguageValidateFonts");
+
+ const ValidateFontsData data[] =
+ {
+ {
+ "void text",
+ "",
+ },
+ {
+ "Easy latin script",
+ "Hello world",
+ },
+ };
+ const unsigned int numberOfTests = 2u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !ValidateFontTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
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
// JSON with a quit event when the actor is touched
std::string json(
"{"
+ " \"constants\":"
+ " {"
+ " \"ALPHA_FUNCTION\":\"EASE_IN_OUT\""
+ " },"
" \"paths\":"
" {"
" \"path0\":"
" \"actor\": \"greeting\","
" \"property\": \"position\","
" \"value\": [300, 300, -1000],"
- " \"alpha-function\": \"EASE_IN_OUT\","
+ " \"alpha-function\": \"{ALPHA_FUNCTION}\","
" \"relative\": true,"
" \"time-period\": {"
" \"delay\": 0,"
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 );
// JSON with a quit event when the actor is touched
std::string json(
"{"
+ " \"constants\":"
+ " {"
+ " \"TEXT\": \"Touch Me\","
+ " \"NAME\": \"greeting\" "
+ " },"
" \"paths\":"
" {"
" \"path0\":"
" \"disconnect-action\": \"BAKE\","
" \"properties\":"
" [{"
- " \"actor\": \"greeting\","
+ " \"actor\": \"{NAME}\","
" \"property\": \"positioninvalid\","
" \"value\": [300, 300, -1000],"
" \"alpha-function\": \"EASE_IN_OUT\","
" \"disconnect-action\": \"BAKE\","
" \"properties\":"
" [{"
- " \"actor\": \"greeting\","
+ " \"actor\": \"{NAME}\","
" \"property\": \"positioninvalid\","
" \"value\": [300, 300, -1000],"
" \"alpha-function\": \"EGGS_OVER_EASY\","
" \"action\": \"play\","
" \"animation\": \"animate\""
" }]"
+ " },"
+ " {"
+ " \"name\": \"greeting2\","
+ " \"type\": \"TextLabel\","
+ " \"text\": \"Touch me\""
" }]"
"}");
// 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;
"\"stage\":"
"[{"
" \"type\": \"ImageActor\","
+ " \"name\": \"{NAME}\","
" \"size\": [100,100,1],"
" \"parent-origin\": \"TOP_LEFT\","
" \"anchor-point\": \"{ANCHOR}\","
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;
}
// 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"
" \"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"
" }\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;
}
END_TEST;
}
+
+int UtcDaliBuilderCustomPropertyP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ "\"templates\":\n"
+ "{\n"
+ " \"image-tree\": { \n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"image\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"quit\"\n"
+ " }],\n"
+ " \"custom-properties\": {\n"
+ " \"newproperty\": true\n"
+ " },\n"
+ " \"actors\": [\n"
+ " {\n"
+ " \"type\":\"ImageActor\",\n"
+ " \"name\":\"child-image\" \n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ "}\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ ImageActor actor = ImageActor::DownCast( builder.Create( "image-tree" ) );
+ DALI_TEST_CHECK( actor );
+
+ // NB: already applied in create
+ Property::Index index = actor.GetPropertyIndex("newproperty");
+ DALI_TEST_CHECK( Property::INVALID_INDEX != index );
+ Property::Value value = actor.GetProperty(index);
+ DALI_TEST_CHECK( value.Get<bool>() == true );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderShaderEffectP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"stage\": [\n"
+ " {\n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"Image1\",\n"
+ " \"position\": [\n"
+ " 0.40461349487305,\n"
+ " 0.9150390625,\n"
+ " 0.0\n"
+ " ],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"size\": [200, 200, 0],\n"
+ " \"effect\": \"Ripple2D\",\n"
+ " \"image\": {\n"
+ " \"filename\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\",\n"
+ " \"width\": 200,\n"
+ " \"height\": 80,\n"
+ " \"load-policy\": \"IMMEDIATE\",\n"
+ " \"release-policy\": \"NEVER\"\n"
+ " },\n"
+ " \"signals\": [\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"play\",\n"
+ " \"animation\": \"Animation_1\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ],\n"
+ " \"paths\": {},\n"
+ " \"animations\": {\n"
+ " \"Animation_1\": {\n"
+ " \"loop\":true,\n"
+ " \"properties\": [\n"
+ " {\n"
+ " \"actor\": \"Image1\",\n"
+ " \"property\": \"uTime\",\n"
+ " \"value\": 10.0,\n"
+ " \"alpha-function\": \"LINEAR\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 10.0\n"
+ " },\n"
+ " \"gui-builder-timeline-color\": \"#8dc0da\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " },\n"
+ " \"shader-effects\": {\n"
+ " \"Ripple2D\": {\n"
+ " \"program\": {\n"
+ " \"vertexPrefix\": \"\",\n"
+ " \"vertex\": \"void main(void)\\n{\\n gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
+ " \"fragmentPrefix\": \"\",\n"
+ " \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n highp float len = length(pos);\\n highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+ " \"geometry-type\": \"GEOMETRY_TYPE_IMAGE\"\n"
+ " },\n"
+ " \"geometry-hints\": \"HINT_NONE\",\n"
+ " \"grid-density\": 0,\n"
+ " \"loop\": true,\n"
+ " \"uAmplitude\": 0.02,\n"
+ " \"uTime\": 0.0\n"
+ " }\n"
+ " }\n"
+ "}\n"
+
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ ShaderEffect effect = builder.GetShaderEffect("Ripple2D");
+
+ // coverage
+ DALI_TEST_CHECK( effect );
+
+ END_TEST;
+}
+
+
+int UtcDaliBuilderLoadFromStringN(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "asdfsadf dsf asdf asdf {"
+ "\"stage\":"
+ "[{"
+ "\"type\": \"Actor\","
+ "\"size\": [100,100,1],"
+ "\"parent-origin\": \"TOP_LEFT\","
+ "\"anchor-point\": \"TOP_LEFT\","
+ "\"signals\": [{"
+ "\"name\": \"touched\","
+ "\"action\": \"quit\""
+ "}]"
+ "}]"
+ "}"
+ );
+ Builder builder = Builder::New();
+
+ bool assert1 = false;
+
+ try
+ {
+ builder.LoadFromString( json );
+ }
+ catch( Dali::DaliException& e )
+ {
+ DALI_TEST_PRINT_ASSERT( e );
+ DALI_TEST_EQUALS(e.condition, "!\"Cannot parse JSON\"", TEST_LOCATION);
+ assert1 = true;
+ }
+
+ DALI_TEST_CHECK( assert1 );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderShaderEffect2P(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ "\"templates\":\n"
+ "{\n"
+ " \"image-tree\": { \n"
+ " \"type\": \"ImageActor\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"position\": [\n"
+ " 0.40461349487305,\n"
+ " 0.9150390625,\n"
+ " 0.0\n"
+ " ],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"quit\"\n"
+ " }],\n"
+ " \"actors\": [\n"
+ " {\n"
+ " \"type\":\"ImageActor\",\n"
+ " \"name\":\"child-image\" \n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ "},\n"
+ " \"stage\": [\n"
+ " {\n"
+ " \"type\": \"image-tree\",\n"
+ " \"name\": \"Image1\",\n"
+ " \"effect\": \"Ripple2D\",\n"
+ " \"image\": \"offscreen\""
+ " }\n"
+ " ],\n"
+ " \"shader-effects\": {\n"
+ " \"Ripple2D\": {\n"
+ " \"program\": {\n"
+ " \"vertexPrefix\": \"\",\n"
+ " \"vertex\": \"void main(void)\\n{\\n gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
+ " \"fragmentPrefix\": \"\",\n"
+ " \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n highp float len = length(pos);\\n highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+ " \"geometry-type\": \"GEOMETRY_TYPE_IMAGE\"\n"
+ " },\n"
+ " \"geometry-hints\": \"HINT_NONE\",\n"
+ " \"grid-density\": 0,\n"
+ " \"loop\": true,\n"
+ " \"uAmplitude\": 0.02,\n"
+ " \"uTime\": 0.0\n"
+ " }\n"
+ " },\n"
+ " \"frame-buffer-images\": {\n"
+ " \"offscreen\": {\n"
+ " \"type\": \"FrameBufferImage\","
+ " \"pixel-format\":\"RGBA8888\","
+ " \"width\": 400,"
+ " \"height\": 400"
+ " }"
+ " }"
+ "}\n"
+
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+
+ // coverage
+ DALI_TEST_CHECK( true );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderAddActorsP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"arbitarysection\":\n"
+ " [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"actor\",\n"
+ " \"size\": [100,100,1],\n"
+ " \"parent-origin\": \"TOP_LEFT\",\n"
+ " \"anchor-point\": \"TOP_LEFT\",\n"
+ " \"actors\": [{\n"
+ " \"type\": \"Actor\",\n"
+ " \"name\": \"sub-actor\",\n"
+ " \"visible\": false\n"
+ " }],\n"
+ " \"signals\": [{\n"
+ " \"name\": \"touched\",\n"
+ " \"action\": \"hide\",\n"
+ " \"actor\": \"actor\",\n"
+ " \"child-actor\": \"sub-actor\"\n"
+ " }]\n"
+ " }]\n"
+ "}\n"
+ );
+
+ Builder builder = Builder::New();
+ builder.LoadFromString( json );
+ builder.AddActors ( "arbitarysection", Stage::GetCurrent().GetRootLayer() );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Actor actor = Stage::GetCurrent().GetRootLayer().FindChildByName("sub-actor");
+ DALI_TEST_CHECK( actor );
+
+ DALI_TEST_CHECK( !actor.IsVisible() );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderFrameBufferP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"constants\":\n"
+ " {\n"
+ " \"FB_WIDTH\": 200.0,\n"
+ " \"FB_HEIGHT\": 200.0,\n"
+ " \"FB_SIZE\": [200,200],\n"
+ " \"FB_ASPECT_RATIO\": 1\n"
+ " },\n"
+ " \"stage\": [\n"
+ " {\n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"fbOnStage\",\n"
+ " \"position\": [\n"
+ " 0.40461349487305,\n"
+ " 0.9150390625,\n"
+ " 0.0\n"
+ " ],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"size\": [300, 300, 0],\n"
+ " \"image\": \"fb0\",\n"
+ " \"clear-color\": [1,0,0,1]\n"
+ " },\n"
+ " {\n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"Image1\",\n"
+ " \"size\": [200, 200, 0],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"effect\": \"Ripple2D\",\n"
+ " \"image\": {\n"
+ " \"filename\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\",\n"
+ " \"width\": 200,\n"
+ " \"height\": 80,\n"
+ " \"load-policy\": \"IMMEDIATE\",\n"
+ " \"release-policy\": \"NEVER\"\n"
+ " },\n"
+ " \"signals\": [\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"play\",\n"
+ " \"animation\": \"Animation_1\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"type\":\"CameraActor\",\n"
+ " \"name\":\"fbCam\",\n"
+ " \"aspect-ratio\": \"{FB_ASPECT_RATIO}\",\n"
+ " \"projection-mode\": \"PERSPECTIVE_PROJECTION\",\n"
+ " \"field-of-view\": 0.785,\n"
+ " \"invert-y-axis\": true\n"
+ " }\n"
+ " ],\n"
+ " \"frame-buffer-images\":\n"
+ " {\n"
+ " \"fb0\":\n"
+ " {\n"
+ " \"type\": \"FrameBufferImage\",\n"
+ " \"width\": { \"type-cast\":\"float\", \"value\":\"{FB_WIDTH}\" },\n"
+ " \"height\": { \"type-cast\":\"float\", \"value\":\"{FB_HEIGHT}\" }\n"
+ " }\n"
+ " },\n"
+ " \"render-tasks\":\n"
+ " {\n"
+ " \"stage\":\n"
+ " [\n"
+ " {\n"
+ " \"source-actor\": \"fbOnStage\"\n"
+ " },\n"
+ " {\n"
+ " \"source-actor\": \"Image1\",\n"
+ " \"target-frame-buffer\": \"fb0\",\n"
+ " \"viewport-size\":\"{FB_SIZE}\",\n"
+ " \"camera-actor\":\"fbCam\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"paths\": {},\n"
+ " \"animations\": {\n"
+ " \"Animation_1\": {\n"
+ " \"loop\":true,\n"
+ " \"properties\": [\n"
+ " {\n"
+ " \"actor\": \"Image1\",\n"
+ " \"property\": \"uTime\",\n"
+ " \"value\": 10.0,\n"
+ " \"alpha-function\": \"LINEAR\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 10.0\n"
+ " },\n"
+ " \"gui-builder-timeline-color\": \"#8dc0da\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " },\n"
+ " \"shader-effects\": {\n"
+ " \"Ripple2D\": {\n"
+ " \"program\": {\n"
+ " \"vertexPrefix\": \"\",\n"
+ " \"vertex\": \"void main(void)\\n{\\n gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
+ " \"fragmentPrefix\": \"\",\n"
+ " \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n highp float len = length(pos);\\n highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+ " \"geometry-type\": \"GEOMETRY_TYPE_IMAGE\"\n"
+ " },\n"
+ " \"geometry-hints\": \"HINT_NONE\",\n"
+ " \"grid-density\": 0,\n"
+ " \"loop\": true,\n"
+ " \"uAmplitude\": 0.02,\n"
+ " \"uTime\": 0.0\n"
+ " }\n"
+ " }\n"
+ "}\n");
+
+ Builder builder = Builder::New();
+
+ // frame buffer coverage
+ builder.LoadFromString( json );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Dali::FrameBufferImage frameBuffer = builder.GetFrameBufferImage( "fb0" );
+ DALI_TEST_CHECK( frameBuffer );
+
+ Dali::FrameBufferImage frameBuffer2 = builder.GetFrameBufferImage( "fb0" );
+ DALI_TEST_CHECK( frameBuffer2 );
+ DALI_TEST_CHECK( frameBuffer == frameBuffer2 );
+
+ DALI_TEST_CHECK( true );
+
+ END_TEST;
+}
+
+int UtcDaliBuilderPathConstraintsP(void)
+{
+ ToolkitTestApplication application;
+
+ // JSON with a quit event when the actor is touched
+ std::string json(
+ "{\n"
+ " \"constants\":\n"
+ " {\n"
+ " \"FB_WIDTH\": 200.0,\n"
+ " \"FB_HEIGHT\": 200.0,\n"
+ " \"FB_SIZE\": [200,200],\n"
+ " \"FB_ASPECT_RATIO\": 1\n"
+ " },\n"
+ " \"stage\": [\n"
+ " {\n"
+ " \"type\": \"ImageActor\",\n"
+ " \"name\": \"Image1\",\n"
+ " \"size\": [200, 200, 0],\n"
+ " \"parent-origin\": [0.5, 0.5, 0.5],\n"
+ " \"effect\": \"Ripple2D\",\n"
+ " \"image\": {\n"
+ " \"filename\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\",\n"
+ " \"width\": 200,\n"
+ " \"height\": 80,\n"
+ " \"load-policy\": \"IMMEDIATE\",\n"
+ " \"release-policy\": \"NEVER\"\n"
+ " },\n"
+ " \"signals\": [\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"play\",\n"
+ " \"animation\": \"path-animation\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"applyConstraint\",\n"
+ " \"constrainer\": \"constrainer0\",\n"
+ " \"properties\":\n"
+ " [\n"
+ " {\n"
+ " \"source\": \"Image1\",\n"
+ " \"sourceProperty\": \"position-x\",\n"
+ " \"target\": \"Image1\",\n"
+ " \"targetProperty\": \"color-red\",\n"
+ " \"range\": [-300,300]\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"on-stage\",\n"
+ " \"action\": \"applyConstraint\",\n"
+ " \"constrainer\": \"constrainer1\",\n"
+ " \"properties\":\n"
+ " [\n"
+ " {\n"
+ " \"source\": \"Image1\",\n"
+ " \"sourceProperty\": \"position-x\",\n"
+ " \"target\": \"Image1\",\n"
+ " \"targetProperty\": \"color-blue\",\n"
+ " \"range\": [-300,300]\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ],\n"
+ " \"paths\":\n"
+ " {\n"
+ " \"path0\":\n"
+ " {\n"
+ " \"points\":[ [-150, -50, 0], [0.0,70.0,0.0], [190.0,-150.0,0.0] ],\n"
+ " \"curvature\":0.35\n"
+ " }\n"
+ " },\n"
+ " \"constrainers\":\n"
+ " {\n"
+ " \"constrainer0\":\n"
+ " {\n"
+ " \"type\": \"PathConstrainer\",\n"
+ " \"points\": [ [0, 0, 0], [0,0,0], [0,0,0] ],\n"
+ " \"control-points\": [ [0, 0, 0], [0,0,0], [0,0,0] ]\n"
+ " },\n"
+ " \"constrainer1\":\n"
+ " {\n"
+ " \"type\": \"LinearConstrainer\",\n"
+ " \"value\": [ 0, 0, 0 ]\n"
+ " }\n"
+ " },\n"
+ " \"animations\": {\n"
+ " \"path-animation\": {\n"
+ " \"duration\": 3.0,\n"
+ " \"properties\":\n"
+ " [{\n"
+ " \"actor\": \"Image1\",\n"
+ " \"path\":\"path0\",\n"
+ " \"forward\":[1,0,0],\n"
+ " \"alpha-function\": \"EASE_IN_OUT\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 3\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"actor\": \"Image1\",\n"
+ " \"property\": \"uTime\",\n"
+ " \"value\": 10.0,\n"
+ " \"alpha-function\": \"LINEAR\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 10.0\n"
+ " },\n"
+ " \"gui-builder-timeline-color\": \"#8dc0da\"\n"
+ " }]\n"
+ " },\n"
+ " \"Animation_1\": {\n"
+ " \"loop\":true,\n"
+ " \"properties\": [\n"
+ " {\n"
+ " \"actor\": \"Image1\",\n"
+ " \"property\": \"uTime\",\n"
+ " \"value\": 10.0,\n"
+ " \"alpha-function\": \"LINEAR\",\n"
+ " \"time-period\": {\n"
+ " \"delay\": 0,\n"
+ " \"duration\": 10.0\n"
+ " },\n"
+ " \"gui-builder-timeline-color\": \"#8dc0da\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " },\n"
+ " \"shader-effects\": {\n"
+ " \"Ripple2D\": {\n"
+ " \"program\": {\n"
+ " \"vertexPrefix\": \"\",\n"
+ " \"vertex\": \"void main(void)\\n{\\n gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
+ " \"fragmentPrefix\": \"\",\n"
+ " \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n highp float len = length(pos);\\n highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+ " \"geometry-type\": \"GEOMETRY_TYPE_IMAGE\"\n"
+ " },\n"
+ " \"geometry-hints\": \"HINT_NONE\",\n"
+ " \"grid-density\": 0,\n"
+ " \"loop\": true,\n"
+ " \"uAmplitude\": 0.02,\n"
+ " \"uTime\": 0.0\n"
+ " }\n"
+ " }\n"
+ "}\n");
+
+ Builder builder = Builder::New();
+
+ // frame buffer coverage
+ builder.LoadFromString( json );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Dali::Path path = builder.GetPath( "path0" );
+ DALI_TEST_CHECK( path );
+
+ Dali::Path path2 = builder.GetPath( "path0" );
+ DALI_TEST_CHECK( path2 );
+ DALI_TEST_CHECK( path == path2 );
+
+ Dali::PathConstrainer constrainer0 = builder.GetPathConstrainer( "constrainer0" );
+ DALI_TEST_CHECK( constrainer0 );
+
+ Dali::PathConstrainer constrainer0_2 = builder.GetPathConstrainer( "constrainer0" );
+ DALI_TEST_CHECK( constrainer0_2 );
+ DALI_TEST_CHECK( constrainer0 == constrainer0_2 );
+
+ Dali::LinearConstrainer constrainer1 = builder.GetLinearConstrainer( "constrainer1" );
+ DALI_TEST_CHECK( constrainer1 );
+
+ Dali::LinearConstrainer constrainer1_2 = builder.GetLinearConstrainer( "constrainer1" );
+ DALI_TEST_CHECK( constrainer1 == constrainer1_2 );
+
+ END_TEST;
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <sstream>
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/magnifier/magnifier.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void dali_magnifier_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void dali_magnifier_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+int UtcDaliMagnifierNew(void)
+{
+ ToolkitTestApplication application;
+
+ Magnifier magnifier;
+ DALI_TEST_CHECK( !magnifier );
+
+ magnifier = Magnifier::New();
+ DALI_TEST_CHECK( magnifier );
+
+ Stage::GetCurrent().Add( magnifier );
+
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierCopyAndAssignment(void)
+{
+ ToolkitTestApplication application;
+
+ Magnifier view = Magnifier::New();
+ DALI_TEST_CHECK( view );
+
+ Magnifier copy( view );
+ DALI_TEST_CHECK( copy == view );
+
+ Magnifier assign;
+ DALI_TEST_CHECK( !assign );
+ assign = view;
+ DALI_TEST_CHECK( assign == view );
+
+ // Self assignment
+ assign = assign;
+ DALI_TEST_CHECK( assign );
+ DALI_TEST_CHECK( assign == view );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierDownCast(void)
+{
+ ToolkitTestApplication application;
+
+ BaseHandle view = Magnifier::New();
+ DALI_TEST_CHECK( Magnifier::DownCast( view ) );
+
+ BaseHandle empty;
+ DALI_TEST_CHECK( ! Magnifier::DownCast( empty ) );
+
+ BaseHandle another = Actor::New();
+ DALI_TEST_CHECK( ! Magnifier::DownCast( another ) );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierTypeRegistry(void)
+{
+ ToolkitTestApplication application;
+
+ TypeRegistry typeRegistry = TypeRegistry::Get();
+ DALI_TEST_CHECK( typeRegistry );
+
+ TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Magnifier" );
+ DALI_TEST_CHECK( typeInfo );
+
+ BaseHandle handle = typeInfo.CreateInstance();
+ DALI_TEST_CHECK( handle );
+
+ Magnifier view = Magnifier::DownCast( handle );
+ DALI_TEST_CHECK( view );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierSetSourceActorP(void)
+{
+ ToolkitTestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+
+ Magnifier view = Magnifier::New();
+ stage.Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ RenderTaskList renderTaskList = stage.GetRenderTaskList();
+ DALI_TEST_CHECK( renderTaskList.GetTaskCount() > 1 );
+
+ Actor actor = Actor::New();
+ stage.Add( actor );
+ DALI_TEST_CHECK( stage.GetRenderTaskList().GetTask( 1 ).GetSourceActor() != actor );
+
+ view.SetSourceActor( actor );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( stage.GetRenderTaskList().GetTask( 1 ).GetSourceActor(), actor, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierSetSourceActorN(void)
+{
+ ToolkitTestApplication application;
+
+ Magnifier view;
+
+ try
+ {
+ view.SetSourceActor( Actor::New() );
+ DALI_TEST_CHECK( false ); // should not get here
+ }
+ catch( ... )
+ {
+ DALI_TEST_CHECK( true );
+ }
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierFrameVisibility(void)
+{
+ ToolkitTestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+
+ Magnifier view = Magnifier::New();
+ stage.Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), true, TEST_LOCATION );
+
+ view.SetProperty( Magnifier::Property::FRAME_VISIBILITY, false );
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), false, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), false, TEST_LOCATION );
+
+ view.SetProperty( Magnifier::Property::FRAME_VISIBILITY, true );
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::FRAME_VISIBILITY ).Get< bool >(), true, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierMagnificationFactor(void)
+{
+ ToolkitTestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+
+ Magnifier view = Magnifier::New();
+ stage.Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ float magnificationFactor( 200.0f );
+
+ DALI_TEST_CHECK( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >() != magnificationFactor );
+
+ view.SetProperty( Magnifier::Property::MAGNIFICATION_FACTOR, magnificationFactor );
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >(), magnificationFactor, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >(), magnificationFactor, TEST_LOCATION );
+
+ view.SetProperty( Magnifier::Property::MAGNIFICATION_FACTOR, 1.0f );
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >(), 1.0f, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::MAGNIFICATION_FACTOR ).Get< float >(), 1.0f, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierSourcePosition(void)
+{
+ ToolkitTestApplication application;
+
+ Stage stage = Stage::GetCurrent();
+
+ Magnifier view = Magnifier::New();
+ stage.Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ Vector3 position( 100.0f, 200.0f, 300.0f );
+
+ DALI_TEST_CHECK( view.GetProperty( Magnifier::Property::SOURCE_POSITION ).Get< Vector3 >() != position );
+
+ view.SetProperty( Magnifier::Property::SOURCE_POSITION, position );
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::SOURCE_POSITION ).Get< Vector3 >(), position, TEST_LOCATION );
+
+ view.SetProperty( Magnifier::Property::SOURCE_POSITION, Vector3::ONE );
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_EQUALS( view.GetProperty( Magnifier::Property::SOURCE_POSITION ).Get< Vector3 >(), Vector3::ONE, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliMagnifierOnSizeSet(void)
+{
+ ToolkitTestApplication application;
+
+ Magnifier view = Magnifier::New();
+
+ Stage::GetCurrent().Add( view );
+
+ application.SendNotification();
+ application.Render();
+
+ Vector3 size( 200.0f, 300.0f, 200.0f );
+ view.SetSize( size );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( view.GetCurrentSize(), size, TEST_LOCATION );
+
+ END_TEST;
+}
// Create a 10x10 table-view
TableView tableView = TableView::New(10,10);
- Constraint constraint = Constraint::New<Vector3>( tableView, Actor::Property::SIZE, Constraint100() );
- constraint.Apply();
+ Stage::GetCurrent().Add( tableView );
+ tableView.SetSize( Dali::Vector2( 100.0f, 100.0f ) );
+
DALI_TEST_CHECK( tableView );
// Create a child actor with the custom properties
Actor child1 = Actor::New();
- child1.RegisterProperty( TableView::CELL_INDICES_PROPERTY_NAME, Vector2( 3, 4 ) );
+ child1.RegisterProperty( "cell-index", Vector2( 3, 4 ), Property::READ_WRITE );
tableView.Add( child1 );
// Check for actors at actual positions.
DALI_TEST_CHECK( tableView.GetChildAt(TableView::CellPosition(3,4)) == child1);
Actor child2 = Actor::New();
float rowSpan = 3.f;
float columnSpan = 2.f;
- child2.RegisterProperty( TableView::CELL_INDICES_PROPERTY_NAME, Vector2( 6, 1 ) );
- child2.RegisterProperty( TableView::ROW_SPAN_PROPERTY_NAME, rowSpan );
- child2.RegisterProperty( TableView::COLUMN_SPAN_PROPERTY_NAME, columnSpan );
+ child2.RegisterProperty( "cell-index", Vector2( 6, 1 ), Property::READ_WRITE );
+ child2.RegisterProperty( "row-span", rowSpan, Property::READ_WRITE );
+ child2.RegisterProperty( "column-span", columnSpan, Property::READ_WRITE );
tableView.Add( child2 );
// Check for actors at actual positions.
for( int i=0; i<rowSpan; i++ )
}
}
+ // Create a third child actor with the cell alignment properties
+ Actor child3 = Actor::New();
+ child3.SetSize( 5.f,5.f );
+ child3.RegisterProperty( "cell-horizontal-alignment", "center", Property::READ_WRITE );
+ child3.RegisterProperty( "cell-vertical-alignment", "bottom", Property::READ_WRITE );
+ tableView.Add( child3 );
+
+ // store the actor in the first available cell
+ DALI_TEST_CHECK( tableView.GetChildAt(TableView::CellPosition(0,0)) == child3)
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( child3.GetCurrentAnchorPoint(), AnchorPoint::TOP_LEFT, TEST_LOCATION );
+ DALI_TEST_EQUALS( child3.GetCurrentParentOrigin(), ParentOrigin::TOP_LEFT, TEST_LOCATION );
+ DALI_TEST_EQUALS( child3.GetCurrentPosition(), Vector3(2.5f, 5.0f, 0.0f), TEST_LOCATION );
+
END_TEST;
}
#include <iostream>
#include <stdlib.h>
#include <dali/integration-api/events/key-event-integ.h>
+#include <dali/integration-api/events/tap-gesture-event.h>
+#include <dali/devel-api/actors/mesh-actor.h>
#include <dali-toolkit-test-suite-utils.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/styling/style-manager.h>
namespace
{
-const char* const PROPERTY_NAME_RENDERING_BACKEND = "rendering-backend";
-const char* const PROPERTY_NAME_PLACEHOLDER_TEXT = "placeholder-text";
-const char* const PROPERTY_NAME_TEXT = "text";
-const char* const PROPERTY_NAME_FONT_FAMILY = "font-family";
-const char* const PROPERTY_NAME_FONT_STYLE = "font-style";
-const char* const PROPERTY_NAME_POINT_SIZE = "point-size";
-const char* const PROPERTY_NAME_EXCEED_POLICY = "exceed-policy";
-const char* const PROPERTY_NAME_PRIMARY_CURSOR_COLOR = "primary-cursor-color";
-const char* const PROPERTY_NAME_SECONDARY_CURSOR_COLOR = "secondary-cursor-color";
-const char* const PROPERTY_NAME_ENABLE_CURSOR_BLINK = "enable-cursor-blink";
-const char* const PROPERTY_NAME_CURSOR_BLINK_INTERVAL = "cursor-blink-interval";
-const char* const PROPERTY_NAME_CURSOR_BLINK_DURATION = "cursor-blink-duration";
-const char* const PROPERTY_NAME_GRAB_HANDLE_IMAGE = "grab-handle-image";
-const char* const PROPERTY_NAME_DECORATION_BOUNDING_BOX = "decoration-bounding-box";
-const char* const PROPERTY_NAME_HORIZONTAL_ALIGNMENT = "horizontal-alignment";
-const char* const PROPERTY_NAME_VERTICAL_ALIGNMENT = "vertical-alignment";
+const char* const PROPERTY_NAME_RENDERING_BACKEND = "rendering-backend";
+const char* const PROPERTY_NAME_TEXT = "text";
+const char* const PROPERTY_NAME_PLACEHOLDER_TEXT = "placeholder-text";
+const char* const PROPERTY_NAME_PLACEHOLDER_TEXT_FOCUSED = "placeholder-text-focused";
+const char* const PROPERTY_NAME_FONT_FAMILY = "font-family";
+const char* const PROPERTY_NAME_FONT_STYLE = "font-style";
+const char* const PROPERTY_NAME_POINT_SIZE = "point-size";
+const char* const PROPERTY_NAME_MAX_LENGTH = "max-length";
+const char* const PROPERTY_NAME_EXCEED_POLICY = "exceed-policy";
+const char* const PROPERTY_NAME_HORIZONTAL_ALIGNMENT = "horizontal-alignment";
+const char* const PROPERTY_NAME_VERTICAL_ALIGNMENT = "vertical-alignment";
+const char* const PROPERTY_NAME_TEXT_COLOR = "text-color";
+const char* const PROPERTY_NAME_PLACEHOLDER_TEXT_COLOR = "placeholder-text-color";
+const char* const PROPERTY_NAME_SHADOW_OFFSET = "shadow-offset";
+const char* const PROPERTY_NAME_SHADOW_COLOR = "shadow-color";
+const char* const PROPERTY_NAME_PRIMARY_CURSOR_COLOR = "primary-cursor-color";
+const char* const PROPERTY_NAME_SECONDARY_CURSOR_COLOR = "secondary-cursor-color";
+const char* const PROPERTY_NAME_ENABLE_CURSOR_BLINK = "enable-cursor-blink";
+const char* const PROPERTY_NAME_CURSOR_BLINK_INTERVAL = "cursor-blink-interval";
+const char* const PROPERTY_NAME_CURSOR_BLINK_DURATION = "cursor-blink-duration";
+const char* const PROPERTY_NAME_GRAB_HANDLE_IMAGE = "grab-handle-image";
+const char* const PROPERTY_NAME_GRAB_HANDLE_PRESSED_IMAGE = "grab-handle-pressed-image";
+const char* const PROPERTY_NAME_SCROLL_THRESHOLD = "scroll-threshold";
+const char* const PROPERTY_NAME_SCROLL_SPEED = "scroll-speed";
+const char* const PROPERTY_NAME_SELECTION_HANDLE_IMAGE_LEFT = "selection-handle-image-left";
+const char* const PROPERTY_NAME_SELECTION_HANDLE_IMAGE_RIGHT = "selection-handle-image-right";
+const char* const PROPERTY_NAME_SELECTION_HANDLE_PRESSED_IMAGE_LEFT = "selection-handle-pressed-image-left";
+const char* const PROPERTY_NAME_SELECTION_HANDLE_PRESSED_IMAGE_RIGHT = "selection-handle-pressed-image-right";
+const char* const PROPERTY_NAME_SELECTION_HIGHLIGHT_COLOR = "selection-highlight-color";
+const char* const PROPERTY_NAME_DECORATION_BOUNDING_BOX = "decoration-bounding-box";
+const char* const PROPERTY_NAME_INPUT_METHOD_SETTINGS = "input-method-settings";
+
+const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
+
+const Vector4 PLACEHOLDER_TEXT_COLOR( 0.8f, 0.8f, 0.8f, 0.8f );
+const Dali::Vector4 LIGHT_BLUE( (0xb2 / 255.0f), (0xeb / 255.0f), (0xf2 / 255.0f), 0.5f ); // The text highlight color.
+
+const unsigned int CURSOR_BLINK_INTERVAL = 500u; // Cursor blink interval
+const float TO_MILLISECONDS = 1000.f;
+const float TO_SECONDS = 1.f / TO_MILLISECONDS;
+
+const float SCROLL_THRESHOLD = 10.f;
+const float SCROLL_SPEED = 300.f;
static bool gTextChangedCallBackCalled;
static bool gMaxCharactersCallBackCalled;
gMaxCharactersCallBackCalled = true;
}
+// Generate a TapGestureEvent to send to Core.
+Integration::TapGestureEvent GenerateTap(
+ Gesture::State state,
+ unsigned int numberOfTaps,
+ unsigned int numberOfTouches,
+ Vector2 point)
+{
+ Integration::TapGestureEvent tap( state );
+
+ tap.numberOfTaps = numberOfTaps;
+ tap.numberOfTouches = numberOfTouches;
+ tap.point = point;
+
+ return tap;
+}
+
+// Generate a KeyEvent to send to Core.
+Integration::KeyEvent GenerateKey( const std::string& keyName,
+ const std::string& keyString,
+ int keyCode,
+ int keyModifier,
+ unsigned long timeStamp,
+ const Integration::KeyEvent::State& keyState )
+{
+ return Integration::KeyEvent( keyName,
+ keyString,
+ keyCode,
+ keyModifier,
+ timeStamp,
+ keyState );
+}
+
} // namespace
int UtcDaliToolkitTextFieldConstructorP(void)
// Check Property Indices are correct
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_RENDERING_BACKEND ) == TextField::Property::RENDERING_BACKEND );
- DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER_TEXT ) == TextField::Property::PLACEHOLDER_TEXT );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_TEXT ) == TextField::Property::TEXT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER_TEXT ) == TextField::Property::PLACEHOLDER_TEXT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER_TEXT_FOCUSED ) == TextField::Property::PLACEHOLDER_TEXT_FOCUSED );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_FONT_FAMILY ) == TextField::Property::FONT_FAMILY );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_FONT_STYLE ) == TextField::Property::FONT_STYLE );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_POINT_SIZE ) == TextField::Property::POINT_SIZE );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_MAX_LENGTH ) == TextField::Property::MAX_LENGTH );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_EXCEED_POLICY ) == TextField::Property::EXCEED_POLICY );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_HORIZONTAL_ALIGNMENT ) == TextField::Property::HORIZONTAL_ALIGNMENT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_VERTICAL_ALIGNMENT ) == TextField::Property::VERTICAL_ALIGNMENT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_TEXT_COLOR ) == TextField::Property::TEXT_COLOR );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PLACEHOLDER_TEXT_COLOR ) == TextField::Property::PLACEHOLDER_TEXT_COLOR );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SHADOW_OFFSET ) == TextField::Property::SHADOW_OFFSET );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SHADOW_COLOR ) == TextField::Property::SHADOW_COLOR );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_PRIMARY_CURSOR_COLOR ) == TextField::Property::PRIMARY_CURSOR_COLOR );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SECONDARY_CURSOR_COLOR ) == TextField::Property::SECONDARY_CURSOR_COLOR );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_ENABLE_CURSOR_BLINK ) == TextField::Property::ENABLE_CURSOR_BLINK );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_CURSOR_BLINK_INTERVAL ) == TextField::Property::CURSOR_BLINK_INTERVAL );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_CURSOR_BLINK_DURATION ) == TextField::Property::CURSOR_BLINK_DURATION );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_GRAB_HANDLE_IMAGE ) == TextField::Property::GRAB_HANDLE_IMAGE );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_GRAB_HANDLE_PRESSED_IMAGE ) == TextField::Property::GRAB_HANDLE_PRESSED_IMAGE );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SCROLL_THRESHOLD ) == TextField::Property::SCROLL_THRESHOLD );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SCROLL_SPEED ) == TextField::Property::SCROLL_SPEED );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HANDLE_IMAGE_LEFT ) == TextField::Property::SELECTION_HANDLE_IMAGE_LEFT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HANDLE_IMAGE_RIGHT ) == TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HANDLE_PRESSED_IMAGE_LEFT ) == TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HANDLE_PRESSED_IMAGE_RIGHT ) == TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_SELECTION_HIGHLIGHT_COLOR ) == TextField::Property::SELECTION_HIGHLIGHT_COLOR );
DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_DECORATION_BOUNDING_BOX ) == TextField::Property::DECORATION_BOUNDING_BOX );
- DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_HORIZONTAL_ALIGNMENT ) == TextField::Property::HORIZONTAL_ALIGNMENT );
- DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_VERTICAL_ALIGNMENT ) == TextField::Property::VERTICAL_ALIGNMENT );
+ DALI_TEST_CHECK( field.GetPropertyIndex( PROPERTY_NAME_INPUT_METHOD_SETTINGS ) == TextField::Property::INPUT_METHOD_SETTINGS );
END_TEST;
}
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- // Check exceed policy
- field.SetProperty( TextField::Property::EXCEED_POLICY, TextField::EXCEED_POLICY_CLIP );
+ // Check defaults.
+ DALI_TEST_EQUALS( field.GetProperty<unsigned int>( TextField::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::PLACEHOLDER_TEXT ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::PLACEHOLDER_TEXT_FOCUSED ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::FONT_FAMILY ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::FONT_STYLE ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::POINT_SIZE ), 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<int>( TextField::Property::MAX_LENGTH ), 50u, TEST_LOCATION );
DALI_TEST_EQUALS( field.GetProperty<int>( TextField::Property::EXCEED_POLICY ), TextField::EXCEED_POLICY_CLIP, TEST_LOCATION );
-
- // Check cursor properties
- field.SetProperty( TextField::Property::ENABLE_CURSOR_BLINK, true );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector2>( TextField::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PLACEHOLDER_TEXT_COLOR ), PLACEHOLDER_TEXT_COLOR, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLACK, TEST_LOCATION );
DALI_TEST_EQUALS( field.GetProperty<bool>( TextField::Property::ENABLE_CURSOR_BLINK ), true, TEST_LOCATION );
- field.SetProperty( TextField::Property::PRIMARY_CURSOR_COLOR, Color::RED );
- DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::RED, TEST_LOCATION );
- field.SetProperty( TextField::Property::SECONDARY_CURSOR_COLOR, Color::BLUE );
- DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLUE, TEST_LOCATION );
- field.SetProperty( TextField::Property::CURSOR_BLINK_DURATION, 10.0f );
- DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_DURATION ), 10.0f, TEST_LOCATION );
-
- // Blink interval
- field.SetProperty( TextField::Property::CURSOR_BLINK_INTERVAL, 1.0f );
- DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_INTERVAL ), 1.0f, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_INTERVAL ), CURSOR_BLINK_INTERVAL * TO_SECONDS, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_DURATION ), 0.f, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::SCROLL_THRESHOLD ), SCROLL_THRESHOLD, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::SCROLL_SPEED ), SCROLL_SPEED, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SELECTION_HIGHLIGHT_COLOR ), LIGHT_BLUE, TEST_LOCATION );
- // Decoration bounding box
- field.SetProperty( TextField::Property::DECORATION_BOUNDING_BOX, Rect<int>( 0, 0, 1, 1 ) );
- DALI_TEST_EQUALS( field.GetProperty<Rect <int > >( TextField::Property::DECORATION_BOUNDING_BOX ), Rect<int>( 0, 0, 1, 1 ), TEST_LOCATION );
-
- // Check that the Alignment properties can be correctly set
- field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "BEGIN" );
- DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION );
- field.SetProperty( TextField::Property::VERTICAL_ALIGNMENT, "CENTER" );
- DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::VERTICAL_ALIGNMENT ), "CENTER", TEST_LOCATION );
+ // Check the render backend property.
+ field.SetProperty( TextField::Property::RENDERING_BACKEND, Text::RENDERING_BASIC );
+ DALI_TEST_EQUALS( field.GetProperty<unsigned int>( TextField::Property::RENDERING_BACKEND ), Text::RENDERING_BASIC, TEST_LOCATION );
- // Set text
+ // Check text property.
field.SetProperty( TextField::Property::TEXT, "Setting Text" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string("Setting Text"), TEST_LOCATION );
- // 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<std::string>( 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<std::string>( 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<std::string>( TextField::Property::FONT_FAMILY ), std::string("Setting font family"), TEST_LOCATION );
+ field.SetProperty( TextField::Property::FONT_STYLE, "Setting font style" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::FONT_STYLE ), std::string("Setting font style"), TEST_LOCATION );
+ field.SetProperty( TextField::Property::POINT_SIZE, 10.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::POINT_SIZE ), 10.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
// Check that the MAX_LENGTH property can be correctly set
const int maxNumberOfCharacters = 20;
field.SetProperty( TextField::Property::MAX_LENGTH, maxNumberOfCharacters );
DALI_TEST_EQUALS( field.GetProperty<int>( TextField::Property::MAX_LENGTH ), maxNumberOfCharacters, TEST_LOCATION );
+ // 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<std::string>( TextField::Property::HORIZONTAL_ALIGNMENT ), "END", TEST_LOCATION );
+ field.SetProperty( TextField::Property::VERTICAL_ALIGNMENT, "CENTER" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::VERTICAL_ALIGNMENT ), "CENTER", TEST_LOCATION );
+
+ // Check text's color property
+ field.SetProperty( TextField::Property::TEXT_COLOR, Color::WHITE );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::TEXT_COLOR ), Color::WHITE, TEST_LOCATION );
+
+ // Check placeholder text's color property.
+ field.SetProperty( TextField::Property::PLACEHOLDER_TEXT_COLOR, Color::RED );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PLACEHOLDER_TEXT_COLOR ), Color::RED, TEST_LOCATION );
+
+ // Check shadow properties.
+ field.SetProperty( TextField::Property::SHADOW_OFFSET, Vector2( 1.f, 1.f ) );
+ DALI_TEST_EQUALS( field.GetProperty<Vector2>( TextField::Property::SHADOW_OFFSET ), Vector2( 1.f, 1.f ), TEST_LOCATION );
+ field.SetProperty( TextField::Property::SHADOW_COLOR, Color::GREEN );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SHADOW_COLOR ), Color::GREEN, TEST_LOCATION );
+
+ // Check cursor properties
+ field.SetProperty( TextField::Property::PRIMARY_CURSOR_COLOR, Color::RED );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::PRIMARY_CURSOR_COLOR ), Color::RED, TEST_LOCATION );
+ field.SetProperty( TextField::Property::SECONDARY_CURSOR_COLOR, Color::BLUE );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SECONDARY_CURSOR_COLOR ), Color::BLUE, TEST_LOCATION );
+
+ field.SetProperty( TextField::Property::ENABLE_CURSOR_BLINK, false );
+ DALI_TEST_EQUALS( field.GetProperty<bool>( TextField::Property::ENABLE_CURSOR_BLINK ), false, TEST_LOCATION );
+ field.SetProperty( TextField::Property::CURSOR_BLINK_INTERVAL, 1.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_INTERVAL ), 1.f, TEST_LOCATION );
+ field.SetProperty( TextField::Property::CURSOR_BLINK_DURATION, 10.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::CURSOR_BLINK_DURATION ), 10.f, TEST_LOCATION );
+
+ // Check scroll properties.
+ field.SetProperty( TextField::Property::SCROLL_THRESHOLD, 1.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::SCROLL_THRESHOLD ), 1.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ field.SetProperty( TextField::Property::SCROLL_SPEED, 100.f );
+ DALI_TEST_EQUALS( field.GetProperty<float>( TextField::Property::SCROLL_SPEED ), 100.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ // Check handle images
+ field.SetProperty( TextField::Property::GRAB_HANDLE_IMAGE, "image1" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::GRAB_HANDLE_IMAGE ), "image1", TEST_LOCATION );
+ field.SetProperty( TextField::Property::GRAB_HANDLE_PRESSED_IMAGE, "image2" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::GRAB_HANDLE_PRESSED_IMAGE ), "image2", TEST_LOCATION );
+ field.SetProperty( TextField::Property::SELECTION_HANDLE_IMAGE_LEFT, "image3" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SELECTION_HANDLE_IMAGE_LEFT ), "image3", TEST_LOCATION );
+ field.SetProperty( TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT, "image4" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SELECTION_HANDLE_IMAGE_RIGHT ), "image4", TEST_LOCATION );
+ field.SetProperty( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT, "image5" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_LEFT ), "image5", TEST_LOCATION );
+ field.SetProperty( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT, "image6" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::SELECTION_HANDLE_PRESSED_IMAGE_RIGHT ), "image6", TEST_LOCATION );
+
+ // Check the highlight color
+ field.SetProperty( TextField::Property::SELECTION_HIGHLIGHT_COLOR, Color::GREEN );
+ DALI_TEST_EQUALS( field.GetProperty<Vector4>( TextField::Property::SELECTION_HIGHLIGHT_COLOR ), Color::GREEN, TEST_LOCATION );
+
+ // Decoration bounding box
+ field.SetProperty( TextField::Property::DECORATION_BOUNDING_BOX, Rect<int>( 0, 0, 1, 1 ) );
+ DALI_TEST_EQUALS( field.GetProperty<Rect <int > >( TextField::Property::DECORATION_BOUNDING_BOX ), Rect<int>( 0, 0, 1, 1 ), TEST_LOCATION );
+
END_TEST;
}
field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "BEGIN" );
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ Stage::GetCurrent().Add( field );
+
try
{
// Render some text with the basic backend
DALI_TEST_CHECK( field );
field.SetProperty( TextField::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
+
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ Stage::GetCurrent().Add( field );
+
try
{
// Render some text with the shared atlas backend
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- Stage::GetCurrent().Add(field);
+ Stage::GetCurrent().Add( field );
field.TextChangedSignal().Connect(&TestTextChangedCallback);
field.SetKeyInputFocus();
- Dali::Integration::KeyEvent keyevent;
- keyevent.keyName = "D";
- keyevent.keyString = "D";
- keyevent.keyCode = 0;
- keyevent.keyModifier = 0;
- keyevent.time = 0;
- keyevent.state = Integration::KeyEvent::Down;
-
gTextChangedCallBackCalled = false;
- application.ProcessEvent( keyevent );
+ application.ProcessEvent( GenerateKey( "D", "D", 0, 0, 0, Integration::KeyEvent::Down ) );
DALI_TEST_CHECK( gTextChangedCallBackCalled );
END_TEST;
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- Stage::GetCurrent().Add(field);
+ Stage::GetCurrent().Add( field );
field.TextChangedSignal().Connect(&TestTextChangedCallback);
gTextChangedCallBackCalled = false;
field.SetProperty( TextField::Property::PLACEHOLDER_TEXT, "ABC" ); // Setting placeholder, not TEXT
- DALI_TEST_CHECK( ! gTextChangedCallBackCalled );
+ DALI_TEST_CHECK( !gTextChangedCallBackCalled );
END_TEST;
}
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- Stage::GetCurrent().Add(field);
+ Stage::GetCurrent().Add( field );
const int maxNumberOfCharacters = 1;
field.SetProperty( TextField::Property::MAX_LENGTH, maxNumberOfCharacters );
gMaxCharactersCallBackCalled = false;
field.MaxLengthReachedSignal().Connect(&TestMaxLengthReachedCallback);
- Dali::Integration::KeyEvent keyevent;
- keyevent.keyName = "a";
- keyevent.keyString = "a";
- keyevent.keyCode = 0;
- keyevent.keyModifier = 0;
- keyevent.time = 0;
- keyevent.state = Integration::KeyEvent::Down;
-
- application.ProcessEvent( keyevent );
-
- application.ProcessEvent( keyevent );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
DALI_TEST_CHECK( gMaxCharactersCallBackCalled );
TextField field = TextField::New();
DALI_TEST_CHECK( field );
- Stage::GetCurrent().Add(field);
+ Stage::GetCurrent().Add( field );
const int maxNumberOfCharacters = 3;
field.SetProperty( TextField::Property::MAX_LENGTH, maxNumberOfCharacters );
gMaxCharactersCallBackCalled = false;
field.MaxLengthReachedSignal().Connect(&TestMaxLengthReachedCallback);
- Dali::Integration::KeyEvent keyevent;
- keyevent.keyName = "a";
- keyevent.keyString = "a";
- keyevent.keyCode = 0;
- keyevent.keyModifier = 0;
- keyevent.time = 0;
- keyevent.state = Integration::KeyEvent::Down;
-
- application.ProcessEvent( keyevent );
- application.ProcessEvent( keyevent );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
DALI_TEST_CHECK( !gMaxCharactersCallBackCalled );
END_TEST;
}
+
+int utcDaliTextFieldEvent01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldEvent01");
+
+ // Creates a tap event. After creating a tap event the text field should
+ // have the focus and add text with key events should be possible.
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ Stage::GetCurrent().Add( field );
+
+ field.SetSize( 300.f, 50.f );
+ field.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ field.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Add a key event but as the text field has not the focus it should do nothing.
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string(""), TEST_LOCATION );
+
+ // Create a tap event to touch the text field.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 150.0f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 150.0f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Now the text field has the focus, so it can handle the key events.
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( TextField::Property::TEXT ), std::string("aa"), TEST_LOCATION );
+
+ // Create a second text field and send key events to it.
+ TextField field2 = TextField::New();
+
+ field2.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ field2.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+ field2.SetSize( 100.f, 100.f );
+ field2.SetPosition( 100.f, 100.f );
+
+ Stage::GetCurrent().Add( field2 );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Create a tap event on the second text field.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 150.0f, 125.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 150.0f, 125.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // The second text field has the focus. It should handle the key events.
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Check the text has been added to the second text field.
+ DALI_TEST_EQUALS( field2.GetProperty<std::string>( TextField::Property::TEXT ), std::string("aa"), TEST_LOCATION );
+
+ END_TEST;
+}
+
+int utcDaliTextFieldEvent02(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldEvent02");
+
+ // Checks if the right number of actors are created.
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ Stage::GetCurrent().Add( field );
+
+ field.SetSize( 300.f, 50.f );
+ field.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ field.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Check there are the expected number of children ( active layer, offscreen root actor, and the offscreen image actor
+ DALI_TEST_EQUALS( field.GetChildCount(), 3u, TEST_LOCATION );
+
+ Actor layer = field.GetChildAt( 0u );
+ DALI_TEST_CHECK( layer.IsLayer() );
+
+ Actor offscreenRoot = field.GetChildAt( 1u );
+ DALI_TEST_CHECK( offscreenRoot.IsLayer() );
+ DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 1u, TEST_LOCATION ); // The camera actor.
+
+ Actor offscreenImage = field.GetChildAt( 2u );
+ ImageActor imageActor = ImageActor::DownCast( offscreenImage );
+ DALI_TEST_CHECK( imageActor );
+
+ // Create a tap event to touch the text field.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 150.0f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 150.0f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( layer.GetChildCount(), 1u, TEST_LOCATION ); // The cursor.
+ DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 1u, TEST_LOCATION ); // The camera actor.
+
+ // Now the text field has the focus, so it can handle the key events.
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Checks the cursor and the renderer have been created.
+ DALI_TEST_EQUALS( layer.GetChildCount(), 1u, TEST_LOCATION ); // The cursor.
+ DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 2u, TEST_LOCATION ); // The camera actor and the renderer
+
+ ImageActor cursor = ImageActor::DownCast( layer.GetChildAt( 0u ) );
+ DALI_TEST_CHECK( cursor );
+
+ CameraActor camera = CameraActor::DownCast( offscreenRoot.GetChildAt( 0u ) );
+ DALI_TEST_CHECK( camera );
+
+ RenderableActor renderer = RenderableActor::DownCast( offscreenRoot.GetChildAt( 1u ) );
+ DALI_TEST_CHECK( renderer );
+
+ // Move the cursor and check the position changes.
+ Vector3 position1 = cursor.GetCurrentPosition();
+
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_CURSOR_LEFT, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector3 position2 = cursor.GetCurrentPosition();
+
+ DALI_TEST_CHECK( position2.x < position1.x );
+
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector3 position3 = cursor.GetCurrentPosition();
+
+ DALI_TEST_EQUALS( position1, position3, TEST_LOCATION ); // Should be in the same position1.
+
+ // Send some taps and check the cursor positions.
+
+ // Try to tap at the beginning.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 3.f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 3.f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Cursor position should be the same than position1.
+ Vector3 position4 = cursor.GetCurrentPosition();
+
+ DALI_TEST_EQUALS( position2, position4, TEST_LOCATION ); // Should be in the same position2.
+
+ // Try to tap at the end.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 13.f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 13.0f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Cursor position should be the same than position1.
+ Vector3 position5 = cursor.GetCurrentPosition();
+
+ DALI_TEST_EQUALS( position1, position5, TEST_LOCATION ); // Should be in the same position1.
+
+ // Remove some text.
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::Down ) );
+ application.ProcessEvent( GenerateKey( "", "", DALI_KEY_BACKSPACE, 0, 0, Integration::KeyEvent::Down ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Cursor position should be the same than position2.
+ Vector3 position6 = cursor.GetCurrentPosition();
+
+ DALI_TEST_EQUALS( Vector3( 0.f, position2.y, position2.z ), position6, TEST_LOCATION ); // TODO Should be in the same position2.
+
+ // Should not be renderer.
+ DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 1u, TEST_LOCATION ); // The camera actor only.
+
+ END_TEST;
+}
+
+int utcDaliTextFieldEvent03(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" utcDaliTextFieldEvent03");
+
+ // Checks if the highlight actor is created.
+
+ TextField field = TextField::New();
+ DALI_TEST_CHECK( field );
+
+ Stage::GetCurrent().Add( field );
+
+ field.SetProperty( TextField::Property::TEXT, "This is a long text for the size of the text-field." );
+ field.SetSize( 30.f, 50.f );
+ field.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ field.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Tap first to get the focus.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, Vector2( 3.f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, Vector2( 3.f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Double tap to select a word.
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 2u, 1u, Vector2( 3.f, 25.0f ) ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 2u, 1u, Vector2( 3.f, 25.0f ) ) );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // The offscreen root actor should have three actors: the camera, a renderer and the highlight actor.
+ Actor offscreenRoot = field.GetChildAt( 1u );
+ DALI_TEST_CHECK( offscreenRoot.IsLayer() );
+
+ CameraActor camera = CameraActor::DownCast( offscreenRoot.GetChildAt( 0u ) );
+ DALI_TEST_CHECK( camera );
+
+ RenderableActor renderer = RenderableActor::DownCast( offscreenRoot.GetChildAt( 1u ) );
+ DALI_TEST_CHECK( renderer );
+
+ MeshActor highlight = MeshActor::DownCast( offscreenRoot.GetChildAt( 2u ) );
+ DALI_TEST_CHECK( highlight );
+
+ END_TEST;
+}
const char* const PROPERTY_NAME_UNDERLINE_COLOR = "underline-color";
const char* const PROPERTY_NAME_UNDERLINE_HEIGHT = "underline-height";
+const unsigned int DEFAULT_RENDERING_BACKEND = Dali::Toolkit::Text::DEFAULT_RENDERING_BACKEND;
+
} // namespace
int UtcDaliToolkitTextLabelConstructorP(void)
DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE_COLOR ) == TextLabel::Property::UNDERLINE_COLOR );
DALI_TEST_CHECK( label.GetPropertyIndex( PROPERTY_NAME_UNDERLINE_HEIGHT) == TextLabel::Property::UNDERLINE_HEIGHT );
- // Check label defaults are correct
- DALI_TEST_EQUALS( label.GetProperty<int>( TextLabel::Property::RENDERING_BACKEND ), Text::RENDERING_SHARED_ATLAS, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::UNDERLINE_ENABLED ), false, TEST_LOCATION );
- DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 0.0f, TEST_LOCATION );
END_TEST;
}
{
ToolkitTestApplication application;
tet_infoline(" UtcDaliToolkitTextLabelSetPropertyP");
- TextLabel label = TextLabel::New("Test Text");
+ TextLabel label = TextLabel::New();
DALI_TEST_CHECK( label );
+ // Check defaults
+ DALI_TEST_EQUALS( label.GetProperty<unsigned int>( TextLabel::Property::RENDERING_BACKEND ), DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_FAMILY ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_STYLE ), std::string(""), TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::POINT_SIZE ), 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::MULTI_LINE ), false, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::TEXT_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<Vector2>( TextLabel::Property::SHADOW_OFFSET ), Vector2::ZERO, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::SHADOW_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::UNDERLINE_ENABLED ), false, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::UNDERLINE_COLOR ), Color::BLACK, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 0.0f, TEST_LOCATION );
+
+ label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Text::RENDERING_BASIC );
+ DALI_TEST_EQUALS( label.GetProperty<unsigned int>( TextLabel::Property::RENDERING_BACKEND ), Text::RENDERING_BASIC, TEST_LOCATION );
+
// Check that text can be correctly reset
label.SetProperty( TextLabel::Property::TEXT, "Setting Text" );
- DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), "Setting Text", TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), std::string("Setting Text"), TEST_LOCATION );
+
+ // Check font properties.
+ label.SetProperty( TextLabel::Property::FONT_FAMILY, "Setting font family" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_FAMILY ), std::string("Setting font family"), TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::FONT_STYLE, "Setting font style" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::FONT_STYLE ), std::string("Setting font style"), TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::POINT_SIZE, 10.f );
+ DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::POINT_SIZE ), 10.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+ // Toggle multi-line
+ label.SetProperty( TextLabel::Property::MULTI_LINE, true );
+ DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::MULTI_LINE ), true, TEST_LOCATION );
// Check that the Alignment properties can be correctly set
- label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "BEGIN" );
- DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "BEGIN", TEST_LOCATION );
- label.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "TOP" );
- DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::VERTICAL_ALIGNMENT ), "TOP", TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::HORIZONTAL_ALIGNMENT ), "CENTER", TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::VERTICAL_ALIGNMENT, "CENTER" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::VERTICAL_ALIGNMENT ), "CENTER", TEST_LOCATION );
+
+ // Check that text color can be properly set
+ label.SetProperty( TextLabel::Property::TEXT_COLOR, Color::BLUE );
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::TEXT_COLOR ), Color::BLUE, TEST_LOCATION );
+ // The underline color is changed as well.
+ DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::UNDERLINE_COLOR ), Color::BLUE, TEST_LOCATION );
// Check that shadow parameters can be correctly set
label.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 3.0f, 3.0f ) );
label.SetProperty( TextLabel::Property::UNDERLINE_HEIGHT, 1.0f );
DALI_TEST_EQUALS( label.GetProperty<float>( TextLabel::Property::UNDERLINE_HEIGHT ), 1.0f, TEST_LOCATION );
- // Check that text color can be properly set
- label.SetProperty( TextLabel::Property::TEXT_COLOR, Color::BLUE );
- DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::TEXT_COLOR ), Color::BLUE, TEST_LOCATION );
+ TextLabel label2 = TextLabel::New( "New text" );
+ DALI_TEST_CHECK( label2 );
+ DALI_TEST_EQUALS( label2.GetProperty<std::string>( TextLabel::Property::TEXT ), std::string("New text"), TEST_LOCATION );
- // Toggle multi-line
- label.SetProperty( TextLabel::Property::MULTI_LINE, true );
- DALI_TEST_EQUALS( label.GetProperty<bool>( TextLabel::Property::MULTI_LINE ), true, TEST_LOCATION );
END_TEST;
}
TextLabel label = TextLabel::New("Test Text");
DALI_TEST_CHECK( label );
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ Stage::GetCurrent().Add( label );
+
label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "BEGIN" );
label.SetProperty( TextLabel::Property::MULTI_LINE, true );
TextLabel label = TextLabel::New("Test Text");
DALI_TEST_CHECK( label );
+ // Avoid a crash when core load gl resources.
+ application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+ Stage::GetCurrent().Add( label );
+
// Turn on all the effects
label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "CENTER" );
label.SetProperty( TextLabel::Property::MULTI_LINE, true );
label.SetProperty( TextLabel::Property::UNDERLINE_COLOR, Color::RED );
label.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 1.0f, 1.0f ) );
label.SetProperty( TextLabel::Property::SHADOW_COLOR, Color::BLUE );
+
try
{
// Render some text with the shared atlas backend
END_TEST;
}
+int UtcDaliToolkitTextLabelLanguagesP(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliToolkitTextLabelLanguagesP");
+ TextLabel label = TextLabel::New();
+ DALI_TEST_CHECK( label );
+
+ Stage::GetCurrent().Add( label );
+
+ const std::string scripts( " привет мир, γειά σου Κόσμε, Hello world, مرحبا بالعالم, שלום עולם, "
+ "բարեւ աշխարհը, მსოფლიოში, 안녕하세요, 你好世界, ひらがな, カタカナ, "
+ "ওহে বিশ্ব, မင်္ဂလာပါကမ္ဘာလောက, हैलो वर्ल्ड, હેલો વર્લ્ડ, ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ ਦੁਨਿਆ, ಹಲೋ ವರ್ಲ್ಡ್, "
+ "ഹലോ വേൾഡ്, ଓଡ଼ିଆ, හෙලෝ වර්ල්ඩ්, ஹலோ உலகம், హలో వరల్డ్, "
+ "ສະບາຍດີໂລກ, สวัสดีโลก, ជំរាបសួរពិភពលោក, "
+ "\xF0\x9F\x98\x81 \xF0\x9F\x98\x82 \xF0\x9F\x98\x83 \xF0\x9F\x98\x84." ); // these characters on the last line are emojis.
+
+ label.SetProperty( TextLabel::Property::TEXT, scripts );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::TEXT ), scripts, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
+}
DALI_TEST_CHECK( !textSelectionPopup );
- textSelectionPopup = TextSelectionPopup::New();
+ textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL );
DALI_TEST_CHECK( textSelectionPopup );
END_TEST;
ToolkitTestApplication application;
TextSelectionPopup textSelectionPopup;
- textSelectionPopup = TextSelectionPopup::New();
+ textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL );
TextSelectionPopup copy( textSelectionPopup );
DALI_TEST_CHECK( copy == textSelectionPopup );
{
ToolkitTestApplication application;
TextSelectionPopup textSelectionPopup;
- textSelectionPopup = TextSelectionPopup::New();
+ textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL );
TextSelectionPopup copy;
copy = textSelectionPopup;
{
ToolkitTestApplication application;
TextSelectionPopup textSelectionPopup;
- textSelectionPopup = TextSelectionPopup::New();
+ textSelectionPopup = TextSelectionPopup::New( TextSelectionPopup::COPY, NULL );
TextSelectionPopup cast = TextSelectionPopup::DownCast( textSelectionPopup );
// Magnifier
///////////////////////////////////////////////////////////////////////////////////////////////////
-const std::string Magnifier::SOURCE_POSITION_PROPERTY_NAME( "source-position" );
-
Magnifier::Magnifier()
{
}
GetImpl(*this).SetSourceActor( actor );
}
-void Magnifier::SetSourcePosition(Vector3 position)
-{
- GetImpl(*this).SetSourcePosition( position );
-}
-
-bool Magnifier::GetFrameVisibility() const
-{
- return GetImpl(*this).GetFrameVisibility();
-}
-
-void Magnifier::SetFrameVisibility(bool visible)
-{
- GetImpl(*this).SetFrameVisibility(visible);
-}
-
-float Magnifier::GetMagnificationFactor() const
-{
- return GetImpl(*this).GetMagnificationFactor();
-}
-
-void Magnifier::SetMagnificationFactor(float value)
-{
- GetImpl(*this).SetMagnificationFactor( value );
-}
-
-
} // namespace Toolkit
} // namespace Dali
{
public:
- // Custom properties
+ /**
+ * @brief The start and end property ranges for this control.
+ */
+ enum PropertyRange
+ {
+ PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1,
+ PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000, ///< Reserve property indices
+
+ ANIMATABLE_PROPERTY_START_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX,
+ ANIMATABLE_PROPERTY_END_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1000 ///< Reserve animatable property indices
+ };
- static const std::string SOURCE_POSITION_PROPERTY_NAME; ///< Property, name "source-position", type Vector3
+ /**
+ * @brief An enumeration of properties belonging to the Magnifier class.
+ */
+ struct Property
+ {
+ enum
+ {
+ // Event side properties
+ FRAME_VISIBILITY = PROPERTY_START_INDEX, ///< name "frame-visibility", Whether a frame is visible or not, type boolean
+ MAGNIFICATION_FACTOR, ///< name "magnification-factor", Larger value means greater magnification, type float
+
+ // Animatable properties
+ SOURCE_POSITION = ANIMATABLE_PROPERTY_START_INDEX, ///< name "source-position", The position of the source, type Vector3
+ };
+ };
public:
*/
void SetSourceActor(Actor actor);
- /**
- * Set the source camera position to render in magnifier
- * @param[in] position The target position from which to render source.
- */
- void SetSourcePosition(Vector3 position);
-
- /**
- * Returns whether the frame is visible or not.
- * @return true if frame is visible, false if not.
- */
- bool GetFrameVisibility() const;
-
- /**
- * Sets whether the frame part of the magnifier should be visible
- * or not.
- * @param[in] visible true to display frame, false to hide frame.
- */
- void SetFrameVisibility(bool visible);
-
- /**
- * Get the magnification factor of the magnifier
- * The larger the value the larger the contents magnified.
- * A value of 1.0f indications 1x magnification.
- * @return Magnification factor is returned
- */
- float GetMagnificationFactor() const;
-
- /**
- * Set the magnification factor of the magnifier
- * The larger the value the larger the contents magnified.
- * A value of 1.0f indications 1x magnification.
- * @param[in] value Magnification factor.
- */
- void SetMagnificationFactor(float value);
-
public: // Not intended for application developers
/**
--- /dev/null
+#ifndef __DALI_TOOLKIT_TEXT_SELECTION_POPUP_CALLBACK_INTERFACE_H__
+#define __DALI_TOOLKIT_TEXT_SELECTION_POPUP_CALLBACK_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+/**
+ * @brief Interface used to receive the TextSelectionPopup's button callbacks.
+ */
+class TextSelectionPopupCallbackInterface
+{
+public:
+ /**
+ * @brief Virtual destructor.
+ */
+ virtual ~TextSelectionPopupCallbackInterface()
+ {}
+
+ /**
+ * @brief Called when a button is touched.
+ *
+ * @param[in] button The button identifier.
+ */
+ virtual void TextPopupButtonTouched( TextSelectionPopup::Buttons button ) = 0;
+};
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+
+#endif // __DALI_TOOLKIT_TEXT_SELECTION_POPUP_CALLBACK_INTERFACE_H__
namespace Toolkit
{
-TextSelectionPopup TextSelectionPopup::New()
+TextSelectionPopup TextSelectionPopup::New( Buttons enabledButtons,
+ TextSelectionPopupCallbackInterface* callbackInterface )
{
- return Internal::TextSelectionPopup::New();
+ return Internal::TextSelectionPopup::New( enabledButtons,
+ callbackInterface );
}
TextSelectionPopup::TextSelectionPopup()
namespace Toolkit
{
+class TextSelectionPopupCallbackInterface;
+
namespace Internal DALI_INTERNAL
{
class TextSelectionPopup;
{
public:
+ enum Buttons
+ {
+ CUT = 1u << 0,
+ COPY = 1u << 1,
+ PASTE = 1u << 2,
+ SELECT = 1u << 3,
+ SELECT_ALL = 1u << 4,
+ CLIPBOARD = 1u << 5,
+ NONE = 1u << 6,
+ };
+
/**
* @brief The start and end property ranges for this control.
*/
{
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
};
/**
- * 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.
{
if( Property::INVALID_INDEX == index )
{
- actor.RegisterProperty( key, value );
+ actor.RegisterProperty( key, value, Property::READ_WRITE );
}
else
{
DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Alignment, Toolkit::Control, Create )
DALI_TYPE_REGISTRATION_END()
-struct ScaleToFillConstraint
-{
- /**
- * @param padding to be added.
- */
- ScaleToFillConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding )
- {}
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
- return Vector3( parentSizeWidth, parentSizeHeight, parentSize.depth );
- }
-
- const Toolkit::Alignment::Padding mPadding;
-};
-
-struct ScaleToFitKeepAspectConstraint
-{
- /**
- * @param padding to be added.
- */
- ScaleToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding ),
- mSizeStored( false ),
- mOriginalSize()
- {}
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
- {
- mOriginalSize = currentSize;
- mSizeStored = true;
- }
-
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
- ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
-
- return mOriginalSize * std::min( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
- }
-
- const Toolkit::Alignment::Padding mPadding;
- bool mSizeStored;
- Vector3 mOriginalSize;
-};
-
-struct ScaleToFillKeepAspectConstraint
-{
- /**
- * @param padding to be added.
- */
- ScaleToFillKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding ),
- mSizeStored( false ),
- mOriginalSize()
- { }
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
- {
- mOriginalSize = currentSize;
- mSizeStored = true;
- }
-
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
- ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
-
- return mOriginalSize * std::max( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
- }
-
- const Toolkit::Alignment::Padding mPadding;
- bool mSizeStored;
- Vector3 mOriginalSize;
-};
-
-struct ShrinkToFitConstraint
-{
- /**
- * @param padding to be added.
- */
- ShrinkToFitConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding ),
- mSizeStored( false ),
- mOriginalSize()
- {}
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
- {
- mOriginalSize = currentSize;
- mSizeStored = true;
- }
-
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
- ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
-
- return Vector3( std::min( parentSizeWidth, mOriginalSize.width ), std::min( parentSizeHeight, mOriginalSize.height ), std::min( parentSize.depth, mOriginalSize.depth ) );
- }
-
- const Toolkit::Alignment::Padding mPadding;
- bool mSizeStored;
- Vector3 mOriginalSize;
-};
-
-/**
- * Constraint that uses naturalSize if it fits inside parent and parent size if not. It also adds some padding pixels
- */
-struct ShrinkToFitKeepAspectConstraint
-{
- /**
- * @param padding to be added.
- */
- ShrinkToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
- : mPadding( padding ),
- mSizeStored( false ),
- mOriginalSize()
- {}
-
- /**
- * Called by render thread
- */
- Vector3 operator()( const Vector3& currentSize,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
- return GetSize( currentSize, parentSize );
- }
-
- inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
- {
- if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
- {
- mOriginalSize = currentSize;
- mSizeStored = true;
- }
-
- const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
- const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
-
- // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
- if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
- ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
- {
- // no point trying to squeeze actors into this small size
- return Vector3::ZERO;
- }
-
- return Vector3( ShrinkInside( Vector2( parentSizeWidth, parentSizeHeight ), Vector2( mOriginalSize ) ) );
- }
-
- const Toolkit::Alignment::Padding mPadding;
- bool mSizeStored;
- Vector3 mOriginalSize;
-};
-
/**
- * Constraint that modifies the contained actor taking into account the padding value.
+ * @param padding The padding value
+ * @param horizontalAlignment The horizontal alignment.
+ * @param verticalAlignment The vertical alignment.
+ * @param currentSize of the object
+ * @param parentSize
*/
-struct PositionConstraint
+inline Vector3 GetPosition( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment,
+ const Vector2& currentSize, const Vector2& parentSize )
{
- /**
- * @param padding The padding value
- * @param horizontalAlignment The horizontal alignment.
- * @param verticalAlignment The vertical alignment.
- */
- PositionConstraint( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment )
- : mPadding( padding ),
- mHorizontalAlignment( horizontalAlignment ),
- mVerticalAlignment( verticalAlignment )
- {}
-
- /**
- * Called by render thread.
- */
- Vector3 operator()( const Vector3& currentPosition,
- const PropertyInput& currentSizeProperty,
- const PropertyInput& parentSizeProperty )
- {
- const Vector3& currentSize( currentSizeProperty.GetVector3() );
- const Vector3& parentSize( parentSizeProperty.GetVector3() );
-
- return GetPosition( currentSize, parentSize );
- }
+ Vector3 position( 0.f, 0.f, 0.f );
- inline Vector3 GetPosition( const Vector3& currentSize, const Vector3& parentSize )
+ switch( horizontalAlignment )
{
- Vector3 position( 0.f, 0.f, 0.f );
-
- switch( mHorizontalAlignment )
- {
case Dali::Toolkit::Alignment::HorizontalLeft:
{
- position.x += mPadding.left;
- break;
- }
- case Dali::Toolkit::Alignment::HorizontalCenter:
- {
- if( currentSize.width + mPadding.left + mPadding.right >= parentSize.width )
- {
- position.x += 0.5f * ( mPadding.left - mPadding.right );
- }
+ position.x += padding.left;
break;
}
case Dali::Toolkit::Alignment::HorizontalRight:
{
- position.x -= mPadding.right;
+ position.x -= padding.right;
break;
}
- default:
+ case Dali::Toolkit::Alignment::HorizontalCenter: // FALLTHROUGH
+ default: // use center as default
{
- DALI_ASSERT_ALWAYS( !"Wrong horizontal alignment value" );
+ if( currentSize.width + padding.left + padding.right >= parentSize.width )
+ {
+ position.x += 0.5f * ( padding.left - padding.right );
+ }
break;
}
- }
+ }
- switch( mVerticalAlignment )
- {
+ switch( verticalAlignment )
+ {
case Dali::Toolkit::Alignment::VerticalTop:
{
- position.y += mPadding.top;
- break;
- }
- case Dali::Toolkit::Alignment::VerticalCenter:
- {
- if( currentSize.height + mPadding.top + mPadding.bottom >= parentSize.height )
- {
- position.y += 0.5f * ( mPadding.top - mPadding.bottom );
- }
+ position.y += padding.top;
break;
}
case Dali::Toolkit::Alignment::VerticalBottom:
{
- position.y -= mPadding.bottom;
+ position.y -= padding.bottom;
break;
}
- default:
+ case Dali::Toolkit::Alignment::VerticalCenter: // FALLTHROUGH
+ default: // use center as default
{
- DALI_ASSERT_ALWAYS( !"Wrong vertical alignment value" );
+ if( currentSize.height + padding.top + padding.bottom >= parentSize.height )
+ {
+ position.y += 0.5f * ( padding.top - padding.bottom );
+ }
break;
}
- }
-
- return position;
}
- const Toolkit::Alignment::Padding mPadding;
- const Toolkit::Alignment::Type mHorizontalAlignment;
- const Toolkit::Alignment::Type mVerticalAlignment;
-};
+ return position;
+}
+
} // namespace
Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
child.SetAnchorPoint( anchorPointAndParentOrigin );
child.SetParentOrigin( anchorPointAndParentOrigin );
- Vector3 currentChildSize( child.GetTargetSize() );
- if( currentChildSize == Vector3::ZERO )
+ Vector2 currentChildSize( child.GetTargetSize().GetVectorXY() );
+ if( currentChildSize == Vector2::ZERO )
{
currentChildSize = child.GetNaturalSize();
}
bool renegotiate = true;
- Vector3 newChildSize;
+ Vector2 newChildSize;
+ newChildSize.width = size.width - ( mPadding.left + mPadding.right );
+ newChildSize.height = size.height- ( mPadding.top + mPadding.bottom );
- switch( mScaling )
+ // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
+ if( ( newChildSize.width > Math::MACHINE_EPSILON_1000 ) && ( newChildSize.height > Math::MACHINE_EPSILON_1000 ) &&
+ ( currentChildSize.width > Math::MACHINE_EPSILON_1000 ) && ( currentChildSize.height > Math::MACHINE_EPSILON_1000 ) )
{
- case Toolkit::Alignment::ScaleNone:
- {
- // Nothing to do but needed just to not to jump to the default.
- newChildSize = currentChildSize;
- renegotiate = false;
- break;
- }
- case Toolkit::Alignment::ScaleToFill:
- {
- ScaleToFillConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) ) ;
- break;
- }
- case Toolkit::Alignment::ScaleToFitKeepAspect:
- {
- ScaleToFitKeepAspectConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) ) ;
- break;
- }
- case Toolkit::Alignment::ScaleToFillKeepAspect:
- {
- ScaleToFillKeepAspectConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) );
- break;
- }
- case Toolkit::Alignment::ShrinkToFit:
- {
- ShrinkToFitConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) );
- break;
- }
- case Toolkit::Alignment::ShrinkToFitKeepAspect:
- {
- ShrinkToFitKeepAspectConstraint constraint( mPadding );
- newChildSize = constraint.GetSize( currentChildSize, Vector3(size) );
- break;
- }
- default:
+ // no point trying to squeeze actors into too small size
+ switch( mScaling )
{
- DALI_ASSERT_ALWAYS( !"Invalid Alignment::mGeometryScaling value" );
- break;
+ case Toolkit::Alignment::ScaleNone:
+ {
+ // Nothing to do
+ renegotiate = false;
+ break;
+ }
+ case Toolkit::Alignment::ScaleToFill:
+ {
+ // Nothing to do, newChildSize is already full size minus padding
+ break;
+ }
+ case Toolkit::Alignment::ScaleToFitKeepAspect:
+ {
+ newChildSize = currentChildSize * std::min( ( newChildSize.width / currentChildSize.width ), ( newChildSize.height / currentChildSize.height ) );
+ break;
+ }
+ case Toolkit::Alignment::ScaleToFillKeepAspect:
+ {
+ newChildSize = currentChildSize * std::max( ( newChildSize.width / currentChildSize.width ), ( newChildSize.height / currentChildSize.height ) );
+ break;
+ }
+ case Toolkit::Alignment::ShrinkToFit:
+ {
+ newChildSize = Vector2( std::min( newChildSize.width, currentChildSize.width ), std::min( newChildSize.height, currentChildSize.height ) );
+ break;
+ }
+ case Toolkit::Alignment::ShrinkToFitKeepAspect:
+ {
+ // check source size vs target size to see if we need to shrink
+ float widthScale = ( newChildSize.width < currentChildSize.width ) ? (newChildSize.width / currentChildSize.width) : 1.f;
+ float heightScale = ( newChildSize.height < currentChildSize.height ) ? (newChildSize.height / currentChildSize.height) : 1.0f;
+ // use smaller of the scales
+ float scale = std::min( widthScale, heightScale );
+ // check if we need to scale
+ if( scale < 1.0f )
+ {
+ // scale natural size to fit inside
+ newChildSize *= scale;
+ }
+ break;
+ }
}
}
- PositionConstraint positionConstraint(mPadding, mHorizontal, mVertical);
- child.SetPosition( positionConstraint.GetPosition(newChildSize, currentChildSize) );
+ child.SetPosition( GetPosition( mPadding, mHorizontal, mVertical , newChildSize, currentChildSize ) );
if( renegotiate )
{
- container.Add( child, Vector2(newChildSize) );
+ container.Add( child, newChildSize );
}
}
}
#include <dali/public-api/common/stage.h>
#include <dali/public-api/render-tasks/render-task-list.h>
#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/object/type-registry-helper.h>
-using namespace Dali;
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
namespace // unnamed namespace
{
+
+Dali::BaseHandle Create()
+{
+ return Toolkit::Magnifier::New();
+}
+
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Magnifier, Toolkit::Control, Create )
+
+DALI_PROPERTY_REGISTRATION( Toolkit, Magnifier, "frame-visibility", BOOLEAN, FRAME_VISIBILITY )
+DALI_PROPERTY_REGISTRATION( Toolkit, Magnifier, "magnification-factor", FLOAT, MAGNIFICATION_FACTOR )
+
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Magnifier, "source-position", VECTOR3, SOURCE_POSITION )
+
+DALI_TYPE_REGISTRATION_END()
+
const char* DEFAULT_FRAME_IMAGE_PATH = DALI_IMAGE_DIR "magnifier-image-frame.png";
const float IMAGE_BORDER_INDENT = 14.0f; ///< Indent of border in pixels.
}
};
-}
-
-namespace Dali
-{
-
-namespace Toolkit
-{
-
-namespace Internal
-{
+} // unnamed namespace
///////////////////////////////////////////////////////////////////////////////////////////////////
// Magnifier
Magnifier::Magnifier()
: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
- mPropertySourcePosition(Property::INVALID_INDEX),
mDefaultCameraDistance(1000.f),
mActorSize(Vector3::ZERO),
mMagnificationFactor(1.0f)
mTask.SetSourceActor( actor );
}
-void Magnifier::SetSourcePosition(const Vector3& position)
-{
- Self().SetProperty(mPropertySourcePosition, position);
-}
-
void Magnifier::Initialize()
{
Actor self = Self();
- mPropertySourcePosition = self.RegisterProperty( Toolkit::Magnifier::SOURCE_POSITION_PROPERTY_NAME, Vector3::ZERO );
Vector2 stageSize(Stage::GetCurrent().GetSize());
// NOTE:
Stage().GetCurrent().Add(mSourceActor);
mSourceActor.SetParentOrigin(ParentOrigin::CENTER);
Constraint constraint = Constraint::New<Vector3>( mSourceActor, Actor::Property::POSITION, EqualToConstraint() );
- constraint.AddSource( Source( self, mPropertySourcePosition ) );
+ constraint.AddSource( Source( self, Toolkit::Magnifier::Property::SOURCE_POSITION ) );
constraint.Apply();
// create the render task this will render content on top of everything
mCameraActor.SetAspectRatio( worldSize.width / worldSize.height );
}
+void Magnifier::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+ Toolkit::Magnifier magnifier = Toolkit::Magnifier::DownCast( Dali::BaseHandle( object ) );
+
+ if( magnifier )
+ {
+ Magnifier& magnifierImpl( GetImpl( magnifier ) );
+ switch( index )
+ {
+ case Toolkit::Magnifier::Property::FRAME_VISIBILITY:
+ {
+ magnifierImpl.SetFrameVisibility( value.Get< bool >() );
+ break;
+ }
+ case Toolkit::Magnifier::Property::MAGNIFICATION_FACTOR:
+ {
+ magnifierImpl.SetMagnificationFactor( value.Get< float >() );
+ break;
+ }
+ }
+ }
+}
+
+Property::Value Magnifier::GetProperty( BaseObject* object, Property::Index index )
+{
+ Property::Value value;
+
+ Toolkit::Magnifier magnifier = Toolkit::Magnifier::DownCast( Dali::BaseHandle( object ) );
+
+ if( magnifier )
+ {
+ Magnifier& magnifierImpl( GetImpl( magnifier ) );
+ switch( index )
+ {
+ case Toolkit::Magnifier::Property::FRAME_VISIBILITY:
+ {
+ value = magnifierImpl.GetFrameVisibility();
+ break;
+ }
+ case Toolkit::Magnifier::Property::MAGNIFICATION_FACTOR:
+ {
+ value = magnifierImpl.GetMagnificationFactor();
+ break;
+ }
+ }
+ }
+
+ return value;
+}
+
} // namespace Internal
} // namespace Toolkit
void SetSourceActor(Actor actor);
/**
- * @copydoc Toolkit::ImageView::SetSourcePosition
- */
- void SetSourcePosition(const Vector3& position);
-
- /**
- * @copydoc Toolkit::ImageView::GetFrameVisibility
+ * Returns whether the frame is visible or not.
+ * @return true if frame is visible, false if not.
*/
bool GetFrameVisibility() const;
/**
- * @copydoc Toolkit::ImageView::SetFrameVisibility
+ * Sets whether the frame part of the magnifier should be visible or not.
+ * @param[in] visible true to display frame, false to hide frame.
*/
void SetFrameVisibility(bool visible);
/**
- * @copydoc Toolkit::ImageView::GetMagnificationFactor
+ * Get the magnification factor of the magnifier
+ * The larger the value the larger the contents magnified.
+ * A value of 1.0f indications 1x magnification.
+ * @return Magnification factor is returned
*/
float GetMagnificationFactor() const;
/**
- * @copydoc Toolkit::ImageView::SetMagnificationFactor
+ * Set the magnification factor of the magnifier
+ * The larger the value the larger the contents magnified.
+ * A value of 1.0f indications 1x magnification.
+ * @param[in] value Magnification factor.
*/
void SetMagnificationFactor(float value);
*/
void Update();
+ // Properties
+
+ /**
+ * Called when a property of an object of this type is set.
+ * @param[in] object The object whose property is set.
+ * @param[in] index The property index.
+ * @param[in] value The new property value.
+ */
+ static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value );
+
+ /**
+ * Called to retrieve a property of an object of this type.
+ * @param[in] object The object whose property is to be retrieved.
+ * @param[in] index The property index.
+ * @return The current value of the property.
+ */
+ static Property::Value GetProperty( BaseObject* object, Property::Index index );
+
protected:
/**
RenderTask mTask; ///< Render Task to render the source actor contents.
CameraActor mCameraActor; ///< CameraActor attached to RenderTask
ImageActor mFrame; ///< The Magnifier Frame
- Property::Index mPropertySourcePosition; ///< Source Position ("source-position")
Actor mSourceActor; ///< Source Delegate Actor represents the source position to read.
float mDefaultCameraDistance; ///< Default RenderTask's camera distance from target.
Vector3 mActorSize; ///< The Actor size
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 )
{
{
{ "fixed", Toolkit::TableView::FIXED },
{ "relative", Toolkit::TableView::RELATIVE },
- { "fill", Toolkit::TableView::FILL }
+ { "fill", Toolkit::TableView::FILL },
+ { "fit", Toolkit::TableView::FIT }
};
-
const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof( LAYOUT_POLICY_STRING_TABLE[0] );
+const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
+{
+ {"left", HorizontalAlignment::LEFT},
+ {"center", HorizontalAlignment::CENTER},
+ {"right", HorizontalAlignment::RIGHT}
+};
+const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
+
+const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
+{
+ {"top", VerticalAlignment::TOP},
+ {"center", VerticalAlignment::CENTER},
+ {"bottom", VerticalAlignment::BOTTOM}
+};
+const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(VERTICAL_ALIGNMENT_STRING_TABLE) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] );
+
} // Unnamed namespace
Toolkit::TableView TableView::New( unsigned int initialRows, unsigned int initialColumns )
DALI_ASSERT_ALWAYS( child );
// if child is already parented, we adopt it
- if( child.GetParent() )
- {
- child.GetParent().Remove( child );
- }
+ child.Unparent();
// check if we need to expand our data array
if( position.rowIndex >= mCellData.GetRows() )
return mPadding;
}
-void TableView::SetRowPolicy( unsigned int rowIndex, CellSizePolicy policy )
+void TableView::SetFitHeight( unsigned int rowIndex )
{
DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
- if( mRowData[ rowIndex ].sizePolicy != policy )
+ if( mRowData[ rowIndex ].sizePolicy != Toolkit::TableView::FIT )
{
- mRowData[ rowIndex ].sizePolicy = policy;
+ mRowData[ rowIndex ].sizePolicy = Toolkit::TableView::FIT;
mRowColumnDirty = true;
RelayoutRequest();
}
}
-TableView::CellSizePolicy TableView::GetRowPolicy( unsigned int rowIndex ) const
+bool TableView::IsFitHeight( unsigned int rowIndex ) const
{
DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
- return mRowData[ rowIndex ].sizePolicy;
+ return mRowData[ rowIndex ].sizePolicy == Toolkit::TableView::FIT;
}
-void TableView::SetColumnPolicy( unsigned int columnIndex, CellSizePolicy policy )
+void TableView::SetFitWidth( unsigned int columnIndex )
{
DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
- if( mColumnData[ columnIndex ].sizePolicy != policy )
+ if( mColumnData[ columnIndex ].sizePolicy != Toolkit::TableView::FIT )
{
- mColumnData[ columnIndex ].sizePolicy = policy;
+ mColumnData[ columnIndex ].sizePolicy = Toolkit::TableView::FIT;
mRowColumnDirty = true;
RelayoutRequest();
}
}
-TableView::CellSizePolicy TableView::GetColumnPolicy( unsigned int columnIndex ) const
+bool TableView::IsFitWidth( unsigned int columnIndex ) const
{
DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
- return mColumnData[ columnIndex ].sizePolicy;
+ return mColumnData[ columnIndex ].sizePolicy == Toolkit::TableView::FIT;
}
void TableView::SetFixedHeight( unsigned int rowIndex, float height )
RowColumnData& data = mRowData[ rowIndex ];
data.size = height;
- data.sizePolicy = FIXED;
+ data.sizePolicy = Toolkit::TableView::FIXED;
mRowColumnDirty = true;
RelayoutRequest();
RowColumnData& data = mColumnData[ columnIndex ];
data.size = width;
- data.sizePolicy = FIXED;
+ data.sizePolicy = Toolkit::TableView::FIXED;
mRowColumnDirty = true;
RelayoutRequest();
RowColumnData& data = mRowData[ rowIndex ];
data.fillRatio = heightPercentage;
- data.userFillRatio = true;
- data.sizePolicy = FILL;
+ data.sizePolicy = Toolkit::TableView::RELATIVE;
mRowColumnDirty = true;
RelayoutRequest();
RowColumnData& data = mColumnData[ columnIndex ];
data.fillRatio = widthPercentage;
- data.userFillRatio = true;
- data.sizePolicy = FILL;
+ data.sizePolicy = Toolkit::TableView::RELATIVE;
mRowColumnDirty = true;
RelayoutRequest();
{
CalculateRowColumnData();
- // Go through the layout data
- float cumulatedHeight = 0.0f;
-
- const unsigned int rowCount = mCellData.GetRows();
+ // update every column position in ColumnData array
+ float cumulatedWidth = 0.0f;
const unsigned int columnCount = mCellData.GetColumns();
+ for( unsigned int column = 0; column < columnCount; ++column )
+ {
+ mColumnData[column].position = cumulatedWidth;
+ cumulatedWidth += mColumnData[ column ].size;
+ }
+ // update every row position in RowData array
+ float cumulatedHeight = 0.0f;
+ const unsigned int rowCount = mCellData.GetRows();
for( unsigned int row = 0; row < rowCount; ++row )
{
- float cumulatedWidth = 0.0f;
+ mRowData[row].position = cumulatedHeight;
+ cumulatedHeight += mRowData[ row ].size;
+ }
+ // Go through the layout data
+ for( unsigned int row = 0; row < rowCount; ++row )
+ {
for( unsigned int column = 0; column < columnCount; ++column )
{
- Actor& actor = mCellData[ row ][ column ].actor;
- const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].position;
+ CellData& cellData= mCellData[ row ][ column ];
+ Actor& actor = cellData.actor;
+ const Toolkit::TableView::CellPosition position = cellData.position;
// If there is an actor and this is the main cell of the actor.
- // An actor can be in multiple cells if its row or columnspan is more than 1.
+ // An actor can be in multiple cells if its row or column span is more than 1.
// We however must lay out each actor only once.
- if( actor && ( position.rowIndex == row ) && ( position.columnIndex == column ) )
+ if( actor && position.rowIndex == row && position.columnIndex == column )
{
- // Anchor actor to top left of table view
+ // Anchor actor to top left of the cell
actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ Vector2( actor.GetRelayoutSize( Dimension::WIDTH ), actor.GetRelayoutSize( Dimension::HEIGHT ) );
+
Padding padding;
actor.GetPadding( padding );
- Vector3 actorPosition( cumulatedWidth + mPadding.width + padding.left, // Left padding
- cumulatedHeight + mPadding.height + padding.top, // Top padding
- 0.0f );
- actor.SetPosition( actorPosition );
- }
+ if( cellData.horizontalAlignment == HorizontalAlignment::LEFT )
+ {
+ actor.SetX( mColumnData[column].position + mPadding.width + padding.left );
+ }
+ else
+ {
+ float cellRightPosition = column+position.columnSpan < columnCount ? mColumnData[column+position.columnSpan].position : cumulatedWidth;
- DALI_ASSERT_DEBUG( column < mColumnData.Size() );
- cumulatedWidth += mColumnData[ column ].size;
- }
+ if( cellData.horizontalAlignment == HorizontalAlignment::RIGHT )
+ {
+ actor.SetX( cellRightPosition - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) );
+ }
+ else //if( cellData.horizontalAlignment == HorizontalAlignment::CENTER )
+ {
+ actor.SetX( (mColumnData[column].position + cellRightPosition
+ + padding.left - padding.right
+ - actor.GetRelayoutSize( Dimension::WIDTH )) * 0.5f );
+ }
+ }
- DALI_ASSERT_DEBUG( row < mRowData.Size() );
- cumulatedHeight += mRowData[ row ].size;
+ if( cellData.verticalAlignment == VerticalAlignment::TOP )
+ {
+ actor.SetY( mRowData[row].position + mPadding.height + padding.top );
+ }
+ else
+ {
+ float cellBottomPosition = row+position.rowSpan < rowCount ? mRowData[row+position.rowSpan].position : cumulatedHeight;
+
+ if( cellData.verticalAlignment == VerticalAlignment::BOTTOM )
+
+ {
+ actor.SetY( cellBottomPosition - mPadding.height - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT ) );
+ }
+ else //if( cellData.verticalAlignment = VerticalAlignment::CENTER )
+ {
+ actor.SetY( (mRowData[row].position + cellBottomPosition
+ + padding.top - padding.bottom
+ - actor.GetRelayoutSize( Dimension::HEIGHT )) * 0.5f );
+ }
+ }
+ }
+ }
}
}
}
case Toolkit::TableView::Property::LAYOUT_ROWS:
{
- SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, value );
+ SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, &TableView::SetFitHeight, value );
break;
}
case Toolkit::TableView::Property::LAYOUT_COLUMNS:
{
- SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, value );
+ SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, &TableView::SetFitWidth, value );
break;
}
}
return;
}
- RelayoutRequest();
-
// Test properties on actor
+ HorizontalAlignment::Type horizontalAlignment = HorizontalAlignment::LEFT;
+ VerticalAlignment::Type verticalAlignment = VerticalAlignment::TOP;
+ if( child.GetPropertyIndex( CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME ) != Property::INVALID_INDEX )
+ {
+ std::string value = child.GetProperty( child.GetPropertyIndex(CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME) ).Get<std::string >();
+ Scripting::GetEnumeration< HorizontalAlignment::Type >( value.c_str(),
+ HORIZONTAL_ALIGNMENT_STRING_TABLE,
+ HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
+ horizontalAlignment );
+ }
+ if( child.GetPropertyIndex( CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME ) != Property::INVALID_INDEX )
+ {
+ std::string value = child.GetProperty( child.GetPropertyIndex(CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME) ).Get<std::string >();
+ Scripting::GetEnumeration< VerticalAlignment::Type >( value.c_str(),
+ VERTICAL_ALIGNMENT_STRING_TABLE,
+ VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
+ verticalAlignment );
+ }
+
+
Toolkit::TableView::CellPosition cellPosition;
- if( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
+ if( child.GetPropertyIndex(ROW_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
{
- cellPosition.rowSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) ).Get<float>() );
+ cellPosition.rowSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(ROW_SPAN_PROPERTY_NAME) ).Get<float>() );
}
- if( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
+ if( child.GetPropertyIndex(COLUMN_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
{
- cellPosition.columnSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) ).Get<float>() );
+ cellPosition.columnSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(COLUMN_SPAN_PROPERTY_NAME) ).Get<float>() );
}
- if( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) != Property::INVALID_INDEX )
+ if( child.GetPropertyIndex(CELL_INDEX_PROPERTY_NAME) != Property::INVALID_INDEX )
{
- Vector2 indices = child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) ).Get<Vector2 >();
+ Vector2 indices = child.GetProperty( child.GetPropertyIndex(CELL_INDEX_PROPERTY_NAME) ).Get<Vector2 >();
cellPosition.rowIndex = static_cast<unsigned int>( indices.x );
cellPosition.columnIndex = static_cast<unsigned int>( indices.y );
AddChild( child, cellPosition );
+ SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment);
// Do not continue
+ RelayoutRequest();
return;
}
data.actor = child;
data.position.columnIndex = column;
data.position.rowIndex = row;
+ data.horizontalAlignment = horizontalAlignment;
+ data.verticalAlignment = verticalAlignment;
mCellData[ row ][ column ] = data;
// Don't continue
+ RelayoutRequest();
return;
}
}
data.actor = child;
data.position.rowIndex = rowCount;
data.position.columnIndex = 0;
+ data.horizontalAlignment = horizontalAlignment;
+ data.verticalAlignment = verticalAlignment;
mCellData[ rowCount ][ 0 ] = data;
+ RelayoutRequest();
}
void TableView::OnControlChildRemove( Actor& child )
void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
void(TableView::*funcFixed)(unsigned int, float),
void(TableView::*funcRelative)(unsigned int, float),
+ void(TableView::*funcFit)(unsigned int),
const Property::Value& value )
{
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" );
LAYOUT_POLICY_STRING_TABLE_COUNT,
policy ) )
{
- if( policy == Toolkit::TableView::FIXED )
+ if( policy == Toolkit::TableView::FIXED )
{
- (tableViewImpl.*funcFixed)( rowIndex, value->Get<float>() );
+ (tableViewImpl.*funcFixed)( index, value->Get<float>() );
}
else if( policy == Toolkit::TableView::RELATIVE )
{
- (tableViewImpl.*funcRelative)( rowIndex, value->Get<float>() );
+ (tableViewImpl.*funcRelative)( index, value->Get<float>() );
+ }
+ else if( policy == Toolkit::TableView::FIT )
+ {
+ (tableViewImpl.*funcFit)( index );
}
+ // do nothing for FILL policy
}
}
}
void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map )
{
- 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;
}
}
}
// Apply padding
- cellSize -= mPadding.width * 2.0f;
+ cellSize -= mPadding.height * 2.0f;
if( cellSize < 0.0f )
{
cellSize = 0.0f;
{
RowColumnData& dataInstance = data[ i ];
- if( dataInstance.sizePolicy == FILL )
+ if( dataInstance.sizePolicy == Toolkit::TableView::RELATIVE )
{
- if( dataInstance.userFillRatio )
- {
- relativeTotal += dataInstance.fillRatio;
- }
- else
- {
- fillData.PushBack( &dataInstance );
- }
+ relativeTotal += dataInstance.fillRatio;
+ }
+ else if(dataInstance.sizePolicy == Toolkit::TableView::FILL)
+ {
+ fillData.PushBack( &dataInstance );
}
}
switch( dataInstance.sizePolicy )
{
- case FIXED:
- case FIT:
+ // we have absolute size to FIXED and FIT column/row and relative size for RELATIVE and FILL column/row
+ case Toolkit::TableView::FIXED:
+ case Toolkit::TableView::FIT:
{
totalSize += dataInstance.size;
break;
{
RowColumnData& dataInstance = data[ i ];
- if( dataInstance.sizePolicy == FIT )
+ if( dataInstance.sizePolicy == Toolkit::TableView::FIT )
{
// Find the size of the biggest actor in the row or column
float maxActorHeight = 0.0f;
{
RowColumnData& dataInstance = data[ i ];
- if( dataInstance.sizePolicy == FILL )
+ if( dataInstance.sizePolicy == Toolkit::TableView::FILL || dataInstance.sizePolicy == Toolkit::TableView::RELATIVE)
{
dataInstance.size = dataInstance.fillRatio * size;
}
{
for( unsigned int i = 0, count = data.Size(); i < count; ++i )
{
- if( data[ i ].sizePolicy == FIT )
+ if( data[ i ].sizePolicy == Toolkit::TableView::FIT )
{
return true;
}
public:
/**
- * Enum for the size policies of rows and columns
- */
- enum CellSizePolicy
- {
- FILL, ///< Fill up available space, may have a ratio associated with it
- FIXED, ///< A specific fixed width or height
- FIT ///< Fit around actors in the row or column
- };
-
- /**
* Create a new TableView.
* @return A smart-pointer to the newly allocated TableView.
*/
Size GetCellPadding();
/**
- * @brief Set a row policy
- *
- * @param[in] rowIndex The row to set the policy for
- * @param[in] policy The policy to set
+ * @copydoc Toolkit::TableView::SetFitHeight
*/
- void SetRowPolicy( unsigned int rowIndex, CellSizePolicy policy );
+ void SetFitHeight( unsigned int rowIndex );
/**
- * @brief Querry a row policy
- *
- * @param[in] rowIndex The row to querry
- * @return Return the policy
+ * @copydoc Toolkit::TableView::IsFitHeight
*/
- CellSizePolicy GetRowPolicy( unsigned int rowIndex ) const;
+ bool IsFitHeight( unsigned int rowIndex ) const;
/**
- * @brief Set a column policy
- *
- * @param[in] columnIndex The column to set the policy for
- * @param[in] policy The policy to set
+ * @copydoc Toolkit::TableView::SetFitWidth
*/
- void SetColumnPolicy( unsigned int columnIndex, CellSizePolicy policy );
+ void SetFitWidth( unsigned int columnIndex );
/**
- * @brief Querry a column policy
- *
- * @param[in] columnIndex The column to querry
- * @return Return the policy
+ * @copydoc Toolkit::TableView::IsFitWidth
*/
- CellSizePolicy GetColumnPolicy( unsigned int columnIndex ) const;
+ bool IsFitWidth( unsigned int columnIndex ) const;
/**
* @copydoc Toolkit::TableView::SetFixedWidth
RowColumnData()
: size( 0.0f ),
fillRatio( 0.0f ),
- sizePolicy( FILL ),
- userFillRatio( false )
+ position(0.0f),
+ sizePolicy( Toolkit::TableView::FILL )
{
}
* @param[in] newSize The size to set for this data
* @param[in] newSizePolicy The policy used to interpret the size value
*/
- RowColumnData( float newSize, float newFillRatio, CellSizePolicy newSizePolicy, bool newUserFillRatio )
+ RowColumnData( float newSize, float newFillRatio, Toolkit::TableView::LayoutPolicy newSizePolicy )
: size( newSize ),
fillRatio( newFillRatio ),
- sizePolicy( newSizePolicy ),
- userFillRatio( newUserFillRatio )
+ position(0.0f),
+ sizePolicy( newSizePolicy )
{
}
- float size; ///< Set or calculated size
- float fillRatio; ///< Ratio to fill remaining space
- CellSizePolicy sizePolicy; ///< The size policy used to interpret the size value
- bool userFillRatio : 1; ///< FillRatio was set by user
+ float size; ///< Set or calculated size
+ float fillRatio; ///< Ratio to fill remaining space, only valid with RELATIVE or FILL policy
+ float position; ///< Position of the row/column, this value is updated during every Relayout round
+ Toolkit::TableView::LayoutPolicy sizePolicy; ///< The size policy used to interpret the size value
};
typedef Dali::Vector<RowColumnData> RowColumnArray;
/**
* Called to set the heights/widths property.
* @param[in] tableViewImpl The object whose property is set.
- * @param[in] funcFixed The set function to call, it can be SetFixedHeight or SetFixedWidths.
- * @param[in] funcRelative The set function to call, it can be SetRelativeHeight or SetRelativeWidths.
+ * @param[in] funcFixed The set function to call, it can be SetFixedHeight or SetFixedWidth.
+ * @param[in] funcRelative The set function to call, it can be SetRelativeHeight or SetRelativeWidth.
+ * @param[in] funcFit The set function to call, it can be SetFitHeight or SetFiltWidth.
* @param[in] value The new property value.
*/
static void SetHeightOrWidthProperty( TableView& tableViewImpl,
void(TableView::*funcFixed)(unsigned int, float),
void(TableView::*funcRelative)(unsigned int, float),
+ void(TableView::*funcFit)(unsigned int),
const Property::Value& map );
/**
private: // Data
- Array2d<CellData> mCellData; ///< Data for each cell: Actor, alignment settings etc
+ Array2d<CellData> mCellData; ///< Data for each cell: Actor, alignment settings etc
RowColumnArray mRowData; ///< Data for each row
RowColumnArray mColumnData; ///< Data for each column
Size mPadding; ///< Padding to apply to each cell
bool mLayoutingChild; ///< Can't be a bitfield due to Relayouting lock
- bool mRowColumnDirty : 1; ///< Flag to indicate the row column data is dirty
+ bool mRowColumnDirty : 1; ///< Flag to indicate the row column data is dirty
};
} // namespace Internal
mController = Text::Controller::New( *this );
- mDecorator = Text::Decorator::New( *mController );
+ mDecorator = Text::Decorator::New( *mController,
+ *mController );
mController->GetLayoutEngine().SetLayout( LayoutEngine::SINGLE_LINE_BOX );
#include <dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/controls/buttons/push-button.h>
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
#include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
#include <dali-toolkit/public-api/controls/text-controls/text-label.h>
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" );
BaseHandle Create()
{
- return Toolkit::TextSelectionPopup::New();
+ return Toolkit::TextSelectionPopup::New( Toolkit::TextSelectionPopup::NONE, NULL );
}
// Setup properties, signals and actions using the type-registry.
} // 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();
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
}
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();
}
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();
}
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();
}
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();
}
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();
}
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();
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 )
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;
}
} // 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;
}
{
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.
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");
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 );
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 )
{
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 );
if ( button.enabled )
{
numberOfOptionsAdded++;
- AddOption( button.name, button.caption, button.icon, ( numberOfOptionsAdded < numberOfOptionsRequired ) , showIcons, showCaptions );
+ AddOption( button, ( numberOfOptionsAdded < numberOfOptionsRequired ) , showIcons, showCaptions );
}
}
}
}
}
-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 ),
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/buttons/push-button.h>
#include <dali-toolkit/public-api/controls/table-view/table-view.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
{
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(),
enabled( false )
{}
- ButtonRequirement( Buttons buttonId,
+ ButtonRequirement( Toolkit::TextSelectionPopup::Buttons buttonId,
std::size_t buttonPriority,
const std::string& buttonName,
const std::string& buttonCaption,
enabled( buttonEnabled )
{}
- Buttons id;
+ Toolkit::TextSelectionPopup::Buttons id;
std::size_t priority;
std::string name;
std::string caption;
};
/**
- * @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
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
* @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
* @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();
/**
* Construct a new TextField.
*/
- TextSelectionPopup();
+ TextSelectionPopup( TextSelectionPopupCallbackInterface* callbackInterface );
/**
* A reference counted object may only be deleted by calling Unreference()
std::vector<ButtonRequirement> 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
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
};
#include <dali/public-api/math/vector2.h>
#include <dali/public-api/math/vector4.h>
#include <dali/devel-api/object/type-registry-helper.h>
-#include <iostream>
-#include <libintl.h>
#include <cfloat>
namespace Dali
{
const Dali::Vector2 DEFAULT_MAX_SIZE( 400.0f, 65.0f ); ///< The maximum size of the Toolbar.
-} // namespace
-
BaseHandle Create()
{
return Toolkit::TextSelectionToolbar::New();
DALI_TYPE_REGISTRATION_END()
+} // namespace
+
Dali::Toolkit::TextSelectionToolbar TextSelectionToolbar::New()
{
// Create the implementation, temporarily owned by this handle on stack
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;
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 );
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 )
TextSelectionToolbar::~TextSelectionToolbar()
{
+ mRulerX.Reset();
}
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/public-api/controls/scrollable/scroll-view/scroll-view.h>
#include <dali-toolkit/public-api/controls/table-view/table-view.h>
#include <dali-toolkit/devel-api/controls/text-controls/text-selection-toolbar.h>
/**
* @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)
*/
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
/**
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.
}
}
-void ReplaceBidirectionalInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
void ReorderLines( const Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo,
Vector<LineRun>& lineRuns,
Vector<BidirectionalLineInfoRun>& lineInfoRuns )
}
}
-void ReorderLines( LogicalModel& logicalModel,
- const VisualModel& visualModel,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
bool GetMirroredText( const Vector<Character>& text,
Vector<Character>& mirroredText )
{
Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo );
/**
- * Replaces the bidirectional info from the logical model.
- *
- * @pre The @p model needs to have a text set.
- * @pre The @p model needs to have the line break info set.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in,out] model The text's logical model.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharactersToRemove The number of characters removed from the text.
- * @param[in] numberOfCharactersToInsert The number of characters inserted in the text.
- */
-void ReplaceBidirectionalInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
-
-/**
* Sets the visual to logical map tables.
*
* Any map tables previously set are removed.
Vector<BidirectionalLineInfoRun>& lineInfoRuns );
/**
- * Replaces the visual to logical and logical to visual map tables.
- *
- * @pre The @p logicalModel needs to have a text set.
- * @pre The @p logicalModel needs to have the line break info set.
- * @pre The @p visualModel needs to have the laid-out lines info set.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in,out] logicalModel The text's logical model.
- * @param[in] visualModel The text's visual model.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharactersToRemove The number of characters removed from the text.
- * @param[in] numberOfCharactersToInsert The number of characters inserted in the text.
- */
-void ReorderLines( LogicalModel& logicalModel,
- const VisualModel& visualModel,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
-
-/**
* @brief Replaces any character which could be mirrored.
*
* @param[in] text The text.
offscreenSize.height,
Pixel::RGBA8888 );
+ mOffscreenRootActor.SetSize( size );
+
mImageActor.SetSize( offscreenSize );
mImageActor.SetImage( frameBufferImage );
mRenderTask.SetTargetFrameBuffer( frameBufferImage );
const char* DEFAULT_GRAB_HANDLE_IMAGE_RELEASED( DALI_IMAGE_DIR "insertpoint-icon.png" );
const char* DEFAULT_GRAB_HANDLE_IMAGE_PRESSED( DALI_IMAGE_DIR "insertpoint-icon-pressed.png" );
-const char* DEFAULT_SELECTION_HANDLE_ONE( DALI_IMAGE_DIR "text-input-selection-handle-left.png" );
-const char* DEFAULT_SELECTION_HANDLE_TWO( DALI_IMAGE_DIR "text-input-selection-handle-right.png" );
+const char* DEFAULT_SELECTION_HANDLE_ONE_RELEASED( DALI_IMAGE_DIR "text-input-selection-handle-left.png" );
+const char* DEFAULT_SELECTION_HANDLE_ONE_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-left-press.png" );
+const char* DEFAULT_SELECTION_HANDLE_TWO_RELEASED( DALI_IMAGE_DIR "text-input-selection-handle-right.png" );
+const char* DEFAULT_SELECTION_HANDLE_TWO_PRESSED( DALI_IMAGE_DIR "text-input-selection-handle-right-press.png" );
-const Dali::Vector3 DEFAULT_GRAB_HANDLE_RELATIVE_SIZE( 1.5f, 2.0f, 1.0f );
-const Dali::Vector3 DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE( 1.5f, 1.5f, 1.0f );
+const int DEFAULT_POPUP_OFFSET( -100.0f ); // Vertical offset of Popup from cursor or handles position.
+
+const Dali::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.
grabDisplacementY( 0.f ),
active( false ),
visible( false ),
+ pressed( false ),
flipped( false )
{
}
float grabDisplacementY;
bool active : 1;
bool visible : 1;
+ bool pressed : 1;
bool flipped : 1;
};
- Impl( 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<int>() ),
mHighlightColor( LIGHT_BLUE ),
+ mHighlightPosition( Vector2::ZERO ),
mActiveCursor( ACTIVE_CURSOR_NONE ),
mCursorBlinkInterval( CURSOR_BLINK_INTERVAL ),
mCursorBlinkDuration( 0.0f ),
mCursorBlinkStatus( true ),
mPrimaryCursorVisible( false ),
mSecondaryCursorVisible( false ),
- mSwapSelectionHandles( false )
+ mSwapSelectionHandles( false ),
+ mNotifyEndOfScroll( false )
{
}
if( mPrimaryCursorVisible )
{
Vector2 position = cursor.position;
- if( GRAB_HANDLE == mHandleScrolling )
- {
- if( mScrollDirection == SCROLL_RIGHT )
- {
- position.x = 0.f;
- }
- else
- {
- position.x = size.width;
- }
- }
mPrimaryCursor.SetPosition( position.x,
position.y );
{
Vector2 position = grabHandle.position;
- if( GRAB_HANDLE == mHandleScrolling )
- {
- if( mScrollDirection == SCROLL_RIGHT )
- {
- position.x = 0.f;
- }
- else
- {
- position.x = size.width;
- }
- }
-
const bool isVisible = ( position.x <= size.width ) && ( position.x >= 0.f );
if( isVisible )
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 );
{
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 );
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 );
}
}
}
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 )
{
if( !mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] )
{
- mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE );
+ mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE_RELEASED );
+ }
+ if( !mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] )
+ {
+ mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_ONE_PRESSED );
}
primary.actor = ImageActor::New( mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] );
primary.grabArea.SetName("SelectionHandleOneGrabArea");
#endif
primary.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
+ primary.grabArea.SetParentOrigin( ParentOrigin::TOP_CENTER );
+ primary.grabArea.SetAnchorPoint( AnchorPoint::TOP_CENTER );
primary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE );
- primary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
mTapDetector.Attach( primary.grabArea );
mPanGestureDetector.Attach( primary.grabArea );
{
if( !mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] )
{
- mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO );
+ mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO_RELEASED );
+ }
+ if( !mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] )
+ {
+ mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED] = ResourceImage::New( DEFAULT_SELECTION_HANDLE_TWO_PRESSED );
}
secondary.actor = ImageActor::New( mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] );
secondary.grabArea.SetName("SelectionHandleTwoGrabArea");
#endif
secondary.grabArea.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS );
+ secondary.grabArea.SetParentOrigin( ParentOrigin::TOP_CENTER );
+ secondary.grabArea.SetAnchorPoint( AnchorPoint::TOP_CENTER );
secondary.grabArea.SetSizeModeFactor( DEFAULT_SELECTION_HANDLE_RELATIVE_SIZE );
- secondary.grabArea.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
mTapDetector.Attach( secondary.grabArea );
mPanGestureDetector.Attach( secondary.grabArea );
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 );
{
mController.DecorationEvent( type, HANDLE_RELEASED, x, y );
}
- handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_RELEASED] );
+
+ if( GRAB_HANDLE == type )
+ {
+ handle.actor.SetImage( mHandleImages[type][HANDLE_IMAGE_RELEASED] );
+ }
+ else
+ {
+ HandleType selectionHandleType = type;
+
+ if( mSwapSelectionHandles != handle.flipped )
+ {
+ selectionHandleType = ( LEFT_SELECTION_HANDLE == type ) ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE;
+ }
+
+ handle.actor.SetImage( mHandleImages[selectionHandleType][HANDLE_IMAGE_RELEASED] );
+ }
+ handle.pressed = false;
}
}
{
const TouchPoint& point = event.GetPoint(0);
- if( TouchPoint::Down == point.state &&
- mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED] )
+ if( TouchPoint::Down == point.state )
{
- mHandle[GRAB_HANDLE].actor.SetImage( mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED] );
+ mHandle[GRAB_HANDLE].pressed = true;
+ Image imagePressed = mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_PRESSED];
+ if( imagePressed )
+ {
+ mHandle[GRAB_HANDLE].actor.SetImage( imagePressed );
+ }
}
- else if( TouchPoint::Up == point.state &&
- mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] )
+ else if( TouchPoint::Up == point.state )
{
- mHandle[GRAB_HANDLE].actor.SetImage( mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] );
+ mHandle[GRAB_HANDLE].pressed = false;
+ Image imageReleased = mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED];
+ if( imageReleased )
+ {
+ mHandle[GRAB_HANDLE].actor.SetImage( imageReleased );
+ }
}
}
return true;
}
- bool OnHandleOneTouched( Actor actor, const TouchEvent& touch )
+ bool OnHandleOneTouched( Actor actor, const TouchEvent& event )
{
- // TODO
+ // Switch between pressed/release selection handle images
+ if( event.GetPointCount() > 0 &&
+ mHandle[LEFT_SELECTION_HANDLE].actor )
+ {
+ const TouchPoint& point = event.GetPoint(0);
+
+ const bool flip = mSwapSelectionHandles != mHandle[LEFT_SELECTION_HANDLE].flipped;
+ if( TouchPoint::Down == point.state )
+ {
+ mHandle[LEFT_SELECTION_HANDLE].pressed = true;
+ Image imagePressed = mHandleImages[flip ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED];
+ if( imagePressed )
+ {
+ mHandle[LEFT_SELECTION_HANDLE].actor.SetImage( imagePressed );
+ }
+ }
+ else if( TouchPoint::Up == point.state )
+ {
+ mHandle[LEFT_SELECTION_HANDLE].pressed = false;
+ Image imageReleased = mHandleImages[flip ? RIGHT_SELECTION_HANDLE : LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED];
+ if( imageReleased )
+ {
+ mHandle[LEFT_SELECTION_HANDLE].actor.SetImage( imageReleased );
+ }
+ }
+ }
+
// Consume to avoid pop-ups accidentally closing, when handle is outside of pop-up area
return true;
}
- bool OnHandleTwoTouched( Actor actor, const TouchEvent& touch )
+ bool OnHandleTwoTouched( Actor actor, const TouchEvent& event )
{
- // TODO
+ // Switch between pressed/release selection handle images
+ if( event.GetPointCount() > 0 &&
+ mHandle[RIGHT_SELECTION_HANDLE].actor )
+ {
+ const TouchPoint& point = event.GetPoint(0);
+
+ const bool flip = mSwapSelectionHandles != mHandle[RIGHT_SELECTION_HANDLE].flipped;
+ if( TouchPoint::Down == point.state )
+ {
+ Image imagePressed = mHandleImages[flip ? LEFT_SELECTION_HANDLE : RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_PRESSED];
+ mHandle[RIGHT_SELECTION_HANDLE].pressed = true;
+ if( imagePressed )
+ {
+ mHandle[RIGHT_SELECTION_HANDLE].actor.SetImage( imagePressed );
+ }
+ }
+ else if( TouchPoint::Up == point.state )
+ {
+ Image imageReleased = mHandleImages[flip ? LEFT_SELECTION_HANDLE : RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED];
+ mHandle[RIGHT_SELECTION_HANDLE].pressed = false;
+ if( imageReleased )
+ {
+ mHandle[RIGHT_SELECTION_HANDLE].actor.SetImage( imageReleased );
+ }
+ }
+ }
+
// Consume to avoid pop-ups accidentally closing, when handle is outside of pop-up area
return true;
}
// if can't be positioned above, then position below row.
alternativeYPosition = AlternatePopUpPositionRelativeToCursor();
- mCopyPastePopup.SetY( alternativeYPosition );
+ mCopyPastePopup.actor.SetY( alternativeYPosition );
}
- void SetUpPopUpPositionNotifications( )
+ void SetUpPopupPositionNotifications( )
{
// Note Property notifications ignore any set anchor point so conditions must allow for this. Default is Top Left.
Vector4 worldCoordinatesBoundingBox;
LocalToWorldCoordinatesBoundingBox( mBoundingBox, worldCoordinatesBoundingBox );
- float popupHeight = mCopyPastePopup.GetRelayoutSize( Dimension::HEIGHT);
+ float popupHeight = mCopyPastePopup.actor.GetRelayoutSize( Dimension::HEIGHT);
- PropertyNotification verticalExceedNotification = mCopyPastePopup.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y,
- OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight/2,
- worldCoordinatesBoundingBox.w - popupHeight/2 ) );
+ PropertyNotification verticalExceedNotification = mCopyPastePopup.actor.AddPropertyNotification( Actor::Property::WORLD_POSITION_Y,
+ OutsideCondition( worldCoordinatesBoundingBox.y + popupHeight * 0.5f,
+ worldCoordinatesBoundingBox.w - popupHeight * 0.5f ) );
verticalExceedNotification.NotifySignal().Connect( this, &Decorator::Impl::PopUpLeavesVerticalBoundary );
}
}
requiredPopupPosition.x = requiredPopupPosition.x + xOffSetToKeepWithinBounds;
+
+ // Prevent pixel mis-alignment by rounding down.
+ requiredPopupPosition.x = static_cast<int>( requiredPopupPosition.x );
+ requiredPopupPosition.y = static_cast<int>( requiredPopupPosition.y );
+
+ }
+
+ void FlipSelectionHandleImages()
+ {
+ SetupTouchEvents();
+
+ CreateSelectionHandles();
+
+ HandleImpl& leftHandle = mHandle[LEFT_SELECTION_HANDLE];
+ HandleImpl& rightHandle = mHandle[RIGHT_SELECTION_HANDLE];
+
+ const HandleImageType leftImageType = leftHandle.pressed ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED;
+ const HandleImageType rightImageType = rightHandle.pressed ? HANDLE_IMAGE_PRESSED : HANDLE_IMAGE_RELEASED;
+ const bool leftFlipped = mSwapSelectionHandles != leftHandle.flipped;
+ const bool rightFlipped = mSwapSelectionHandles != rightHandle.flipped;
+
+ leftHandle.actor.SetImage( leftFlipped ? mHandleImages[RIGHT_SELECTION_HANDLE][leftImageType] : mHandleImages[LEFT_SELECTION_HANDLE][leftImageType] );
+
+ leftHandle.actor.SetAnchorPoint( leftFlipped ? AnchorPoint::TOP_LEFT : AnchorPoint::TOP_RIGHT );
+
+ rightHandle.actor.SetImage( rightFlipped ? mHandleImages[LEFT_SELECTION_HANDLE][rightImageType] : mHandleImages[RIGHT_SELECTION_HANDLE][rightImageType] );
+
+ rightHandle.actor.SetAnchorPoint( rightFlipped ? AnchorPoint::TOP_RIGHT : AnchorPoint::TOP_LEFT );
}
void SetScrollThreshold( float threshold )
return mScrollSpeed;
}
+ void NotifyEndOfScroll()
+ {
+ StopScrollTimer();
+
+ if( mScrollTimer )
+ {
+ mNotifyEndOfScroll = true;
+ }
+ }
+
/**
* Creates and starts a timer to scroll the text when handles are close to the edges of the text.
*
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;
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<int> mBoundingBox;
Vector4 mHighlightColor; ///< Color of the highlight
+ Vector2 mHighlightPosition; ///< The position of the highlight actor.
unsigned int mActiveCursor;
unsigned int mCursorBlinkInterval;
float mScrollThreshold; ///< Defines a square area inside the control, close to the edge. A cursor entering this area will trigger scroll events.
float mScrollSpeed; ///< The scroll speed in pixels per second.
float mScrollDistance; ///< Distance the text scrolls during a scroll interval.
- unsigned int mScrollInterval; ///< Time in milliseconds of a scroll interval.
bool mActiveCopyPastePopup : 1;
bool mCursorBlinkStatus : 1; ///< Flag to switch between blink on and blink off.
bool mPrimaryCursorVisible : 1; ///< Whether the primary cursor is visible.
bool mSecondaryCursorVisible : 1; ///< Whether the secondary cursor is visible.
bool mSwapSelectionHandles : 1; ///< Whether to swap the selection handle images.
+ bool mNotifyEndOfScroll : 1; ///< Whether to notify the end of the scroll.
};
-DecoratorPtr Decorator::New( 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<int>& boundingBox )
void Decorator::SwapSelectionHandlesEnabled( bool enable )
{
mImpl->mSwapSelectionHandles = enable;
+
+ mImpl->FlipSelectionHandleImages();
}
void Decorator::AddHighlight( float x1, float y1, float x2, float y2 )
return mImpl->mActiveCopyPastePopup ;
}
+void Decorator::SetEnabledPopupButtons( TextSelectionPopup::Buttons& enabledButtonsBitMask )
+{
+ mImpl->mEnabledPopupButtons = enabledButtonsBitMask;
+}
+
+TextSelectionPopup::Buttons& Decorator::GetEnabledPopupButtons()
+{
+ return mImpl->mEnabledPopupButtons;
+}
+
/** Scroll **/
void Decorator::SetScrollThreshold( float threshold )
return mImpl->GetScrollSpeed();
}
+void Decorator::NotifyEndOfScroll()
+{
+ mImpl->NotifyEndOfScroll();
+}
+
Decorator::~Decorator()
{
delete mImpl;
}
-Decorator::Decorator( ControllerInterface& controller )
+Decorator::Decorator( ControllerInterface& controller,
+ TextSelectionPopupCallbackInterface& callbackInterface )
: mImpl( NULL )
{
- mImpl = new Decorator::Impl( controller );
+ mImpl = new Decorator::Impl( controller, callbackInterface );
}
} // namespace Text
#include <dali/public-api/math/rect.h>
#include <dali/public-api/math/vector2.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup.h>
+
namespace Dali
{
namespace Toolkit
{
+class TextSelectionPopupCallbackInterface;
+
namespace Internal
{
class Control;
* @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.
bool IsPopupActive() const;
/**
+ * @brief Set a bit mask of the buttons to be shown by Popup
+ * @param[in] enabledButtonsBitMask from TextSelectionPopup::Buttons enum
+ */
+ void SetEnabledPopupButtons( TextSelectionPopup::Buttons& enabledButtonsBitMask );
+
+ /**
+ * @brief Get the current bit mask of buttons to be shown by Popup
+ * @return bitmask of TextSelectionPopup::Buttons
+ */
+ TextSelectionPopup::Buttons& GetEnabledPopupButtons();
+
+ /**
* @brief Sets the scroll threshold.
*
* It defines a square area inside the control, close to the edge.
float GetScrollSpeed() const;
/**
- * @brief Sets the scroll interval.
- *
- * @param[in] seconds The scroll interval in seconds.
- */
- void SetScrollTickInterval( float seconds );
-
- /**
- * @brief Retrieves the scroll interval.
- *
- * @return The scroll interval.
+ * @brief Notifies the decorator the whole text has been scrolled.
*/
- float GetScrollTickInterval() const;
+ void NotifyEndOfScroll();
protected:
/**
* @brief Private constructor.
* @param[in] 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 );
return LogicalModelPtr( new LogicalModel() );
}
-void LogicalModel::SetText( const Character* const text,
- Length numberOfCharacters )
-{
- if( 0u == numberOfCharacters )
- {
- mText.Clear();
- }
- else
- {
- mText.Resize( numberOfCharacters );
- memcpy( mText.Begin(), text, numberOfCharacters * sizeof( Character ) );
- }
-}
-
-Length LogicalModel::GetNumberOfCharacters() const
-{
- return mText.Count();
-}
-
-void LogicalModel::GetText( Character* text,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- memcpy( text, mText.Begin() + characterIndex, numberOfCharacters * sizeof( Character ) );
-}
-
-Character LogicalModel::GetCharacter( CharacterIndex characterIndex ) const
-{
- return mText[characterIndex];
-}
-
-void LogicalModel::ReplaceText( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const Character* const text,
- Length numberOfCharactersToInsert )
-{
-}
-
-void LogicalModel::SetScripts( const ScriptRun* const scripts,
- Length numberOfRuns )
-{
- if( 0u == numberOfRuns )
- {
- mScriptRuns.Clear();
- }
- else
- {
- mScriptRuns.Resize( numberOfRuns );
- memcpy( mScriptRuns.Begin(), scripts, numberOfRuns * sizeof( ScriptRun ) );
- }
-}
-
-void LogicalModel::GetNumberOfScriptRuns( CharacterIndex characterIndex,
- Length numberOfCharacters,
- ScriptRunIndex& firstScriptRun,
- Length& numberOfScriptRuns ) const
-{
- // Initialize the number of scripts and the index to the first script.
- firstScriptRun = 0u;
- numberOfScriptRuns = 0;
- bool firstScriptFound = false;
-
- const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters;
-
- // Traverse the scripts and count those scripts within the range of characters.
- for( Vector<ScriptRun>::ConstIterator it = mScriptRuns.Begin(),
- endIt = mScriptRuns.End();
- it != endIt;
- ++it )
- {
- const ScriptRun& script = *it;
-
- if( ( script.characterRun.characterIndex + script.characterRun.numberOfCharacters > characterIndex ) &&
- ( lastCharacterIndex > script.characterRun.characterIndex ) )
- {
- firstScriptFound = true;
- ++numberOfScriptRuns;
- }
- else if( lastCharacterIndex <= script.characterRun.characterIndex )
- {
- // nothing else to do.
- break;
- }
-
- if( !firstScriptFound )
- {
- ++firstScriptRun;
- }
- }
-}
-
-void LogicalModel::GetScriptRuns( ScriptRun* scriptRuns,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- ScriptRunIndex firstScriptRun = 0u;
- Length numberOfScriptRuns = 0u;
-
- GetNumberOfScriptRuns( characterIndex,
- numberOfCharacters,
- firstScriptRun,
- numberOfScriptRuns );
-
- memcpy( scriptRuns, mScriptRuns.Begin() + firstScriptRun, numberOfScriptRuns * sizeof( ScriptRun ) );
-}
-
Script LogicalModel::GetScript( CharacterIndex characterIndex ) const
{
// If this operation is too slow, consider a binary search.
return TextAbstraction::UNKNOWN;
}
-void LogicalModel::ReplaceScripts( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const ScriptRun* const scriptRuns,
- Length numberOfCharactersToInsert )
-{
-}
-
-void LogicalModel::SetFonts( const FontRun* const fonts,
- Length numberOfRuns )
-{
- if( 0u == numberOfRuns )
- {
- mFontRuns.Clear();
- }
- else
- {
- mFontRuns.Resize( numberOfRuns );
- memcpy( mFontRuns.Begin(), fonts, numberOfRuns * sizeof( FontRun ) );
- }
-}
-
-void LogicalModel::GetNumberOfFontRuns( CharacterIndex characterIndex,
- Length numberOfCharacters,
- FontRunIndex& firstFontRun,
- Length& numberOfFontRuns ) const
-{
- // Initialize the number of fonts and the index to the first font.
- firstFontRun = 0u;
- numberOfFontRuns = 0;
- bool firstFontFound = false;
-
- const CharacterIndex lastCharacterIndex = characterIndex + numberOfCharacters;
-
- // Traverse the fonts and count those fonts within the range of characters.
- for( Vector<FontRun>::ConstIterator it = mFontRuns.Begin(),
- endIt = mFontRuns.End();
- it != endIt;
- ++it )
- {
- const FontRun& font = *it;
-
- if( ( font.characterRun.characterIndex + font.characterRun.numberOfCharacters > characterIndex ) &&
- ( characterIndex + numberOfCharacters > font.characterRun.characterIndex ) )
- {
- firstFontFound = true;
- ++numberOfFontRuns;
- }
- else if( lastCharacterIndex <= font.characterRun.characterIndex )
- {
- // nothing else to do.
- break;
- }
-
- if( !firstFontFound )
- {
- ++firstFontRun;
- }
- }
-}
-
-void LogicalModel::GetFontRuns( FontRun* fontRuns,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- FontRunIndex firstFontRun = 0u;
- Length numberOfFontRuns = 0u;
-
- GetNumberOfFontRuns( characterIndex,
- numberOfCharacters,
- firstFontRun,
- numberOfFontRuns );
-
- memcpy( fontRuns, mFontRuns.Begin() + firstFontRun, numberOfFontRuns * sizeof( FontRun ) );
-}
-
-FontId LogicalModel::GetFont( CharacterIndex characterIndex ) const
-{
- for( Length index = 0u, length = mFontRuns.Count(); index < length; ++index )
- {
- const FontRun* const fontRun = mFontRuns.Begin() + index;
-
- if( ( fontRun->characterRun.characterIndex <= characterIndex ) &&
- ( characterIndex < fontRun->characterRun.characterIndex + fontRun->characterRun.numberOfCharacters ) )
- {
- return fontRun->fontId;
- }
- }
-
- return 0u;
-}
-
-void LogicalModel::ReplaceFonts( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const FontRun* const fontRuns,
- Length numberOfCharactersToInsert )
-{
-}
-
-void LogicalModel::SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
- Length length )
-{
- if( 0u == length )
- {
- mLineBreakInfo.Clear();
- }
- else
- {
- mLineBreakInfo.Resize( length );
- memcpy( mLineBreakInfo.Begin(), lineBreakInfo, length * sizeof( LineBreakInfo ) );
- }
-}
-
-void LogicalModel::GetLineBreakInfo( LineBreakInfo* lineBreakInfo,
- CharacterIndex characterIndex,
- Length numberOfItems ) const
-{
- memcpy( lineBreakInfo, mLineBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( LineBreakInfo ) );
-}
-
-LineBreakInfo LogicalModel::GetLineBreakInfo( CharacterIndex characterIndex ) const
-{
- return *( mLineBreakInfo.Begin() + characterIndex );
-}
-
-void LogicalModel::ReplaceLineBreakInfo( CharacterIndex characterIndex,
- Length numberOfItemsToRemove,
- const LineBreakInfo* const lineBreakInfo,
- Length numberOfItemsToInsert )
-{
-}
-
-void LogicalModel::SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
- Length length )
-{
- if( 0u == length )
- {
- mWordBreakInfo.Clear();
- }
- else
- {
- mWordBreakInfo.Resize( length );
- memcpy( mWordBreakInfo.Begin(), wordBreakInfo, length * sizeof( WordBreakInfo ) );
- }
-}
-
-void LogicalModel::GetWordBreakInfo( WordBreakInfo* wordBreakInfo,
- CharacterIndex characterIndex,
- Length numberOfItems ) const
-{
- memcpy( wordBreakInfo, mWordBreakInfo.Begin() + characterIndex, numberOfItems * sizeof( WordBreakInfo ) );
-}
-
-WordBreakInfo LogicalModel::GetWordBreakInfo( CharacterIndex characterIndex ) const
-{
- return *( mWordBreakInfo.Begin() + characterIndex );
-}
-
-void LogicalModel::ReplaceWordBreakInfo( CharacterIndex characterIndex,
- Length numberOfItemsToRemove,
- const WordBreakInfo* const wordBreakInfo,
- Length numberOfItemsToInsert )
-{
-}
-
-void LogicalModel::SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
- Length numberOfRuns )
-{
- if( 0u == numberOfRuns )
- {
- mBidirectionalParagraphInfo.Clear();
- }
- else
- {
- mBidirectionalParagraphInfo.Resize( numberOfRuns );
- memcpy( mBidirectionalParagraphInfo.Begin(), bidirectionalInfo, numberOfRuns * sizeof( BidirectionalParagraphInfoRun ) );
- }
-}
-
-void LogicalModel::GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
- Length numberOfCharacters,
- BidirectionalRunIndex& firstBidirectionalRun,
- Length& numberOfFontRuns ) const
-{
- // Initialize the number of bidi paragraphs and the index to the first paragraph.
- firstBidirectionalRun = 0u;
- numberOfFontRuns = 0;
- bool firstParagraphFound = false;
-
- // Traverse the bidirectional paragraph info and count those bidi paragraphs within the range of characters.
- for( Vector<BidirectionalParagraphInfoRun>::ConstIterator it = mBidirectionalParagraphInfo.Begin(),
- endIt = mBidirectionalParagraphInfo.End();
- it != endIt;
- ++it )
- {
- const BidirectionalParagraphInfoRun& bidi = *it;
-
- if( ( bidi.characterRun.characterIndex + bidi.characterRun.numberOfCharacters > characterIndex ) &&
- ( characterIndex + numberOfCharacters > bidi.characterRun.characterIndex ) )
- {
- firstParagraphFound = true;
- ++numberOfFontRuns;
- }
-
- if( !firstParagraphFound )
- {
- ++firstBidirectionalRun;
- }
- }
-}
-
-void LogicalModel::GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- BidirectionalRunIndex firstBidirectionalRun = 0u;
- Length numberOfFontRuns = 0u;
-
- GetNumberOfBidirectionalInfoRuns( characterIndex,
- numberOfCharacters,
- firstBidirectionalRun,
- numberOfFontRuns );
-
- memcpy( bidirectionalInfo, mBidirectionalParagraphInfo.Begin() + firstBidirectionalRun, numberOfFontRuns * sizeof( BidirectionalParagraphInfoRun ) );
-}
-
-void ReplaceBidirectionalInfo( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const BidirectionalParagraphInfoRun* const bidirectionalInfo,
- Length numberOfCharactersToInsert )
-{
-}
-
-void LogicalModel::SetCharacterDirections( const CharacterDirection* const directions,
- Length numberOfCharacters )
-{
- if( 0u == numberOfCharacters )
- {
- mCharacterDirections.Clear();
- }
- else
- {
- mCharacterDirections.Resize( numberOfCharacters );
- memcpy( mCharacterDirections.Begin(), directions, numberOfCharacters * sizeof( CharacterDirection ) );
- }
-}
-
-void LogicalModel::GetCharacterDirections( CharacterDirection* directions,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- if( 0u == mCharacterDirections.Count() )
- {
- // Nothing to retrieve if the model has no right to left characters.
- return;
- }
-
- memcpy( directions, mCharacterDirections.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterDirection ) );
-}
-
CharacterDirection LogicalModel::GetCharacterDirection( CharacterIndex characterIndex ) const
{
if( characterIndex >= mCharacterDirections.Count() )
}
}
-void LogicalModel::ReplaceVisualToLogicalMap( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const BidirectionalLineInfoRun* const bidirectionalInfo,
- Length numberOfCharactersToInsert )
-{
-}
-
-CharacterIndex LogicalModel::GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const
-{
- if( 0u == mLogicalToVisualMap.Count() )
- {
- // If there is no logical to visual info is because the whole text is left to right.
- // Return the identity.
- return logicalCharacterIndex;
- }
-
- return *( mLogicalToVisualMap.Begin() + logicalCharacterIndex );
-}
-
CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
{
if( 0u == mVisualToLogicalMap.Count() )
return *( mVisualToLogicalMap.Begin() + visualCharacterIndex );
}
-void LogicalModel::GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- memcpy( logicalToVisualMap, mLogicalToVisualMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) );
-}
-
-void LogicalModel::GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- memcpy( visualToLogicalMap, mVisualToLogicalMap.Begin() + characterIndex, numberOfCharacters * sizeof( CharacterIndex ) );
-}
-
LogicalModel::~LogicalModel()
{
}
*/
static LogicalModelPtr New();
- // Text interface.
-
- /**
- * @brief Replaces any text previously set.
- *
- * @note If the number of characters is zero the text buffer is cleared.
- *
- * @param[in] text An array of UTF-32 characters.
- * @param[in] numberOfCharacters The length of the array.
- */
- void SetText( const Character* const text,
- Length numberOfCharacters );
-
- /**
- * @brief Retrieves the number of characters of the text.
- *
- * @return The number of characters.
- */
- Length GetNumberOfCharacters() const;
-
- /**
- * @brief Retrieves characters from the text in the given buffer.
- *
- * @pre The size of the @p text buffer needs to be big enough to copy the @p numberOfCharacters.
- * @param[out] text Pointer to a buffer where the text is copied.
- * @param[in] characterIndex The index to the first character to copy.
- * @param[in] numberOfCharacters The number of characters to be copied.
- */
- void GetText( Character* text,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const;
-
- /**
- * @brief Retrieves a character.
- *
- * @param[in] characterIndex Index to a character.
- *
- * @return A character.
- */
- Character GetCharacter( CharacterIndex characterIndex ) const;
-
- /**
- * @brief Replaces characters from the text.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in] characterIndex Where to replace the text.
- * @param[in] numberOfCharactersToRemove The number of characters to be removed.
- * @param[in] text Pointer to a buffer with the text encoded in utf32.
- * @param[in] numberOfCharactersToInsert The number of characters in the buffer.
- */
- void ReplaceText( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const Character* const text,
- Length numberOfCharactersToInsert );
-
// Language support interface.
/**
- * @brief Sets the script runs.
- *
- * Replaces any scripts previously set.
- *
- * A run is a group of consecutive characters. A script run contains the script for a run.
- *
- * @note If the number of runs is zero the script buffer is cleared.
- *
- * @param[in] scripts Pointer to a buffer with all the script runs.
- * @param[in] numberOfRuns The number of script runs.
- */
- void SetScripts( const ScriptRun* const scripts,
- Length numberOfRuns );
-
- /**
- * @brief Retrieves the number of script runs and the index to the first one for the given range of characters.
- *
- * A run is a group of consecutive characters. A script run contains the script for a run.
- *
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- * @param[out] firstScriptRun Index to the script run containing the character index.
- * @param[out] numberOfScriptRuns The number of script runs.
- */
- void GetNumberOfScriptRuns( CharacterIndex characterIndex,
- Length numberOfCharacters,
- ScriptRunIndex& firstScriptRun,
- Length& numberOfScriptRuns ) const;
-
- /**
- * @brief Retrieves the script runs for the given range of characters.
- *
- * The @p scriptRuns buffer needs to be big enough to copy the number of script runs.
- * Call GetNumberOfScriptRuns() to retrieve the number of script runs.
- *
- * @param[out] scriptRuns Pointer to a buffer where the script runs are copied.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- */
- void GetScriptRuns( ScriptRun* scriptRuns,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const;
-
- /**
* @brief Retrieves the script for the given character index.
*
* @param[in] characterIndex Index to the character.
*/
Script GetScript( CharacterIndex characterIndex ) const;
- /**
- * @brief Replaces script runs for the given range of characters.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in] characterIndex Index of the first character where to replace the scripts.
- * @param[in] numberOfCharactersToRemove The number of characters to be the script removed.
- * @param[in] scriptRuns Pointer to a buffer with the script runs.
- * @param[in] numberOfCharactersToInsert The number of characters to be the script inserted.
- */
- void ReplaceScripts( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const ScriptRun* const scriptRuns,
- Length numberOfCharactersToInsert );
-
- /**
- * @brief Sets the font runs.
- *
- * Replaces any fonts previously set.
- *
- * A run is a group of consecutive characters. A font run contains the font id for a run.
- *
- * @note If the number of runs is zero the font buffer is cleared.
- *
- * @param[in] fonts Pointer to a buffer with all the font runs.
- * @param[in] numberOfRuns The number of font runs.
- */
- void SetFonts( const FontRun* const fonts,
- Length numberOfRuns );
-
- /**
- * @brief Retrieves the number of font runs and the index of the first one for the given range of characters.
- *
- * A run is a group of consecutive characters. A font run contains the font id for a run.
- *
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- * @param[out] firstFontRun Index to the font run containing the character index.
- * @param[out] numberOfFontRuns The number of font runs.
- */
- void GetNumberOfFontRuns( CharacterIndex characterIndex,
- Length numberOfCharacters,
- FontRunIndex& firstFontRun,
- Length& numberOfFontRuns ) const;
-
- /**
- * @brief Retrieves the font runs for the given range of characters.
- *
- * The @p fontRuns buffer needs to be big enough to copy the number of font runs.
- * Call GetNumberOfFontRuns() to retrieve the number of font runs.
- *
- * @param[out] fontRuns Pointer to a buffer where the font runs are copied.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- */
- void GetFontRuns( FontRun* fontRuns,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const;
-
- /**
- * @brief Retrieves the font id for the given character index.
- *
- * @param[in] characterIndex Index to the first character.
- *
- * @return The font id.
- */
- FontId GetFont( CharacterIndex characterIndex ) const;
-
- /**
- * @brief Replaces font runs for the given range of characters.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in] characterIndex Index of the first character where to replace the fonts.
- * @param[in] numberOfCharactersToRemove The number of characters to be the font removed.
- * @param[in] fontRuns Pointer to a buffer with the font runs.
- * @param[in] numberOfCharactersToInsert The number of characters to be the font inserted.
- */
- void ReplaceFonts( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const FontRun* const fontRuns,
- Length numberOfCharactersToInsert );
-
- // Break info interface.
-
- /**
- * @brief Sets the line break info.
- *
- * See GetLineBreakInfo() to get how the line break info is encoded.
- *
- * Replaces any line break info previously set.
- *
- * @note If the @length is zero the break info buffer is cleared.
- *
- * @param[in] lineBreakInfo Pointer to a buffer with the line break info.
- * @param[in] length The size of the buffer.
- */
- void SetLineBreakInfo( const LineBreakInfo* const lineBreakInfo,
- Length length );
-
- /**
- * @brief Retrieves the line break info in the given buffer.
- *
- * The size of the @p lineBreakInfo buffer needs to be big enough to copy the @p numberOfItems.
- *
- * Possible values for LineBreakInfo are:
- *
- * - 0 is a LINE_MUST_BREAK. Text must be broken into a new line.
- * - 1 is a LINE_ALLOW_BREAK. Is possible to break the text into a new line.
- * - 2 is a LINE_NO_BREAK. Text can't be broken into a new line.
- *
- @verbatim
- i.e. Hello big\nworld produces:
- 2222212220 22220
- @endverbatim
- *
- * @param[out] lineBreakInfo Pointer to a buffer where the line break info is copied.
- * @param[in] characterIndex Index to the first line break info item.
- * @param[in] numberOfItems The number of items to be copied.
- */
- void GetLineBreakInfo( LineBreakInfo* lineBreakInfo,
- CharacterIndex characterIndex,
- Length numberOfItems ) const;
-
- /**
- * @brief Retrieves the line break info for the given item index.
- *
- * @param[in] characterIndex Index to the line break info item.
- */
- LineBreakInfo GetLineBreakInfo( CharacterIndex characterIndex ) const;
-
- /**
- * @brief Replaces line break info.
- *
- * See GetLineBreakInfo() to get how the line break info is encoded.
- *
- * If the @p numberOfItemsToRemove is zero, this operation is like an insert.
- * If the @p numberOfItemsToInsert is zero, this operation is like a remove.
- *
- * @param[in] characterIndex Where to replace the line break info.
- * @param[in] numberOfItemsToRemove The number of items to be removed.
- * @param[in] lineBreakInfo Pointer to a buffer with the line break info.
- * @param[in] numberOfItemsToInsert The number of items in the buffer.
- */
- void ReplaceLineBreakInfo( CharacterIndex characterIndex,
- Length numberOfItemsToRemove,
- const LineBreakInfo* const lineBreakInfo,
- Length numberOfItemsToInsert );
-
- /**
- * @brief Sets the word break info.
- *
- * See GetWordBreakInfo() to get how the word break info is encoded.
- *
- * Replaces any word break info previously set.
- *
- * @note If the @length is zero the break info buffer is cleared.
- *
- * @param[in] wordBreakInfo Pointer to a buffer with the word break info.
- * @param[in] length The size of the buffer.
- */
- void SetWordBreakInfo( const WordBreakInfo* const wordBreakInfo,
- Length length );
-
- /**
- * @brief Retrieves the word break info in the given buffer.
- *
- * The size of the @p wordBreakInfo buffer needs to be big enough to copy the @p numberOfItems.
- *
- * The size of the buffer has to be big enough to store the whole word break info per character.
- * Call GetNumberOfCharacters() to get the number of characters.
- *
- * Possible values for WordBreakInfo are:
- *
- * - 0 is a WORD_BREAK. Text can be broken into a new word.
- * - 1 is a WORD_NO_BREAK. Text can't be broken into a new word.
- *
- @verbatim
- i.e. Hello big\nworld produces:
- 1111001100 11110
- @endverbatim
- *
- * @param[out] wordBreakInfo Pointer to a buffer where the word break info is copied.
- * @param[in] characterIndex Index to the first word break info item.
- * @param[in] numberOfItems The number of items to be copied.
- */
- void GetWordBreakInfo( WordBreakInfo* wordBreakInfo,
- CharacterIndex characterIndex,
- Length numberOfItems ) const;
-
- /**
- * @brief Retrieves the word break info for the given item index.
- *
- * @param[in] characterIndex Index to the word break info item.
- */
- WordBreakInfo GetWordBreakInfo( CharacterIndex characterIndex ) const;
-
- /**
- * @brief Replaces word break info.
- *
- * See GetWordBreakInfo() to get how the word break info is encoded.
- *
- * If the @p numberOfItemsToRemove is zero, this operation is like an insert.
- * If the @p numberOfItemsToInsert is zero, this operation is like a remove.
- *
- * @param[in] characterIndex Where to replace the word break info.
- * @param[in] numberOfItemsToRemove The number of items to be removed.
- * @param[in] wordBreakInfo Pointer to a buffer with the word break info.
- * @param[in] numberOfItemsToInsert The number of items in the buffer.
- */
- void ReplaceWordBreakInfo( CharacterIndex characterIndex,
- Length numberOfItemsToRemove,
- const WordBreakInfo* const wordBreakInfo,
- Length numberOfItemsToInsert );
-
// Bidirectional support interface.
/**
- * @brief Sets the bidirectional info runs.
- *
- * Replaces any bidirectional info previously set.
- *
- * Each bidirectional info run stores bidirectional info for a whole 'paragraph' of text which contains right to left scripts.
-
- * In terms of the bidirectional algorithm, a 'paragraph' is understood as a run of characters between Paragraph Separators or appropriate Newline Functions.
- * A 'paragraph' may also be determined by higher-level protocols like a mark-up tag.
- *
- * @note If the number of runs is zero the bidirectional info buffer is cleared.
- *
- * @param[in] bidirectionalInfo Pointer to a buffer with all the bidirectional info runs.
- * @param[in] numberOfRuns The number of bidirectional info runs.
- */
- void SetBidirectionalInfo( const BidirectionalParagraphInfoRun* const bidirectionalInfo,
- Length numberOfRuns );
-
- /**
- * @brief Retrieves the number of bidirectional info runs and the index to the first one for the given range of characters.
- *
- * It may be zero if there is no right to left scripts.
- *
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- *
- * @return The number of bidirectional info runs.
- */
- void GetNumberOfBidirectionalInfoRuns( CharacterIndex characterIndex,
- Length numberOfCharacters,
- BidirectionalRunIndex& firstBidirectionalRun,
- Length& numberOfFontRuns ) const;
-
- /**
- * @brief Retrieves the bidirectional paragraph info runs for the given range of characters.
- *
- * The @p bidirectionalInfo buffer needs to be big enough to copy the number of bidirectional
- * paragraph info runs.
- * Call GetNumberOfBidirectionalInfoRuns() to retrieve the number of bidirectional runs.
- *
- * @param[out] bidirectionalInfo Pointer to a buffer where the bidirectional info runs are copied.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- */
- void GetBidirectionalInfo( BidirectionalParagraphInfoRun* bidirectionalInfo,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const;
-
- /**
- * @brief Replaces bidirectional info runs for the given range of characters.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in] characterIndex Index of the first character where to replace the bidirectional info.
- * @param[in] numberOfCharactersToRemove The number of characters to be the bidirectional info removed.
- * @param[in] bidirectionalInfo Pointer to a buffer with the bidirectional info runs.
- * @param[in] numberOfCharactersToInsert The number of characters to be the bidirectional info inserted.
- */
- void ReplaceBidirectionalInfo( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const BidirectionalParagraphInfoRun* const bidirectionalInfo,
- Length numberOfCharactersToInsert );
-
- /**
- * @brief Replaces the direction of the characters.
- *
- * @note If the number of characters is zero the directions buffer is cleared.
- *
- * @param[in] directions The directions of the characters.
- * @param[in] numberOfCharacters The number of characters.
- */
- void SetCharacterDirections( const CharacterDirection* const directions,
- Length numberOfCharacters );
-
- /**
- * @brief Retrieves the direction of the characters.
- *
- * It sets @e true for right to left characters and @e false for left to right.
- * For neutral characters it check's the next and previous character's directions:
- * - If they are equals set that direction. If they are not, sets the paragraph's direction.
- * - If there is no next, sets the paragraph's direction.
- *
- * See SetBidirectionalInfo() to get an explanation of the 'paragraph' meaning in the bidirectional algorithm.
- *
- * @pre the @p directions vector should be initialized to @e false (left to right) as this method is not going
- * to update it if there is no right to left characters.
- *
- * @param[out] directions Whether the characters are right to left or left to right.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- */
- void GetCharacterDirections( CharacterDirection* directions,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const;
-
- /**
* @brief Retrieves the direction of a characters.
*
* See GetCharacterDirections().
Length numberOfRuns );
/**
- * @brief Replaces the visual to logical and logical to visual map tables for the given range of characters.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in] characterIndex Index of the first character where to replace the map tables.
- * @param[in] numberOfCharactersToRemove The number of characters to be removed.
- * @param[in] bidirectionalInfo Pointer to a buffer with the bidirectional info runs.
- * @param[in] numberOfCharactersToInsert The number of characters to be inserted.
- */
- void ReplaceVisualToLogicalMap( CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- const BidirectionalLineInfoRun* const bidirectionalInfo,
- Length numberOfCharactersToInsert );
-
- /**
- * @brief Retrieves the visual character index for the given logical character index.
- *
- * @param[in] logicalCharacterIndex The logical character index.
- *
- * @return The visual character index.
- */
- CharacterIndex GetVisualCharacterIndex( CharacterIndex logicalCharacterIndex ) const;
-
- /**
* @brief Retrieves the logical character index for the given visual character index.
*
* @param[in] visualCharacterIndex The visual character index.
*/
CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const;
- /**
- * @brief Retrieves the whole or part of the logical to visual conversion map.
- *
- * The size of the buffer needs to be big enough to copy the @p numberOfCharacters.
- *
- * @param[out] logicalToVisualMap Pointer to a buffer where the conversion map is copied.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- */
- void GetLogicalToVisualMap( CharacterIndex* logicalToVisualMap,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const;
-
- /**
- * @brief Retrieves the whole or part of the visual to logical conversion map.
- *
- * The size of the buffer needs to be big enough to copy the @p numberOfCharacters.
- *
- * @param[out] visualToLogicalMap Pointer to a buffer where the conversion map is copied.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- */
- void GetVisualToLogicalMap( CharacterIndex* visualToLogicalMap,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const;
-
protected:
/**
// Add remaining characters into the last script.
currentScriptRun.characterRun.numberOfCharacters += numberOfAllScriptCharacters;
- if( 0u != currentScriptRun.characterRun.numberOfCharacters )
- {
- if( TextAbstraction::UNKNOWN == currentScriptRun.script )
- {
- // There are only white spaces in the last script. Set the latin script.
- currentScriptRun.script = TextAbstraction::LATIN;
- }
- // Store the last run.
- scripts.PushBack( currentScriptRun );
+ DALI_ASSERT_DEBUG( ( 0u != currentScriptRun.characterRun.numberOfCharacters ) && "MultilanguageSupport::SetScripts() Trying to insert a script run with zero characters." );
+
+ if( TextAbstraction::UNKNOWN == currentScriptRun.script )
+ {
+ // There are only white spaces in the last script. Set the latin script.
+ currentScriptRun.script = TextAbstraction::LATIN;
}
-}
-void MultilanguageSupport::ReplaceScripts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
+ // Store the last run.
+ scripts.PushBack( currentScriptRun );
}
void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--MultilanguageSupport::ValidateFonts\n" );
}
-void MultilanguageSupport::ValidateFonts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
} // namespace Internal
} // namespace Text
Vector<ScriptRun>& scripts );
/**
- * @copydoc Dali::MultilanguageSupport::ReplaceScripts()
- */
- void ReplaceScripts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
-
- /**
* @copydoc Dali::MultilanguageSupport::ValidateFonts( const Vector<Character>& text, const Vector<ScriptRun>& scripts, Vector<FontRun>& fonts )
*/
void ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
Vector<FontRun>& fonts );
- /**
- * @copydoc Dali::MultilanguageSupport::ValidateFonts( LogicalModel& model, CharacterIndex characterIndex, Length numberOfCharactersToRemove, Length numberOfCharactersToInsert )
- */
- void ValidateFonts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
private:
Vector<FontId> mDefaultFontPerScriptCache; ///< Caches the default font for a script.
Vector<ValidateFontsPerScript*> mValidFontsPerScriptCache; ///< Caches valid fonts for a script.
scripts );
}
-void MultilanguageSupport::ReplaceScripts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
- GetImplementation( *this ).ReplaceScripts( model,
- characterIndex,
- numberOfCharactersToRemove,
- numberOfCharactersToInsert );
-}
-
void MultilanguageSupport::ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
Vector<FontRun>& fonts )
fonts );
}
-void MultilanguageSupport::ValidateFonts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
- GetImplementation( *this ).ValidateFonts( model,
- characterIndex,
- numberOfCharactersToRemove,
- numberOfCharactersToInsert );
-}
-
} // namespace Text
} // namespace Toolkit
Vector<ScriptRun>& scripts );
/**
- * Replaces the scrips of the given range of characters.
- *
- * @pre The @p model needs to have a text set.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in,out] model The text's logical model.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharactersToRemove The number of characters removed from the text.
- * @param[in] numberOfCharactersToInsert The number of characters inserted in the text.
- */
- void ReplaceScripts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
-
- /**
* @brief Validates the character's font of the whole text.
*
* It may update fonts set by application developers.
void ValidateFonts( const Vector<Character>& text,
const Vector<ScriptRun>& scripts,
Vector<FontRun>& fonts );
-
- /**
- * Validates the character's font of the given range of characters.
- *
- * It may update fonts set by the mark-up processor.
- * It sets default fonts based on the script to those characters without a font set.
- *
- * @pre The @p model needs to have a text set.
- * @pre The @p model needs to have the scripts set.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in,out] model The text's logical model.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharactersToRemove The number of characters removed from the text.
- * @param[in] numberOfCharactersToInsert The number of characters inserted in the text.
- */
- void ValidateFonts( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
};
} // namespace Text
#endif
}
-void ReplaceLineBreakInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
void SetWordBreakInfo( const Vector<Character>& text,
Vector<WordBreakInfo>& wordBreakInfo )
{
#endif
}
-void ReplaceWordBreakInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
} // namespace Text
} // namespace Toolkit
Vector<LineBreakInfo>& lineBreakInfo );
/**
- * Replaces line break info.
- *
- * @pre The @p model needs to have a text set.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in,out] model The text's logical model.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharactersToRemove The number of characters removed from the text.
- * @param[in] numberOfCharactersToInsert The number of characters inserted in the text.
- */
-void ReplaceLineBreakInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
-
-/**
* Sets word break info.
*
* - 0 is a WORD_BREAK. Text can be broken into a new word.
void SetWordBreakInfo( const Vector<Character>& text,
Vector<WordBreakInfo>& wordBreakInfo );
-/**
- * Replaces word break info.
- *
- * @pre The @p model needs to have a text set.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in,out] model The text's logical model.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharactersToRemove The number of characters removed from the text.
- * @param[in] numberOfCharactersToInsert The number of characters inserted in the text.
- */
-void ReplaceWordBreakInfo( LogicalModel& model,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
-
} // namespace Text
} // namespace Toolkit
glyphToCharacterMap.Resize( totalNumberOfGlyphs );
}
-void ShapeText( const LogicalModel& logicalModel,
- VisualModel& visualModel,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert )
-{
-}
-
} // namespace Text
} // namespace Toolkit
Vector<CharacterIndex>& glyphToCharacterMap,
Vector<Length>& charactersPerGlyph );
-/**
- * Replaces the shape info of the given range of characters.
- *
- * @pre The @p model needs to have a text set.
- * @pre The @p model needs to have the scripts set.
- * @pre The @p model needs to have the fonts set.
- * @pre The @p model needs to have the bidirectional info set.
- *
- * If the @p numberOfCharactersToRemove is zero, this operation is like an insert.
- * If the @p numberOfCharactersToInsert is zero, this operation is like a remove.
- *
- * @param[in] logicalModel The text's logical model.
- * @param[in,out] visualModel The text's logical model.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharactersToRemove The number of characters removed from the text.
- * @param[in] numberOfCharactersToInsert The number of characters inserted in the text.
- */
-void ShapeText( const LogicalModel& logicalModel,
- VisualModel& visualModel,
- CharacterIndex characterIndex,
- Length numberOfCharactersToRemove,
- Length numberOfCharactersToInsert );
-
} // namespace Text
} // namespace Toolkit
{
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;
+ }
}
}
}
}
else if( Dali::DALI_KEY_CURSOR_RIGHT == keyCode )
{
- if( mLogicalModel->GetNumberOfCharacters() > mEventData->mPrimaryCursorPosition )
+ if( mLogicalModel->mText.Count() > mEventData->mPrimaryCursorPosition )
{
mEventData->mPrimaryCursorPosition = CalculateNewCursorIndex( mEventData->mPrimaryCursorPosition );
}
mEventData->mUpdateCursorPosition = true;
mEventData->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;
- }
}
}
{
ChangeState ( EventData::SELECTION_HANDLE_PANNING );
- if( handleNewPosition != mEventData->mLeftSelectionPosition )
+ if( ( handleNewPosition != mEventData->mLeftSelectionPosition ) &&
+ ( handleNewPosition != mEventData->mRightSelectionPosition ) )
{
mEventData->mLeftSelectionPosition = handleNewPosition;
{
ChangeState ( EventData::SELECTION_HANDLE_PANNING );
- if( handleNewPosition != mEventData->mRightSelectionPosition )
+ if( ( handleNewPosition != mEventData->mRightSelectionPosition ) &&
+ ( handleNewPosition != mEventData->mLeftSelectionPosition ) )
{
mEventData->mRightSelectionPosition = handleNewPosition;
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 );
}
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 );
}
{
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<Character>& utf32Characters = mLogicalModel->mText;
+
+ Utf32ToUtf8( &utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText );
+
+ if ( deleteAfterRetreival ) // Only delete text if copied successfully
+ {
+ // Delete text between handles
+ Vector<Character>& currentText = mLogicalModel->mText;
+
+ Vector<Character>::Iterator first = currentText.Begin() + startOfSelectedText;
+ Vector<Character>::Iterator last = first + lengthOfSelectedText;
+ currentText.Erase( first, last );
+ }
+ mEventData->mPrimaryCursorPosition = mEventData->mLeftSelectionPosition;
+ mEventData->mScrollAfterDelete = true;
+ mEventData->mDecoratorUpdated = true;
+ }
+}
+
+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;
// TODO: Multi-line.
const Vector<LineRun>& 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 );
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;
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;
}
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;
// 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 )
{
*/
// EXTERNAL INCLUDES
-#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/devel-api/adaptor-framework/clipboard.h>
#include <dali/devel-api/adaptor-framework/imf-manager.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/layouts/layout-engine.h>
PAN_EVENT,
GRAB_HANDLE_EVENT,
LEFT_SELECTION_HANDLE_EVENT,
- RIGHT_SELECTION_HANDLE_EVENT
+ RIGHT_SELECTION_HANDLE_EVENT,
+ SELECT,
+ SELECT_ALL
};
union Param
{
INACTIVE,
SELECTING,
+ SELECTION_CHANGED,
EDITING,
EDITING_WITH_POPUP,
GRAB_HANDLE_PANNING,
mFontDefaults( NULL ),
mEventData( NULL ),
mFontClient(),
+ mClipboard(),
mView(),
mLayoutEngine(),
mModifyEvents(),
mVisualModel = VisualModel::New();
mFontClient = TextAbstraction::FontClient::Get();
+ mClipboard = Clipboard::Get();
mView.SetVisualModel( mVisualModel );
ClearPreEditFlag();
}
+ bool IsClipboardEmpty()
+ {
+ bool result( mClipboard && mClipboard.NumberOfItems() );
+ return !result; // // If NumberOfItems greater than 0, return false
+ }
+
void UpdateModel( OperationsMask operationsRequired );
/**
void OnHandleEvent( const Event& event );
+ void OnSelectEvent( const Event& event );
+
+ void OnSelectAllEvent();
+
+ void RetrieveSelection( std::string& selectedText, bool deleteAfterRetreival );
+
+ bool CopyStringToClipboard( std::string& source );
+
+ void SendSelectionToClipboard( bool deleteAfterSending );
+
+ void GetTextFromClipboard( unsigned int itemIndex, std::string& retreivedString );
+
void RepositionSelectionHandles( CharacterIndex selectionStart, CharacterIndex selectionEnd );
void RepositionSelectionHandles( float visualX, float visualY );
FontDefaults* mFontDefaults; ///< Avoid allocating this when the user does not specify a font.
EventData* mEventData; ///< Avoid allocating everything for text input until EnableTextInput().
TextAbstraction::FontClient mFontClient; ///< Handle to the font client.
+ Clipboard mClipboard; ///< Handle to the system clipboard
View mView; ///< The view interface to the rendering back-end.
LayoutEngine mLayoutEngine; ///< The layout engine.
std::vector<ModifyEvent> mModifyEvents; ///< Temporary stores the text set until the next relayout.
const std::string EMPTY_STRING("");
+float ConvertToEven( float value )
+{
+ int intValue(static_cast<int>( value ));
+ return static_cast<float>(intValue % 2 == 0) ? intValue : (intValue + 1);
+}
+
} // namespace
namespace Dali
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize cached %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z );
}
+ naturalSize.x = ConvertToEven( naturalSize.x );
+ naturalSize.y = ConvertToEven( naturalSize.y );
+
return naturalSize;
}
if( ( size.width < Math::MACHINE_EPSILON_1000 ) || ( size.height < Math::MACHINE_EPSILON_1000 ) )
{
bool glyphsRemoved( false );
- if( 0u != mImpl->mVisualModel->GetNumberOfGlyphPositions() )
+ if( 0u != mImpl->mVisualModel->mGlyphPositions.Count() )
{
- mImpl->mVisualModel->SetGlyphPositions( NULL, 0u );
+ mImpl->mVisualModel->mGlyphPositions.Clear();
glyphsRemoved = true;
}
// Not worth to relayout if width or height is equal to zero.
// after the first time the text has been laid out.
// Fill the vectors again.
- Length numberOfGlyphs = mImpl->mVisualModel->GetNumberOfGlyphs();
+ Length numberOfGlyphs = mImpl->mVisualModel->mGlyphs.Count();
if( 0u == numberOfGlyphs )
{
if( 0u != bidirectionalInfo.Count() )
{
// Get the lines
- const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines();
+ const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
// Reorder the lines.
Vector<BidirectionalLineInfoRun> lineBidirectionalInfoRuns;
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 )
{
}
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
{
mImpl->ClearPreEditFlag();
InsertText( keyString, COMMIT );
-
textChanged = true;
}
void Controller::InsertText( const std::string& text, Controller::InsertType type )
{
- bool removedPreEdit( false );
+ bool removedPrevious( false );
bool maxLengthReached( false );
DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "Unexpected InsertText" )
Vector<Character> utf32Characters;
Length characterCount( 0u );
- if( ! text.empty() )
+ // Remove the previous IMF pre-edit (predicitive text)
+ if( mImpl->mEventData &&
+ mImpl->mEventData->mPreEditFlag &&
+ 0 != mImpl->mEventData->mPreEditLength )
{
- // The placeholder text is no longer needed
- if( mImpl->IsShowingPlaceholderText() )
- {
- ResetText();
- }
+ CharacterIndex offset = mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition;
+ removedPrevious = RemoveText( -static_cast<int>(offset), mImpl->mEventData->mPreEditLength );
+ mImpl->mEventData->mPrimaryCursorPosition = mImpl->mEventData->mPreEditStartPosition;
+ mImpl->mEventData->mPreEditLength = 0;
+ }
+ else
+ {
+ // Remove the previous Selection
+ removedPrevious = RemoveSelectedText();
+ }
+
+ if( ! text.empty() )
+ {
// Convert text into UTF-32
utf32Characters.Resize( text.size() );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "UTF8 size %d, UTF32 size %d\n", text.size(), utf32Characters.Count() );
}
- if( 0u != utf32Characters.Count() )
+ if( 0u != utf32Characters.Count() ) // Check if Utf8ToUtf32 conversion succeeded
{
+ // The placeholder text is no longer needed
+ if( mImpl->IsShowingPlaceholderText() )
+ {
+ ResetText();
+ }
+
// Handle the IMF (predicitive text) state changes
if( mImpl->mEventData )
{
- if( mImpl->mEventData->mPreEditFlag &&
- 0 != mImpl->mEventData->mPreEditLength )
- {
- // Remove previous pre-edit text
- CharacterIndex offset = mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition;
- removedPreEdit = RemoveText( -static_cast<int>(offset), mImpl->mEventData->mPreEditLength );
-
- mImpl->mEventData->mPrimaryCursorPosition = mImpl->mEventData->mPreEditStartPosition;
- mImpl->mEventData->mPreEditLength = 0;
- }
-
if( COMMIT == type )
{
// IMF manager is no longer handling key-events
}
}
- const Length numberOfCharactersInModel = mImpl->mLogicalModel->GetNumberOfCharacters();
+ const Length numberOfCharactersInModel = mImpl->mLogicalModel->mText.Count();
// Restrict new text to fit within Maximum characters setting
Length maxSizeOfNewText = std::min ( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount );
DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition );
}
- if( removedPreEdit ||
- 0 != utf32Characters.Count() )
+ if( 0u == mImpl->mLogicalModel->mText.Count() &&
+ mImpl->IsPlaceholderAvailable() )
+ {
+ // Show place-holder if empty after removing the pre-edit text
+ ShowPlaceholderText();
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ mImpl->ClearPreEditFlag();
+ }
+ else if( removedPrevious ||
+ 0 != utf32Characters.Count() )
{
// Queue an inserted event
mImpl->QueueModifyEvent( ModifyEvent::TEXT_INSERTED );
}
}
+bool Controller::RemoveSelectedText()
+{
+ bool textRemoved( false );
+
+ if ( EventData::SELECTING == mImpl->mEventData->mState ||
+ EventData::SELECTION_CHANGED == mImpl->mEventData->mState )
+ {
+ std::string removedString;
+ mImpl->RetrieveSelection( removedString, true );
+
+ if( !removedString.empty() )
+ {
+ textRemoved = true;
+ mImpl->ChangeState( EventData::EDITING );
+ }
+ }
+
+ return textRemoved;
+}
+
void Controller::TapEvent( unsigned int tapCount, float x, float y )
{
DALI_ASSERT_DEBUG( mImpl->mEventData && "Unexpected TapEvent" );
if( !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();
}
}
}
+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;
}
}
+void Controller::TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Buttons button )
+{
+ if( NULL == mImpl->mEventData )
+ {
+ return;
+ }
+
+ switch( button )
+ {
+ case Toolkit::TextSelectionPopup::CUT:
+ {
+ mImpl->SendSelectionToClipboard( true ); // Synchronous call to modify text
+ mImpl->mOperationsPending = ALL_OPERATIONS;
+ if( 0u != mImpl->mLogicalModel->mText.Count() ||
+ !mImpl->IsPlaceholderAvailable() )
+ {
+ mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
+ }
+ else
+ {
+ ShowPlaceholderText();
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ }
+ mImpl->RequestRelayout();
+ mImpl->mControlInterface.TextChanged();
+ break;
+ }
+ case Toolkit::TextSelectionPopup::COPY:
+ {
+ mImpl->SendSelectionToClipboard( false ); // Text not modified
+ mImpl->RequestRelayout(); // Handles, Selection Highlight, Popup
+ break;
+ }
+ case Toolkit::TextSelectionPopup::PASTE:
+ {
+ std::string stringToPaste("");
+ mImpl->GetTextFromClipboard( 0, stringToPaste ); // Paste latest item from system clipboard
+ InsertText( stringToPaste, Text::Controller::COMMIT );
+ mImpl->ChangeState( EventData::EDITING );
+ mImpl->RequestRelayout();
+ break;
+ }
+ case Toolkit::TextSelectionPopup::SELECT:
+ {
+ const Vector2& currentCursorPosition = mImpl->mEventData->mDecorator->GetPosition( PRIMARY_CURSOR );
+
+ if( mImpl->mEventData->mSelectionEnabled )
+ {
+ // Creates a SELECT event.
+ SelectEvent( currentCursorPosition.x, currentCursorPosition.y, false );
+ }
+ break;
+ }
+ case Toolkit::TextSelectionPopup::SELECT_ALL:
+ {
+ // Creates a SELECT_ALL event
+ SelectEvent( 0.f, 0.f, true );
+ break;
+ }
+ case Toolkit::TextSelectionPopup::CLIPBOARD:
+ {
+ break;
+ }
+ case Toolkit::TextSelectionPopup::NONE:
+ {
+ // Nothing to do.
+ break;
+ }
+ }
+}
+
ImfManager::ImfCallbackData Controller::OnImfEvent( ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent )
{
bool update( false );
delete mImpl;
}
+bool Controller::BackspaceKeyEvent()
+{
+ DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::KeyEvent %p DALI_KEY_BACKSPACE\n", this );
+
+ // IMF manager is no longer handling key-events
+ mImpl->ClearPreEditFlag();
+
+ bool removed( false );
+
+ if ( EventData::SELECTING == mImpl->mEventData->mState ||
+ EventData::SELECTION_CHANGED == mImpl->mEventData->mState )
+ {
+ removed = RemoveSelectedText();
+ }
+ else if( mImpl->mEventData->mPrimaryCursorPosition > 0 )
+ {
+ // Remove the character before the current cursor position
+ removed = RemoveText( -1, 1 );
+ }
+
+ if( removed )
+ {
+ if( 0u != mImpl->mLogicalModel->mText.Count() ||
+ !mImpl->IsPlaceholderAvailable() )
+ {
+ mImpl->QueueModifyEvent( ModifyEvent::TEXT_DELETED );
+ }
+ else
+ {
+ ShowPlaceholderText();
+ mImpl->mEventData->mUpdateCursorPosition = true;
+ }
+ }
+
+ return removed;
+}
+
void Controller::ShowPlaceholderText()
{
if( mImpl->IsPlaceholderAvailable() )
#include <dali/public-api/object/ref-object.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/font-run.h>
#include <dali-toolkit/internal/text/layouts/layout-engine.h>
* It provides a view of the text that can be used by rendering back-ends.
*
* For selectable/editable UI controls, the controller handles input events from the UI control
- * and decorations (grab handles etc) via an 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:
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.
// Text-input Event Queuing
/**
- * @brief Caller by editable UI controls when keyboard focus is gained.
+ * @brief Called by editable UI controls when keyboard focus is gained.
*/
void KeyboardFocusGainEvent();
/**
- * @brief Caller by editable UI controls when focus is lost.
+ * @brief Called by editable UI controls when focus is lost.
*/
void KeyboardFocusLostEvent();
/**
- * @brief Caller by editable UI controls when key events are received.
+ * @brief Called by editable UI controls when key events are received.
*
* @param[in] event The key event.
* @param[in] type Used to distinguish between regular key events and IMF events.
bool KeyEvent( const Dali::KeyEvent& event );
/**
- * @brief Caller by editable UI controls when key events are received.
+ * @brief Called by editable UI controls when key events are received.
*
* @param[in] text The text to insert.
* @param[in] type Used to distinguish between regular key events and IMF events.
void InsertText( const std::string& text, InsertType type );
/**
- * @brief Caller by editable UI controls when a tap gesture occurs.
+ * @brief Checks if text is selected and if so removes it.
+ * @return true if text was removed
+ */
+ bool RemoveSelectedText();
+
+ /**
+ * @brief Called by editable UI controls when a tap gesture occurs.
* @param[in] tapCount The number of taps.
* @param[in] x The x position relative to the top-left of the parent control.
* @param[in] y The y position relative to the top-left of the parent control.
void TapEvent( unsigned int tapCount, float x, float y );
/**
- * @brief Caller by editable UI controls when a pan gesture occurs.
+ * @brief Called by editable UI controls when a pan gesture occurs.
*
* @param[in] state The state of the gesture.
* @param[in] displacement This distance panned since the last pan gesture.
void PanEvent( Gesture::State state, const Vector2& displacement );
/**
+ * @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.
*/
virtual void DecorationEvent( HandleType handle, HandleState state, float x, float y );
+ /**
+ * @copydoc Dali::Toolkit::TextSelectionPopup::TextPopupButtonCallbackInterface::TextPopupButtonTouched()
+ */
+ virtual void TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Buttons button );
+
protected:
/**
private:
/**
+ * @brief Helper to KeyEvent() to handle the backspace case.
+ *
+ * @return True if a character was deleted.
+ */
+ bool BackspaceKeyEvent();
+
+ /**
* @brief Helper to clear font-specific data.
*/
void ShowPlaceholderText();
// If ellipsis is enabled, the number of glyphs the layout engine has laid out may be less than 'numberOfGlyphs'.
// Check the last laid out line to know if the layout engine elided some text.
- const Length numberOfLines = mImpl->mVisualModel->GetNumberOfLines();
+ const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
if( numberOfLines > 0u )
{
const LineRun& lastLine = *( mImpl->mVisualModel->mLines.Begin() + ( numberOfLines - 1u ) );
{
VisualModel& model = *mImpl->mVisualModel;
- Length glyphCount = model.GetNumberOfGlyphs();
- Length positionCount = model.GetNumberOfGlyphPositions();
+ const Length glyphCount = model.mGlyphs.Count();
+ const Length positionCount = model.mGlyphPositions.Count();
DALI_ASSERT_DEBUG( positionCount <= glyphCount && "Invalid glyph positions in Model" );
return VisualModelPtr( new VisualModel() );
}
-void VisualModel::SetGlyphs( const GlyphInfo* 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.
}
}
-Length VisualModel::GetNumberOfGlyphs() const
-{
- return mGlyphs.Count();
-}
-
void VisualModel::GetGlyphs( GlyphInfo* glyphs,
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const
memcpy( glyphs, mGlyphs.Begin() + glyphIndex, numberOfGlyphs * sizeof( GlyphInfo ) );
}
-const GlyphInfo& VisualModel::GetGlyphInfo( GlyphIndex glyphIndex ) const
-{
- return mGlyphs[glyphIndex];
-}
-
-void VisualModel::ReplaceGlyphs( GlyphIndex glyphIndex,
- Length numberOfGlyphsToRemove,
- const GlyphInfo* const glyphs,
- const Length* const numberOfCharacters,
- Length numberOfGlyphsToInsert )
-{
-}
-
-CharacterIndex VisualModel::GetCharacterIndex( GlyphIndex glyphIndex ) const
-{
- return mGlyphsToCharacters[glyphIndex];
-}
-
-Length VisualModel::GetCharactersPerGlyph( GlyphIndex glyphIndex ) const
-{
- return mCharactersPerGlyph[glyphIndex];
-}
-
-GlyphIndex VisualModel::GetGlyphIndex( CharacterIndex characterIndex ) const
-{
- return mCharactersToGlyph[characterIndex];
-}
-
-void VisualModel::GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- memcpy( characterToGlyphMap, mCharactersToGlyph.Begin() + characterIndex, numberOfCharacters * sizeof( GlyphIndex ) );
-}
-
-void VisualModel::GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
- GlyphIndex glyphIndex,
- Length numberOfGlyphs ) const
-{
- memcpy( glyphToCharacter, mGlyphsToCharacters.Begin() + glyphIndex, numberOfGlyphs * sizeof( CharacterIndex ) );
-}
-
-void VisualModel::GetCharactersPerGlyphMap( Length* charactersPerGlyph,
- GlyphIndex glyphIndex,
- Length numberOfGlyphs ) const
-{
- memcpy( charactersPerGlyph, mCharactersPerGlyph.Begin() + glyphIndex, numberOfGlyphs * sizeof( Length ) );
-}
-
-void VisualModel::GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const
-{
- memcpy( glyphsPerCharacter, mGlyphsPerCharacter.Begin() + characterIndex, numberOfCharacters * sizeof( Length ) );
-}
-
-void VisualModel::SetGlyphPositions( const Vector2* 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
memcpy( glyphPositions, mGlyphPositions.Begin() + glyphIndex, numberOfGlyphs * sizeof( Vector2 ) );
}
-const Vector2& VisualModel::GetGlyphPosition( GlyphIndex glyphIndex ) const
-{
- return *( mGlyphPositions.Begin() + glyphIndex );
-}
-
-void VisualModel::ReplaceGlyphPositions( GlyphIndex glyphIndex,
- Length numberOfGlyphsToRemove,
- const Vector2* const positions,
- Length numberOfGlyphsToInsert )
-{
-}
-
-void VisualModel::SetLines( const LineRun* const lines,
- Length numberOfLines )
-{
- if( 0u == numberOfLines )
- {
- mLines.Clear();
- }
- else
- {
- mLines.Resize( numberOfLines );
- memcpy( mLines.Begin(), lines, numberOfLines * sizeof( LineRun ) );
- }
-}
-
-Length VisualModel::GetNumberOfLines() const
-{
- return mLines.Count();
-}
-
-void VisualModel::GetLines( LineRun* lines,
- LineIndex lineIndex,
- Length numberOfLines ) const
-{
- memcpy( lines, mLines.Begin() + lineIndex, numberOfLines * sizeof( LineRun ) );
-}
-
void VisualModel::GetNumberOfLines( GlyphIndex glyphIndex,
Length numberOfGlyphs,
LineIndex& firstLine,
memcpy( lines, mLines.Begin() + firstLine, numberOfLines * sizeof( LineRun ) );
}
-LineIndex VisualModel::GetLineOfGlyph( GlyphIndex glyphIndex )
-{
- const CharacterIndex characterIndex = *( mGlyphsToCharacters.Begin() + glyphIndex );
-
- return GetLineOfCharacter( characterIndex );
-}
-
LineIndex VisualModel::GetLineOfCharacter( CharacterIndex characterIndex )
{
// 1) Check first in the cached line.
return index;
}
-void VisualModel::ReplaceLines( GlyphIndex glyphIndex,
- Length numberOfGlyphsToRemove,
- const LineRun* const lines,
- Length numberOfGlyphsToInsert )
-{
-}
-
void VisualModel::SetNaturalSize( const Vector2& size )
{
mNaturalSize = size;
// Glyph interface.
/**
- * @brief Replaces any glyphs previously set.
- *
- * @note If the number of glyphs is zero, all buffers are cleared.
- * @note If one pointer is NULL and the number of glyphs is not zero, the buffer is not touched.
- *
- * @param[in] glyphs An array of glyphs in the visual order.
- * @param[in] characterIndices An array containing the first character in the logical model that each glyph relates to.
- * @param[in] charactersPerGlyph An array containing the number of characters per glyph.
- * @param[in] numberOfGlyphs The number of glyphs.
- */
- void SetGlyphs( const GlyphInfo* 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.
void CreateGlyphsPerCharacterTable( Length numberOfCharacters = 0u );
/**
- * @brief Retrieves the number of glyphs.
- *
- * @return The number of glyphs.
- */
- Length GetNumberOfGlyphs() const;
-
- /**
* @brief Retrieves glyphs in the given buffer.
*
* The size of the @p glyphs buffer needs to be big enough to copy the @p numberOfGlyphs.
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const;
- /**
- * @brief Retrieves a glyph.
- *
- * @param[in] glyphIndex Index to a glyph.
- *
- * @return A glyph.
- */
- const GlyphInfo& GetGlyphInfo( GlyphIndex glyphIndex ) const;
-
- /**
- * @brief Replaces glyphs.
- *
- * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert.
- * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove.
- *
- * @param[in] glyphIndex Where to replace the glyphs.
- * @param[in] numberOfGlyphsToRemove The number of glyphs to be removed.
- * @param[in] glyphs Pointer to a buffer with the new glyphs.
- * @param[in] numberOfCharacters Pointer to a buffer with the number of characters per glyph.
- * @param[in] numberOfGlyphsToInsert The number of new glyphs in the buffer.
- */
- void ReplaceGlyphs( GlyphIndex glyphIndex,
- Length numberOfGlyphsToRemove,
- const GlyphInfo* const glyphs,
- const Length* const numberOfCharacters,
- Length numberOfGlyphsToInsert );
-
// Character <--> Glyph conversion
/**
- * @brief Retrieves the first character in the logical model which a glyph represents.
- *
- * @note After shaping several characters may be represented by the same glyph.
- * Alternatively several glyphs may be required to display a character.
- * @param[in] glyphIndex The glyph index.
- * @return The character index.
- */
- CharacterIndex GetCharacterIndex( GlyphIndex glyphIndex ) const;
-
- /**
- * @brief Query the number of characters the glyph represents.
- *
- * @param[in] glyphIndex The glyph index.
- * @return The number of characters represented by the glyph.
- */
- Length GetCharactersPerGlyph( GlyphIndex glyphIndex ) const;
-
- /**
- * @brief Retrieves the first glyph in the visual model which represents a given character.
- *
- * @note After shaping several characters may be represented by the same glyph.
- * Alternatively several glyphs may be required to display a character.
- * @param[in] characterIndex The character index.
- * @return The glyph index.
- */
- GlyphIndex GetGlyphIndex( CharacterIndex characterIndex ) const;
-
- /**
- * @brief Retrieves the whole or part of the character to glyph conversion map.
- *
- * The size of the buffer needs to be big enough to copy the @p numberOfCharacters.
- *
- * @param[out] characterToGlyphMap Pointer to a buffer where the conversion map is copied.
- * @param[in] characterIndex Index to the first character.
- * @param[in] numberOfCharacters The number of characters.
- */
- void GetCharacterToGlyphMap( GlyphIndex* characterToGlyphMap,
- CharacterIndex characterIndex,
- Length numberOfCharacters ) const;
-
- /**
- * @brief Retrieves the whole or part of the glyph to character conversion map.
- *
- * The size of the buffer needs to be big enough to copy the @p numberOfGlyphs.
- *
- * @param[out] glyphToCharacter Pointer to a buffer where the conversion map is copied.
- * @param[in] glyphIndex Index to the first glyph.
- * @param[in] numberOfGlyphs The number of glyphs.
- */
- void GetGlyphToCharacterMap( CharacterIndex* glyphToCharacter,
- GlyphIndex glyphIndex,
- Length numberOfGlyphs ) const;
-
- /**
- * @brief Retrieves for each glyph the number of characters the glyph represents.
- *
- * @param[out] charactersPerGlyph Pointer to a buffer where the number of characters for each glyph are copied.
- * @param[in] glyphIndex Index to the first glyph.
- * @param[in] numberOfGlyphs The number of glyphs.
- */
- void GetCharactersPerGlyphMap( Length* charactersPerGlyph,
- GlyphIndex glyphIndex,
- Length numberOfGlyphs ) const;
-
- /**
* @brief Retrieves for each character the number of glyphs the character is shaped.
*
* @param[out] glyphsPerCharacter Pointer to a buffer where the number of glyphs for each character are copied.
// Position interface
/**
- * @brief Replaces any glyph positions previously set.
- *
- * @note If the number of glyphs is zero the position buffer is cleared.
- *
- * @param[in] glyphPositions An array of visual positions for each glyph.
- * @param[in] numberOfGlyphs The number of positions.
- */
- void SetGlyphPositions( const Vector2* 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.
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const;
- /**
- * @brief Retrieve the glyph's position of the given glyph.
- *
- * @param[in] glyphIndex Index to the glyph.
- *
- * @return The glyph's position.
- */
- const Vector2& GetGlyphPosition( GlyphIndex glyphIndex ) const;
-
- /**
- * @brief Replaces glyph's positions.
- *
- * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert.
- * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove.
- *
- * @param[in] glyphIndex Where to replace the glyph's positions.
- * @param[in] numberOfGlyphsToRemove The number of glyph's positions to be removed.
- * @param[in] positions Pointer to a buffer with the new glyph's positions.
- * @param[in] numberOfGlyphsToInsert The number of new glyph's positions in the buffer.
- */
- void ReplaceGlyphPositions( GlyphIndex glyphIndex,
- Length numberOfGlyphsToRemove,
- const Vector2* const positions,
- Length numberOfGlyphsToInsert );
-
// Line interface.
/**
- * @brief Sets the lines.
- *
- * Replaces any lines previously set.
- *
- * Every line is an item run containing the index to the first glyph of the line and the number of glyphs.
- *
- * @note If the number of lines is zero or the pointer is NULL, the lines buffer is cleared.
- *
- * @param[in] lines Pointer to a buffer containing all the line runs.
- * @param[in] numberOfLines The number of lines in the buffer.
- */
- void SetLines( const LineRun* const lines,
- Length numberOfLines );
-
- /**
- * @brief Retrieves the number of lines of the whole text.
- *
- * @return The number of lines.
- */
- Length GetNumberOfLines() const;
-
- /**
- * @brief Retrieves lines.
- *
- * The size of the @p lines buffer needs to be big enough to copy the @p numberOfLines.
- *
- * @param[out] lines Pointer to a buffer where the lines are copied.
- * @param[in] lineIndex Index to the first line.
- * @param[in] numberOfLines Number of lines to be copied.
- */
- void GetLines( LineRun* lines,
- LineIndex lineIndex,
- Length numberOfLines ) const;
-
- /**
* @brief Retrieves the number of lines and the index to the first line where the given range of glyphs is laid out.
*
* @param[in] glyphIndex Index to the first glyph.
Length numberOfGlyphs,
LineIndex& firstLine,
Length& numberOfLines ) const;
+
/**
* @brief Retrieves the lines where the given range of glyphs is laid out.
*
Length numberOfGlyphs ) const;
/**
- * @brief Retrieves the line index where the glyph is laid-out.
- *
- * @param[in] glyphIndex The glyph's index.
- *
- * @return The line index.
- */
- LineIndex GetLineOfGlyph( GlyphIndex glyphIndex );
-
- /**
* @brief Retrieves the line index where the character is laid-out.
*
* @param[in] characterIndex The character's index.
*/
LineIndex GetLineOfCharacter( CharacterIndex characterIndex );
- /**
- * @brief Replaces lines for the given range of glyphs.
- *
- * If the @p numberOfGlyphsToRemove is zero, this operation is like an insert.
- * If the @p numberOfGlyphsToInsert is zero, this operation is like a remove.
- *
- * @param[in] glyphIndex Index of the first glyph where to replace the line info.
- * @param[in] numberOfGlyphsToRemove The number of glyphs to be the line info removed.
- * @param[in] lines Pointer to a buffer with the lines.
- * @param[in] numberOfGlyphsToInsert The number of characters to be the line info inserted.
- */
- void ReplaceLines( GlyphIndex glyphIndex,
- Length numberOfGlyphsToRemove,
- const LineRun* const lines,
- Length numberOfGlyphsToInsert );
-
// Size interface
/**
namespace Toolkit
{
-const std::string TableView::CELL_INDICES_PROPERTY_NAME("cell-indices");
-const std::string TableView::ROW_SPAN_PROPERTY_NAME("row-span");
-const std::string TableView::COLUMN_SPAN_PROPERTY_NAME("column-span");
-
TableView::TableView()
{
}
void TableView::SetFitHeight( unsigned int rowIndex )
{
- GetImpl(*this).SetRowPolicy( rowIndex, Internal::TableView::FIT );
+ GetImpl(*this).SetFitHeight( rowIndex );
}
bool TableView::IsFitHeight( unsigned int rowIndex ) const
{
- return ( GetImpl(*this).GetRowPolicy( rowIndex ) == Internal::TableView::FIT );
+ return GetImpl(*this).IsFitHeight( rowIndex );
}
void TableView::SetFitWidth( unsigned int columnIndex )
{
- GetImpl(*this).SetColumnPolicy( columnIndex, Internal::TableView::FIT );
+ GetImpl(*this).SetFitWidth( columnIndex );
}
bool TableView::IsFitWidth( unsigned int columnIndex ) const
{
- return ( GetImpl(*this).GetColumnPolicy( columnIndex ) == Internal::TableView::FIT );
+ return GetImpl(*this).IsFitWidth( columnIndex );
}
void TableView::SetFixedHeight( unsigned int rowIndex, float height )
* TableView constrains the x and y position and width and height of the child actors.
* z position and depth are left intact so that 3D model actors can also be laid out
* in a grid without loosing their depth scaling.
+ *
+ * @nosubgrouping
+ *
+ * Per-child Custom properties for script supporting.
+ *
+ * When an actor is add to the tableView through Actor::Add() instead of TableView::AddChild,
+ * the following custom properties of the actor are checked to decide the actor position inside the table
+ *
+ * These properties are registered dynamically to the child and is non-animatable.
+ *
+ * | %Property Name | Type |
+ * |---------------------------|--------------------|
+ * | cell-index | Vector2 |
+ * | row-span | float | // type float (Currently builder is unable to differentiate integer and float from Json string)
+ * | column-span | float | // type float (Currently builder is unable to differentiate integer and float from Json string)
+ * | cell-horizontal-alignment | string | // available values: left, center, right
+ * | cell-vertical-alignment | string | // available values: top, center, bottom
+ *
+ * @code
+ * "name":"gallery-1",
+ * "type":"ImageActor",
+ * "image": {
+ * "filename": "{DALI_IMAGE_DIR}gallery-small-1.jpg"
+ * },
+ * "custom-properties": {
+ * "cell-index":[1,1], // property to specify the top-left cell this child occupies, if not set, the first available cell is used
+ * "row-span":3, // property to specify how many rows this child occupies, if not set, default value is 1
+ * "column-span": 2, // property to specify how many columns this child occupies, if nor set, default value is 1
+ * "cell-horizontal-alignment": "left", // property to specify how to align horizontally inside the cells, if not set, default value is 'left'
+ * "cell-vertical-alignment": "center" // property to specify how to align vertically inside the cells, if not set, default value is 'top'
+ * }
+ * @endcode
*/
class DALI_IMPORT_API TableView : public Control
{
* "layout-rows":
{
"0": { "policy": "fixed", "value": 40 }, //@see SetFixedHight
- "2": { "policy": "relative", "value": 0.33 } //@see SetRelativeHeight
+ "2": { "policy": "relative", "value": 0.33 }, //@see SetRelativeHeight
+ "3": { "policy": "fit", "value":0.0 } //@see SetFitHeight, the value is not used, its height is decided by the children in this row
}
* @endcode
*
* "layout-columns":
{
"0": { "policy": "fixed", "value": 40 }, //@see SetFixedWidth
+ "1": { "policy": "fit", "value":0.0 } //@see SetFitHeight, the value is not used, its width is decided by the children in this column
"2": { "policy": "relative", "value": 0.33 } //@see SetRelativeWidth
}
* @endcode
};
};
- // Custom properties for where to put the actor, these properties should be registered to the child which would be added to the table
- static const std::string CELL_INDICES_PROPERTY_NAME; ///< Property, name "cell-indices", type Vector2
- static const std::string ROW_SPAN_PROPERTY_NAME; ///< Property, name "row-span", type float (Currently builder is unable to differentiate integer and float from Json string)
- static const std::string COLUMN_SPAN_PROPERTY_NAME; ///< Property, name "column-span", type float (Currently builder is unable to differentiate integer and float from Json string)
-
/**
* @brief Describes how the size of a row / column been set
*/
{
FIXED, ///< Fixed with the given value.
RELATIVE, ///< Calculated as percentage of the remainder after subtracting Padding and Fixed height/width
- FILL ///< Get the remainder of the 100% (after subtracting Padding, Fixed and Relative height/ width) divided evenly between 'fill' rows/columns
+ FILL, ///< Default policy, get the remainder of the 100% (after subtracting Padding, Fixed and Relative height/ width) divided evenly between 'fill' rows/columns
+ FIT ///< Fit around its children.
};
/**
unsigned int GetColumns();
/**
- * @brief Set the alignment on a cell
+ * @brief Set the alignment on a cell.
+ *
+ * Cells without calling this function have the default values of LEFT and TOP respectively.
*
- * @param[in] position The cell to set alignment on
- * @param[in] horizontal The horizontal alignment
- * @param[in] vertical The vertical alignment
+ * @param[in] position The cell to set alignment on.
+ * @param[in] horizontal The horizontal alignment.
+ * @param[in] vertical The vertical alignment.
*/
void SetCellAlignment( CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical );
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 45;
+const unsigned int TOOLKIT_MICRO_VERSION = 46;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
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