From: Adeel Kazmi Date: Fri, 21 Oct 2016 10:34:10 +0000 (-0700) Subject: Merge "Added code for stylable transitions" into devel/master X-Git-Tag: dali_1.2.12~21 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=f4c1e7f52d49c3ce033b9ee4c3c7414b06a22d45;hp=04dface1b4b122e8eef10026bf0a45d621d5f3d7 Merge "Added code for stylable transitions" into devel/master --- diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt index 05380dd..4a9a003 100644 --- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt +++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt @@ -20,6 +20,7 @@ SET(TC_SOURCES utc-Dali-Text-Controller.cpp utc-Dali-VisualFactoryResolveUrl.cpp utc-Dali-Visuals.cpp + utc-Dali-Text-Markup.cpp ) # Append list of test harness files (Won't get parsed for test cases) diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp index 7480435..f2e761f 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp @@ -19,10 +19,14 @@ #include #include +#include #include #include #include +#include +#include +#include using namespace Dali; using namespace Toolkit; @@ -40,7 +44,9 @@ const char* const OPTION_CLIPBOARD("optionClipboard"); // "Clipboard" popup const Size CONTROL_SIZE( 300.f, 60.f ); -class ControlImpl : public ControlInterface +const std::string DEFAULT_FONT_DIR( "/resources/fonts" ); + +class ControlImpl : public ControlInterface, public Text::EditableControlInterface { public: ControlImpl() @@ -80,8 +86,7 @@ int UtcDaliTextController(void) ToolkitTestApplication application; // Creates a text controller. - ControlImpl controlImpl; - ControllerPtr controller = Controller::New( controlImpl ); + ControllerPtr controller = Controller::New(); DALI_TEST_CHECK( controller ); @@ -95,8 +100,7 @@ int UtcDaliTextControllerEnableCursorBlinking(void) ToolkitTestApplication application; // Creates a text controller. - ControlImpl controlImpl; - ControllerPtr controller = Controller::New( controlImpl ); + ControllerPtr controller = Controller::New(); DALI_TEST_CHECK( controller ); @@ -131,8 +135,7 @@ int UtcDaliTextControllerImfEvent(void) ToolkitTestApplication application; // Creates a text controller. - ControlImpl controlImpl; - ControllerPtr controller = Controller::New( controlImpl ); + ControllerPtr controller = Controller::New(); std::string text; ImfManager::ImfEventData imfEvent; @@ -214,8 +217,7 @@ int UtcDaliTextControllerTextPopupButtonTouched(void) ToolkitTestApplication application; // Creates a text controller. - ControlImpl controlImpl; - ControllerPtr controller = Controller::New( controlImpl ); + ControllerPtr controller = Controller::New(); DALI_TEST_CHECK( controller ); @@ -330,3 +332,193 @@ int UtcDaliTextControllerTextPopupButtonTouched(void) tet_result(TET_PASS); END_TEST; } + +int UtcDaliTextControllerGetInputShadowProperty(void) +{ + tet_infoline(" UtcDaliTextControllerGetInputShadowProperty"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + const std::string& shadowProperties = controller->GetInputShadowProperties(); + + DALI_TEST_CHECK( shadowProperties.empty() ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerGetInputUnderlineProperty(void) +{ + tet_infoline(" UtcDaliTextControllerGetInputUnderlineProperty"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + const std::string& underlineProperties = controller->GetInputUnderlineProperties(); + + DALI_TEST_CHECK( underlineProperties.empty() ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerSetGetAutoScrollEnabled(void) +{ + tet_infoline(" UtcDaliTextControllerSetGetAutoScrollEnabled"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + DALI_TEST_CHECK( !controller->IsAutoScrollEnabled() ); + + // The auto scrolling shouldn't be enabled if the multi-line is enabled. + + // Enable multi-line. + controller->SetMultiLineEnabled( true ); + + // Enable text scrolling. + controller->SetAutoScrollEnabled( true ); + + DALI_TEST_CHECK( !controller->IsAutoScrollEnabled() ); + + // Disable multi-line. + controller->SetMultiLineEnabled( false ); + + // Enable text scrolling. + controller->SetAutoScrollEnabled( true ); + + // Should be ebabled now. + DALI_TEST_CHECK( controller->IsAutoScrollEnabled() ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerSetGetAutoScrollSpeed(void) +{ + tet_infoline(" UtcDaliTextControllerSetGetAutoScrollSpeed"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + // Check the default value. + DALI_TEST_EQUALS( 0, controller->GetAutoScrollSpeed(), TEST_LOCATION ); + + // Set the auto scroll speed. + controller->SetAutoscrollSpeed( 10 ); + + DALI_TEST_EQUALS( 10, controller->GetAutoScrollSpeed(), TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerSetGetAutoScrollLoopCount(void) +{ + tet_infoline(" UtcDaliTextControllerSetGetAutoScrollLoopCount"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + // Check the default value. + DALI_TEST_EQUALS( 0, controller->GetAutoScrollLoopCount(), TEST_LOCATION ); + + // Set the auto scroll loop count. + controller->SetAutoScrollLoopCount( 5 ); + + DALI_TEST_EQUALS( 5, controller->GetAutoScrollLoopCount(), TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerSetGetAutoScrollWrapGap(void) +{ + tet_infoline(" UtcDaliTextControllerSetGetAutoScrollWrapGap"); + ToolkitTestApplication application; + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + // Check the default value. + DALI_TEST_EQUALS( 0.f, controller->GetAutoScrollWrapGap(), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Set the auto scroll loop count. + controller->SetAutoScrollWrapGap( 25.f ); + + DALI_TEST_EQUALS( 25.f, controller->GetAutoScrollWrapGap(), Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextControllerGetAutoScrollData(void) +{ + tet_infoline(" UtcDaliTextControllerGetAutoScrollData"); + ToolkitTestApplication application; + + // Load some fonts to get the same metrics on different platforms. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.SetDpi( 96u, 96u ); + + char* pathNamePtr = get_current_dir_name(); + const std::string pathName( pathNamePtr ); + free( pathNamePtr ); + + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" ); + + // Creates a text controller. + ControllerPtr controller = Controller::New(); + + DALI_TEST_CHECK( controller ); + + DALI_TEST_CHECK( NULL == controller->GetAutoScrollData() ); + + // Set and check some values. + controller->SetAutoscrollSpeed( 10 ); + controller->SetAutoScrollLoopCount( 5 ); + controller->SetAutoScrollWrapGap( 25.f ); + + const ScrollerData* scrollerData = controller->GetAutoScrollData(); + DALI_TEST_CHECK( NULL != controller->GetAutoScrollData() ); + + DALI_TEST_EQUALS( Size::ZERO, scrollerData->mControlSize, TEST_LOCATION ); + DALI_TEST_EQUALS( Size::ZERO, scrollerData->mOffscreenSize, TEST_LOCATION ); + DALI_TEST_EQUALS( 10, scrollerData->mScrollSpeed, TEST_LOCATION ); + DALI_TEST_EQUALS( 5, scrollerData->mLoopCount, TEST_LOCATION ); + DALI_TEST_EQUALS( 25.f, scrollerData->mWrapGap, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( 0.f, scrollerData->mAlignmentOffset, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_CHECK( !scrollerData->mAutoScrollDirectionRTL ); + + // Set some text and layout. + controller->SetMarkupProcessorEnabled( true ); + controller->SetHorizontalAlignment( LayoutEngine::HORIZONTAL_ALIGN_END ); + controller->SetText( "Hello world" ); + controller->Relayout( Size( 100.f, 20.f ) ); + + scrollerData = controller->GetAutoScrollData(); + DALI_TEST_EQUALS( Size( 100.f, 20.f ), scrollerData->mControlSize, TEST_LOCATION ); + DALI_TEST_EQUALS( Size( 80.f, 20.f ), scrollerData->mOffscreenSize, TEST_LOCATION ); + DALI_TEST_EQUALS( 20.f, scrollerData->mAlignmentOffset, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + tet_result(TET_PASS); + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp new file mode 100644 index 0000000..23f7e51 --- /dev/null +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Markup.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Toolkit; +using namespace Text; + +namespace +{ + /////////////////////////////////////////////////////////// + + struct TokenComparisonData + { + std::string description; + std::string string1; ///< must be in lower case!!!! + std::string string2; + bool expectedResult; + }; + + bool TokenComparisonTest( const TokenComparisonData& data ) + { + std::cout << " testing " << data.description << std::endl; + + const bool result = TokenComparison( data.string1, + data.string2.c_str(), + data.string2.size() ); + + if( result != data.expectedResult ) + { + std::cout << " different conparison result : " << result << ", expected : " << data.expectedResult << std::endl; + std::cout << " comparing : [" << data.string1 << "] and [" << data.string2 << "]" << std::endl; + + return false; + } + + return true; + } + + /////////////////////////////////////////////////////////// + + struct ColorStringToVector4Data + { + std::string description; + std::string colorStr; + Vector4 expectedColor; + }; + + bool ColorStringToVector4Test( const ColorStringToVector4Data& data ) + { + std::cout << " testing " << data.description << std::endl; + + Vector4 color; + ColorStringToVector4( data.colorStr.c_str(), data.colorStr.size(), color ); + + if( color != data.expectedColor ) + { + std::cout << " different color : " << color << ", expected : " << data.expectedColor << std::endl; + return false; + } + + return true; + } + + /////////////////////////////////////////////////////////// + + struct Vector4ToColorStringData + { + std::string description; + Vector4 color; + std::string expectedColorStr; + }; + + bool Vector4ToColorStringTest( const Vector4ToColorStringData& data ) + { + std::cout << " testing " << data.description << std::endl; + + std::string colorStr; + Vector4ToColorString( data.color, colorStr ); + + if( colorStr != data.expectedColorStr ) + { + std::cout << " different color : [" << colorStr << "], expected : [" << data.expectedColorStr << "]" << std::endl; + return false; + } + + return true; + } + + /////////////////////////////////////////////////////////// + + struct StringToVector2Data + { + std::string description; + std::string vector2Str; + Vector2 expectedVector2; + }; + + bool StringToVector2Test( const StringToVector2Data& data ) + { + std::cout << " testing " << data.description << std::endl; + + Vector2 vector2; + StringToVector2( data.vector2Str.c_str(), data.vector2Str.size(), vector2 ); + + if( vector2 != data.expectedVector2 ) + { + std::cout << " different vector2 : " << vector2 << ", expected : " << data.expectedVector2 << std::endl; + return false; + } + + return true; + } + + /////////////////////////////////////////////////////////// + + + struct Vector2ToStringData + { + std::string description; + Vector2 vector2; + std::string expectedVector2Str; + }; + + bool Vector2ToStringTest( const Vector2ToStringData& data ) + { + std::cout << " testing " << data.description << std::endl; + + std::string vector2Str; + Vector2ToString( data.vector2, vector2Str ); + + if( vector2Str != data.expectedVector2Str ) + { + std::cout << " different vector2 : [" << vector2Str << "], expected : [" << data.expectedVector2Str << "]" << std::endl; + return false; + } + + return true; + } + +} // namespace + +int UtcDaliTextTokenComparison(void) +{ + tet_infoline(" UtcDaliTextTokenComparison"); + + const TokenComparisonData data[] = + { + { + "void texts", + "", + "", + true + }, + { + "different size text", + "hello", + "world!", + false + }, + { + "different texts", + "hello", + "world", + false + }, + { + "same texts", + "world", + "wOrLD", + true + }, + { + "some punctuation characters, numbers, ...", + "hello0123456789.![?]", + "Hello0123456789.![?]", + true + } + + }; + const unsigned int numberOfTests = 5u; + + for( unsigned int index = 0u; index < numberOfTests; ++index ) + { + ToolkitTestApplication application; + if( !TokenComparisonTest( data[index] ) ) + { + tet_result(TET_FAIL); + } + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextColorStringToVector4(void) +{ + tet_infoline(" UtcDaliTextColorStringToVector4"); + + const ColorStringToVector4Data data[] = + { + { + "black string", + "bLack", + Color::BLACK + }, + { + "white string", + "White", + Color::WHITE + }, + { + "red string", + "reD", + Color::RED + }, + { + "green string", + "green", + Color::GREEN + }, + { + "blue string", + "blue", + Color::BLUE + }, + { + "yellow string", + "yeLloW", + Color::YELLOW + }, + { + "magenta string", + "MagEnta", + Color::MAGENTA + }, + { + "cyan string", + "CyaN", + Color::CYAN + }, + { + "transparent string", + "transparent", + Color::TRANSPARENT + }, + { + "3 component web color", + "#F00", + Color::RED + }, + { + "6 component web color", + "#fF0000", + Color::RED + }, + { + "hex color red (ARGB)", + "0xffff0000", + Color::RED + }, + { + "hex color green (ARGB)", + "0xFf00FF00", + Color::GREEN + }, + { + "undefined color", + "undefined", + Vector4::ZERO + }, + }; + const unsigned int numberOfTests = 14u; + + for( unsigned int index = 0u; index < numberOfTests; ++index ) + { + ToolkitTestApplication application; + if( !ColorStringToVector4Test( data[index] ) ) + { + tet_result(TET_FAIL); + } + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextVector4ToColorString(void) +{ + tet_infoline(" UtcDaliTextVector4ToColorString"); + + const Vector4ToColorStringData data[] = + { + { + "black color", + Color::BLACK, + "black" + }, + { + "white string", + Color::WHITE, + "white" + }, + { + "red string", + Color::RED, + "red" + }, + { + "green string", + Color::GREEN, + "green" + }, + { + "blue string", + Color::BLUE, + "blue" + }, + { + "yellow string", + Color::YELLOW, + "yellow" + }, + { + "magenta string", + Color::MAGENTA, + "magenta", + }, + { + "cyan string", + Color::CYAN, + "cyan" + }, + { + "transparent string", + Color::TRANSPARENT, + "transparent" + }, + { + "hex color", + Vector4( 0.4f, 0.5f, 0.6f, 1.f ), + "0xff667f99" + }, + }; + const unsigned int numberOfTests = 10u; + + for( unsigned int index = 0u; index < numberOfTests; ++index ) + { + ToolkitTestApplication application; + if( !Vector4ToColorStringTest( data[index] ) ) + { + tet_result(TET_FAIL); + } + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextStringToVector2(void) +{ + tet_infoline(" UtcDaliTextStringToVector2"); + const StringToVector2Data data[] = + { + { + "void text", + "", + Vector2::ZERO + }, + { + "zero zero", + "0 0", + Vector2::ZERO + }, + { + "five four", + "5 4", + Vector2(5.f, 4.f) + } + }; + const unsigned int numberOfTests = 3u; + + for( unsigned int index = 0u; index < numberOfTests; ++index ) + { + ToolkitTestApplication application; + if( !StringToVector2Test( data[index] ) ) + { + tet_result(TET_FAIL); + } + } + + tet_result(TET_PASS); + END_TEST; +} + +int UtcDaliTextVector2ToString(void) +{ + tet_infoline(" UtcDaliTextVector2ToString"); + const Vector2ToStringData data[] = + { + { + "zero zero", + Vector2::ZERO, + "0 0", + }, + { + "five four", + Vector2(5.f, 4.f), + "5 4", + } + }; + const unsigned int numberOfTests = 2u; + + for( unsigned int index = 0u; index < numberOfTests; ++index ) + { + ToolkitTestApplication application; + if( !Vector2ToStringTest( data[index] ) ) + { + tet_result(TET_FAIL); + } + } + + tet_result(TET_PASS); + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp index 83744f3..b6b638c 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp @@ -441,16 +441,16 @@ int UtcDaliTextEditorSetPropertyP(void) DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::INPUT_LINE_SPACING ), 20.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); // Check the underline property - editor.SetProperty( TextEditor::Property::UNDERLINE, "Underline properties" ); - DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::UNDERLINE ), std::string("Underline properties"), TEST_LOCATION ); + editor.SetProperty( TextEditor::Property::UNDERLINE, "{\"enable\":\"true\",\"color\":\"red\",\"height\":\"1\"}" ); + DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::UNDERLINE ), std::string("{\"enable\":\"true\",\"color\":\"red\",\"height\":\"1\"}"), TEST_LOCATION ); // Check the input underline property editor.SetProperty( TextEditor::Property::INPUT_UNDERLINE, "Underline input properties" ); DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::INPUT_UNDERLINE ), std::string("Underline input properties"), TEST_LOCATION ); // Check the shadow property - editor.SetProperty( TextEditor::Property::SHADOW, "Shadow properties" ); - DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION ); + editor.SetProperty( TextEditor::Property::SHADOW, "{\"color\":\"green\",\"offset\":\"2 2\"}" ); + DALI_TEST_EQUALS( editor.GetProperty( TextEditor::Property::SHADOW ), std::string("{\"color\":\"green\",\"offset\":\"2 2\"}"), TEST_LOCATION ); // Check the input shadow property editor.SetProperty( TextEditor::Property::INPUT_SHADOW, "Shadow input properties" ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp index 0335e4e..80ed1d7 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp @@ -612,16 +612,16 @@ int UtcDaliTextFieldSetPropertyP(void) DALI_TEST_EQUALS( field.GetProperty( TextField::Property::INPUT_FONT_STYLE ), std::string(""), TEST_LOCATION ); // Check the underline property - field.SetProperty( TextField::Property::UNDERLINE, "Underline properties" ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::UNDERLINE ), std::string("Underline properties"), TEST_LOCATION ); + field.SetProperty( TextField::Property::UNDERLINE, "{\"enable\":\"true\",\"color\":\"red\",\"height\":\"1\"}" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::UNDERLINE ), std::string("{\"enable\":\"true\",\"color\":\"red\",\"height\":\"1\"}"), TEST_LOCATION ); // Check the input underline property field.SetProperty( TextField::Property::INPUT_UNDERLINE, "Underline input properties" ); DALI_TEST_EQUALS( field.GetProperty( TextField::Property::INPUT_UNDERLINE ), std::string("Underline input properties"), TEST_LOCATION ); // Check the shadow property - field.SetProperty( TextField::Property::SHADOW, "Shadow properties" ); - DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION ); + field.SetProperty( TextField::Property::SHADOW, "{\"color\":\"green\",\"offset\":\"2 2\"}" ); + DALI_TEST_EQUALS( field.GetProperty( TextField::Property::SHADOW ), std::string("{\"color\":\"green\",\"offset\":\"2 2\"}"), TEST_LOCATION ); // Check the input shadow property field.SetProperty( TextField::Property::INPUT_SHADOW, "Shadow input properties" ); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp index 5f9a710..0f0072e 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp @@ -222,6 +222,8 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) // The underline color is changed as well. DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE_COLOR ), Color::BLUE, TEST_LOCATION ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE ), std::string("{\"enable\":\"false\",\"color\":\"blue\",\"height\":\"0\"}"), TEST_LOCATION ); + // Check that shadow parameters can be correctly set label.SetProperty( TextLabel::Property::SHADOW_OFFSET, Vector2( 3.0f, 3.0f ) ); DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW_OFFSET ), Vector2( 3.0f, 3.0f ), TEST_LOCATION ); @@ -266,12 +268,18 @@ int UtcDaliToolkitTextLabelSetPropertyP(void) DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::LINE_SPACING ), 10.0f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); // Check the underline property - label.SetProperty( TextLabel::Property::UNDERLINE, "Underline properties" ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE ), std::string("Underline properties"), TEST_LOCATION ); + label.SetProperty( TextLabel::Property::UNDERLINE, "{\"enable\":\"true\",\"color\":\"red\",\"height\":\"1\"}" ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE ), std::string("{\"enable\":\"true\",\"color\":\"red\",\"height\":\"1\"}"), TEST_LOCATION ); + + label.SetProperty( TextLabel::Property::UNDERLINE, "" ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::UNDERLINE ), std::string("{\"enable\":\"false\",\"color\":\"red\",\"height\":\"1\"}"), TEST_LOCATION ); // Check the shadow property - label.SetProperty( TextLabel::Property::SHADOW, "Shadow properties" ); - DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION ); + label.SetProperty( TextLabel::Property::SHADOW, "{\"color\":\"green\",\"offset\":\"2 2\"}" ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW ), std::string("{\"color\":\"green\",\"offset\":\"2 2\"}"), TEST_LOCATION ); + + label.SetProperty( TextLabel::Property::SHADOW, "" ); + DALI_TEST_EQUALS( label.GetProperty( TextLabel::Property::SHADOW ), std::string("{\"color\":\"green\",\"offset\":\"0 0\"}"), TEST_LOCATION ); // Check the emboss property label.SetProperty( TextLabel::Property::EMBOSS, "Emboss properties" ); @@ -395,14 +403,14 @@ int UtcDaliToolkitTextlabelScrollingP(void) Stage::GetCurrent().Add( label ); // Turn on all the effects label.SetProperty( TextLabel::Property::MULTI_LINE, false ); - label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, 50.0f ); - label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 3 ); - label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, 80.0f); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, 50.0f ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 3 ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, 80.0f ); try { // Render some text with the shared atlas backend - label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true ); + label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true ); application.SendNotification(); application.Render(); } @@ -414,6 +422,37 @@ int UtcDaliToolkitTextlabelScrollingP(void) END_TEST; } +int UtcDaliToolkitTextlabelScrollingN(void) +{ + ToolkitTestApplication application; + tet_infoline(" UtcDaliToolkitTextlabelScrollingN"); + + TextLabel label = TextLabel::New("Some text to scroll"); + DALI_TEST_CHECK( label ); + + Stage::GetCurrent().Add( label ); + + // Avoid a crash when core load gl resources. + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // The text scrolling works only on single line text. + label.SetProperty( TextLabel::Property::MULTI_LINE, true ); + + // Turn on all the effects. + label.SetProperty( TextLabel::Property::AUTO_SCROLL_GAP, 50.0f ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_LOOP_COUNT, 3 ); + label.SetProperty( TextLabel::Property::AUTO_SCROLL_SPEED, 80.0f ); + + // Enable the auto scrolling effect. + label.SetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL, true ); + + // The auto scrolling shouldn't be enabled. + const bool enabled = label.GetProperty( TextLabel::Property::ENABLE_AUTO_SCROLL ).Get(); + DALI_TEST_CHECK( !enabled ); + + END_TEST; +} + int UtcDaliToolkitTextlabelEllipsis(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index dc0723d..35c224e 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -16,6 +16,8 @@ #include #include +#include + #include #include #include @@ -35,6 +37,8 @@ const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg"; const char* TEST_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube.obj"; const char* TEST_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal.mtl"; const char* TEST_RESOURCE_LOCATION = TEST_RESOURCE_DIR "/"; + +const std::string DEFAULT_FONT_DIR( "/resources/fonts" ); } void dali_visual_startup(void) @@ -208,6 +212,12 @@ int UtcDaliVisualSize(void) // DALI_TEST_EQUALS( naturalSize, Vector2(100.f, 100.f), TEST_LOCATION ); + // svg visual with a size + Visual::Base svgVisual2 = factory.CreateVisual( TEST_SVG_FILE_NAME, ImageDimensions(200, 200) ); + DALI_TEST_EQUALS( svgVisual2.GetSize(), Vector2( 200.f, 200.f ), TEST_LOCATION ); + svgVisual2.GetNaturalSize(naturalSize); + DALI_TEST_EQUALS( naturalSize, Vector2(100.f, 100.f), TEST_LOCATION ); // Natural size should still be 100, 100 + // Batch Image visual propertyMap.Clear(); propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE ); @@ -219,6 +229,31 @@ int UtcDaliVisualSize(void) batchImageVisual.GetNaturalSize( naturalSize ); DALI_TEST_EQUALS( naturalSize, Vector2( 80.0f, 160.0f ), TEST_LOCATION ); + // Text visual. + + // Load some fonts to get the same metrics on different platforms. + TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); + fontClient.SetDpi( 96u, 96u ); + + char* pathNamePtr = get_current_dir_name(); + const std::string pathName( pathNamePtr ); + free( pathNamePtr ); + + fontClient.GetFontId( pathName + DEFAULT_FONT_DIR + "/tizen/TizenSansRegular.ttf" ); + + propertyMap.Clear(); + propertyMap.Insert( Visual::Property::TYPE, Visual::TEXT ); + propertyMap.Insert( TextVisual::Property::ENABLE_MARKUP, true ); + propertyMap.Insert( TextVisual::Property::TEXT, "Hello world" ); + propertyMap.Insert( TextVisual::Property::MULTI_LINE, true ); + + Visual::Base textVisual = factory.CreateVisual( propertyMap ); + textVisual.GetNaturalSize( naturalSize ); + DALI_TEST_EQUALS( naturalSize, Size( 80.f, 20.f ), TEST_LOCATION ); + + const float height = textVisual.GetHeightForWidth( 40.f ); + DALI_TEST_EQUALS( height, 40.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + END_TEST; } @@ -912,6 +947,95 @@ int UtcDaliVisualGetPropertyMapBatchImageVisual(void) END_TEST; } +//Text shape visual +int UtcDaliVisualGetPropertyMap10(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualGetPropertyMap10: TextVisual" ); + + //Request PrimitiveVisual using a property map. + VisualFactory factory = VisualFactory::Get(); + + Property::Map propertyMap; + propertyMap.Insert( Visual::Property::TYPE, Visual::TEXT ); + propertyMap.Insert( "renderingBackend", static_cast( Toolkit::Text::DEFAULT_RENDERING_BACKEND ) ); + propertyMap.Insert( "text", "Hello world" ); + propertyMap.Insert( "fontFamily", "TizenSans" ); + propertyMap.Insert( "fontStyle", "{\"weight\":\"bold\"}" ); + propertyMap.Insert( "pointSize", 12.f ); + propertyMap.Insert( "multiLine", true ); + propertyMap.Insert( "horizontalAlignment", "CENTER" ); + propertyMap.Insert( "verticalAlignment", "CENTER" ); + propertyMap.Insert( "textColor", Color::RED ); + propertyMap.Insert( "enableMarkup", false ); + propertyMap.Insert( "enableAutoScroll", false ); + propertyMap.Insert( "lineSpacing", 0.f ); + propertyMap.Insert( "batchingEnabled", false ); + Visual::Base textVisual = factory.CreateVisual( propertyMap ); + + Property::Map resultMap; + textVisual.CreatePropertyMap( resultMap ); + + //Check values in the result map are identical to the initial map's values. + Property::Value* value = resultMap.Find( Visual::Property::TYPE, Property::INTEGER ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), (int)Visual::TEXT, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::RENDERING_BACKEND, Property::INTEGER ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Toolkit::Text::DEFAULT_RENDERING_BACKEND, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::TEXT, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "Hello world", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::FONT_FAMILY, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "TizenSans", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::FONT_STYLE, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "{\"weight\":\"bold\"}", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::POINT_SIZE, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 12.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::MULTI_LINE, Property::BOOLEAN ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() ); + + value = resultMap.Find( TextVisual::Property::HORIZONTAL_ALIGNMENT, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "CENTER", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::VERTICAL_ALIGNMENT, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), "CENTER", TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::TEXT_COLOR, Property::VECTOR4 ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Color::RED, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::ENABLE_MARKUP, Property::BOOLEAN ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( !value->Get() ); + + value = resultMap.Find( TextVisual::Property::ENABLE_AUTO_SCROLL, Property::BOOLEAN ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( !value->Get() ); + + value = resultMap.Find( TextVisual::Property::LINE_SPACING, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + value = resultMap.Find( TextVisual::Property::BATCHING_ENABLED, Property::BOOLEAN ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( !value->Get() ); + + END_TEST; +} + int UtcDaliVisualGetPropertyMapBatchImageVisualNoAtlas(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp index 40e37c9..3fe52b4 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp @@ -1139,6 +1139,46 @@ int UtcDaliVisualFactoryGetSvgVisual(void) END_TEST; } +int UtcDaliVisualFactoryGetSvgVisualLarge(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualFactoryGetSvgVisual: Request svg visual with a svg url" ); + + VisualFactory factory = VisualFactory::Get(); + Visual::Base visual = factory.CreateVisual( TEST_SVG_FILE_NAME, ImageDimensions( 2000, 2000 ) ); + DALI_TEST_CHECK( visual ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable(true); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + visual.SetOnStage( actor ); + application.SendNotification(); + application.Render(); + + // renderer is not added to actor until the rasterization is completed. + DALI_TEST_CHECK( actor.GetRendererCount() == 0u ); + + EventThreadCallback* eventTrigger = EventThreadCallback::Get(); + CallbackBase* callback = eventTrigger->GetCallback(); + + eventTrigger->WaitingForTrigger( 1 );// waiting until the svg image is rasterized. + CallbackBase::Execute( *callback ); + + // renderer is added to actor + DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); + + // waiting for the resource uploading + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION ); + + END_TEST; +} + //Creates a mesh visual from the given propertyMap and tries to load it on stage in the given application. //This is expected to succeed, which will then pass the test. void MeshVisualLoadsCorrectlyTest( Property::Map& propertyMap, ToolkitTestApplication& application ) diff --git a/dali-toolkit/dali-toolkit.h b/dali-toolkit/dali-toolkit.h index 4e39d12..be46ddd 100644 --- a/dali-toolkit/dali-toolkit.h +++ b/dali-toolkit/dali-toolkit.h @@ -61,6 +61,7 @@ #include #include #include +#include #include #include diff --git a/dali-toolkit/devel-api/visual-factory/visual-base.cpp b/dali-toolkit/devel-api/visual-factory/visual-base.cpp index dfe7370..c40bc41 100644 --- a/dali-toolkit/devel-api/visual-factory/visual-base.cpp +++ b/dali-toolkit/devel-api/visual-factory/visual-base.cpp @@ -71,6 +71,11 @@ const Vector2& Visual::Base::GetSize() const return GetImplementation( *this ).GetSize(); } +float Visual::Base::GetHeightForWidth( float width ) const +{ + return GetImplementation( *this ).GetHeightForWidth( width ); +} + void Visual::Base::GetNaturalSize(Vector2& naturalSize ) const { GetImplementation( *this ).GetNaturalSize( naturalSize ); diff --git a/dali-toolkit/devel-api/visual-factory/visual-base.h b/dali-toolkit/devel-api/visual-factory/visual-base.h index c38720c..2cbb0b7 100644 --- a/dali-toolkit/devel-api/visual-factory/visual-base.h +++ b/dali-toolkit/devel-api/visual-factory/visual-base.h @@ -106,6 +106,15 @@ public: const Vector2& GetSize() const; /** + * @brief Returns the height for a given width. + * + * @param[in] width Width to use. + * + * @return The height based on the width. + */ + float GetHeightForWidth( float width ) const; + + /** * @brief Return the natural size of the visual. * * Deriving classes stipulate the natural size and by default a visual has a ZERO natural size. diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp index ddcb8d5..9d59568 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp @@ -933,7 +933,7 @@ void TextEditor::OnInitialize() { Actor self = Self(); - mController = Text::Controller::New( *this ); + mController = Text::Controller::New( this, this ); mDecorator = Text::Decorator::New( *mController, *mController ); @@ -949,6 +949,7 @@ void TextEditor::OnInitialize() // Disables the horizontal scrolling. mController->SetHorizontalScrollEnabled( false ); + // Sets the maximum number of characters. mController->SetMaximumNumberOfCharacters( std::numeric_limits::max() ); // Enable the smooth handle panning. @@ -1042,7 +1043,7 @@ void TextEditor::OnRelayout( const Vector2& size, RelayoutContainer& container ) mRenderer = Backend::Get().NewRenderer( mRenderingBackend ); } - EnableClipping( true, size ); + EnableClipping( size ); RenderText( updateTextType ); } @@ -1235,21 +1236,6 @@ bool TextEditor::OnKeyEvent( const KeyEvent& event ) return mController->KeyEvent( event ); } -void TextEditor::AddDecoration( Actor& actor, bool needsClipping ) -{ - if( actor ) - { - if( needsClipping ) - { - mClippingDecorationActors.push_back( actor ); - } - else - { - Self().Add( actor ); - } - } -} - void TextEditor::RequestTextRelayout() { RelayoutRequest(); @@ -1261,6 +1247,11 @@ void TextEditor::TextChanged() mTextChangedSignal.Emit( handle ); } +void TextEditor::MaxLengthReached() +{ + // Nothing to do as TextEditor doesn't emit a max length reached signal. +} + void TextEditor::InputStyleChanged( Text::InputStyle::Mask inputStyleMask ) { Dali::Toolkit::TextEditor handle( GetOwner() ); @@ -1315,9 +1306,19 @@ void TextEditor::InputStyleChanged( Text::InputStyle::Mask inputStyleMask ) mInputStyleChangedSignal.Emit( handle, editorInputStyleMask ); } -void TextEditor::MaxLengthReached() +void TextEditor::AddDecoration( Actor& actor, bool needsClipping ) { - // Nothing to do as TextEditor doesn't emit a max length reached signal. + if( actor ) + { + if( needsClipping ) + { + mClippingDecorationActors.push_back( actor ); + } + else + { + Self().Add( actor ); + } + } } void TextEditor::OnStageConnect( Dali::Actor actor ) @@ -1353,31 +1354,23 @@ void TextEditor::GetHandleImagePropertyValue( Property::Value& value, Text::Han } } -void TextEditor::EnableClipping( bool clipping, const Vector2& size ) +void TextEditor::EnableClipping( const Vector2& size ) { - if( clipping ) + // Not worth to created clip actor if width or height is equal to zero. + if( size.width > Math::MACHINE_EPSILON_1000 && size.height > Math::MACHINE_EPSILON_1000 ) { - // Not worth to created clip actor if width or height is equal to zero. - if( size.width > Math::MACHINE_EPSILON_1000 && size.height > Math::MACHINE_EPSILON_1000 ) + if( !mClipper ) { - if( !mClipper ) - { - Actor self = Self(); + Actor self = Self(); - mClipper = Clipper::New( size ); - self.Add( mClipper->GetRootActor() ); - self.Add( mClipper->GetImageView() ); - } - else if ( mClipper ) - { - mClipper->Refresh( size ); - } + mClipper = Clipper::New( size ); + self.Add( mClipper->GetRootActor() ); + self.Add( mClipper->GetImageView() ); + } + else if ( mClipper ) + { + mClipper->Refresh( size ); } - } - else - { - // Note - this will automatically remove the root actor & the image view - mClipper.Reset(); } } diff --git a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h index cb40406..2d7190b 100644 --- a/dali-toolkit/internal/controls/text-controls/text-editor-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-editor-impl.h @@ -1,5 +1,5 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H__ +#ifndef DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H +#define DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -18,18 +18,19 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include #include #include #include +#include #include #include -// EXTERNAL INCLUDES -#include - namespace Dali { @@ -42,7 +43,7 @@ namespace Internal /** * @brief A control which renders a long text string with styles. */ -class TextEditor : public Control, public Text::ControlInterface +class TextEditor : public Control, public Text::ControlInterface, public Text::EditableControlInterface { public: @@ -157,15 +158,12 @@ private: // From Control // From ControlInterface /** - * @copydoc Text::ControlInterface::AddDecoration() - */ - virtual void AddDecoration( Actor& actor, bool needsClipping ); - - /** * @copydoc Text::ControlInterface::RequestTextRelayout() */ virtual void RequestTextRelayout(); +// From EditableControlInterface + /** * @copydoc Text::ControlInterface::TextChanged() */ @@ -181,6 +179,11 @@ private: // From Control */ virtual void InputStyleChanged( Text::InputStyle::Mask inputStyleMask ); + /** + * @copydoc Text::ControlInterface::AddDecoration() + */ + virtual void AddDecoration( Actor& actor, bool needsClipping ); + private: // Implementation /** @@ -205,10 +208,9 @@ private: // Implementation /** * @brief Enable or disable clipping. * - * @param[in] clipping True if clipping should be enabled. * @param[in] size The area to clip within. */ - void EnableClipping( bool clipping, const Vector2& size ); + void EnableClipping( const Vector2& size ); /** * @brief Callback when keyboard is shown/hidden. @@ -299,4 +301,4 @@ inline const Toolkit::Internal::TextEditor& GetImpl( const Toolkit::TextEditor& } // namespace Dali -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H__ +#endif // DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp index e0d75ce..6e679e3 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.cpp @@ -1114,7 +1114,7 @@ void TextField::OnInitialize() { Actor self = Self(); - mController = Text::Controller::New( *this ); + mController = Text::Controller::New( this, this ); // When using the vector-based rendering, the size of the GLyphs are different TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; @@ -1222,7 +1222,7 @@ void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container ) mRenderer = Backend::Get().NewRenderer( mRenderingBackend ); } - EnableClipping( ( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy ), size ); + EnableClipping( size ); RenderText( updateTextType ); } @@ -1246,7 +1246,7 @@ void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container ) } } - void TextField::RenderText( Text::Controller::UpdateTextType updateTextType ) +void TextField::RenderText( Text::Controller::UpdateTextType updateTextType ) { Actor self = Self(); Actor renderableActor; @@ -1416,21 +1416,6 @@ bool TextField::OnKeyEvent( const KeyEvent& event ) return mController->KeyEvent( event ); } -void TextField::AddDecoration( Actor& actor, bool needsClipping ) -{ - if( actor ) - { - if( needsClipping ) - { - mClippingDecorationActors.push_back( actor ); - } - else - { - Self().Add( actor ); - } - } -} - void TextField::RequestTextRelayout() { RelayoutRequest(); @@ -1442,6 +1427,12 @@ void TextField::TextChanged() mTextChangedSignal.Emit( handle ); } +void TextField::MaxLengthReached() +{ + Dali::Toolkit::TextField handle( GetOwner() ); + mMaxLengthReachedSignal.Emit( handle ); +} + void TextField::InputStyleChanged( Text::InputStyle::Mask inputStyleMask ) { Dali::Toolkit::TextField handle( GetOwner() ); @@ -1492,6 +1483,21 @@ void TextField::InputStyleChanged( Text::InputStyle::Mask inputStyleMask ) mInputStyleChangedSignal.Emit( handle, fieldInputStyleMask ); } +void TextField::AddDecoration( Actor& actor, bool needsClipping ) +{ + if( actor ) + { + if( needsClipping ) + { + mClippingDecorationActors.push_back( actor ); + } + else + { + Self().Add( actor ); + } + } +} + void TextField::OnStageConnect( Dali::Actor actor ) { if ( mHasBeenStaged ) @@ -1504,12 +1510,6 @@ void TextField::OnStageConnect( Dali::Actor actor ) } } -void TextField::MaxLengthReached() -{ - Dali::Toolkit::TextField handle( GetOwner() ); - mMaxLengthReachedSignal.Emit( handle ); -} - ImfManager::ImfCallbackData TextField::OnImfEvent( Dali::ImfManager& imfManager, const ImfManager::ImfEventData& imfEvent ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField::OnImfEvent %p eventName %d\n", mController.Get(), imfEvent.eventName ); @@ -1531,9 +1531,9 @@ void TextField::GetHandleImagePropertyValue( Property::Value& value, Text::Hand } } -void TextField::EnableClipping( bool clipping, const Vector2& size ) +void TextField::EnableClipping( const Vector2& size ) { - if( clipping ) + if( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy ) { // Not worth to created clip actor if width or height is equal to zero. if( size.width > Math::MACHINE_EPSILON_1000 && size.height > Math::MACHINE_EPSILON_1000 ) diff --git a/dali-toolkit/internal/controls/text-controls/text-field-impl.h b/dali-toolkit/internal/controls/text-controls/text-field-impl.h index 558cced..e40c647 100644 --- a/dali-toolkit/internal/controls/text-controls/text-field-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-field-impl.h @@ -1,5 +1,5 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__ +#ifndef DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H +#define DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -18,18 +18,19 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include #include #include #include +#include #include #include -// EXTERNAL INCLUDES -#include - namespace Dali { @@ -42,7 +43,7 @@ namespace Internal /** * @brief A control which renders a short text string. */ -class TextField : public Control, public Text::ControlInterface +class TextField : public Control, public Text::ControlInterface, public Text::EditableControlInterface { public: @@ -162,15 +163,12 @@ private: // From Control // From ControlInterface /** - * @copydoc Text::ControlInterface::AddDecoration() - */ - virtual void AddDecoration( Actor& actor, bool needsClipping ); - - /** * @copydoc Text::ControlInterface::RequestTextRelayout() */ virtual void RequestTextRelayout(); +// From EditableControlInterface + /** * @copydoc Text::ControlInterface::TextChanged() */ @@ -186,6 +184,11 @@ private: // From Control */ virtual void InputStyleChanged( Text::InputStyle::Mask inputStyleMask ); + /** + * @copydoc Text::ControlInterface::AddDecoration() + */ + virtual void AddDecoration( Actor& actor, bool needsClipping ); + private: // Implementation /** @@ -210,10 +213,9 @@ private: // Implementation /** * @brief Enable or disable clipping. * - * @param[in] clipping True if clipping should be enabled. * @param[in] size The area to clip within. */ - void EnableClipping( bool clipping, const Vector2& size ); + void EnableClipping( const Vector2& size ); /** * @brief Callback when keyboard is shown/hidden. @@ -306,4 +308,4 @@ inline const Toolkit::Internal::TextField& GetImpl( const Toolkit::TextField& te } // namespace Dali -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__ +#endif // DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index bf8c866..955e0f2 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -24,17 +24,11 @@ // INTERNAL INCLUDES #include -#include -#include -#include +#include #include -#include -#include -#include #include using Dali::Toolkit::Text::LayoutEngine; -using Dali::Toolkit::Text::Backend; namespace Dali { @@ -57,22 +51,6 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS"); #endif -const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] = -{ - { "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN }, - { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER }, - { "END", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END }, -}; -const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); - -const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] = -{ - { "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP }, - { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER }, - { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM }, -}; -const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); - // Type registration BaseHandle Create() { @@ -109,7 +87,33 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextLabel, "outline", STRING, DALI_TYPE_REGISTRATION_END() - +const int TEXT_VISUAL_PROPERTY_TABLE[] = { + Dali::Toolkit::TextVisual::Property::RENDERING_BACKEND, + Dali::Toolkit::TextVisual::Property::TEXT, + Dali::Toolkit::TextVisual::Property::FONT_FAMILY, + Dali::Toolkit::TextVisual::Property::FONT_STYLE, + Dali::Toolkit::TextVisual::Property::POINT_SIZE, + Dali::Toolkit::TextVisual::Property::MULTI_LINE, + Dali::Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, + Dali::Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, + Dali::Toolkit::TextVisual::Property::TEXT_COLOR, + Dali::Toolkit::TextVisual::Property::SHADOW, + Dali::Toolkit::TextVisual::Property::SHADOW, + Dali::Toolkit::TextVisual::Property::UNDERLINE, + Dali::Toolkit::TextVisual::Property::UNDERLINE, + Dali::Toolkit::TextVisual::Property::UNDERLINE, + Dali::Toolkit::TextVisual::Property::ENABLE_MARKUP, + Dali::Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL, + Dali::Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED, + Dali::Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT, + Dali::Toolkit::TextVisual::Property::AUTO_SCROLL_GAP, + Dali::Toolkit::TextVisual::Property::LINE_SPACING, + Dali::Toolkit::TextVisual::Property::UNDERLINE, + Dali::Toolkit::TextVisual::Property::SHADOW, + Dali::Toolkit::TextVisual::Property::EMBOSS, + Dali::Toolkit::TextVisual::Property::OUTLINE, + Dali::Toolkit::TextVisual::Property::BATCHING_ENABLED +}; } // namespace @@ -134,298 +138,10 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr if( label ) { - TextLabel& impl( GetImpl( label ) ); - switch( index ) - { - case Toolkit::TextLabel::Property::RENDERING_BACKEND: - { - int backend = value.Get< int >(); - -#ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING - if( Text::RENDERING_VECTOR_BASED == backend ) - { - backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering - } -#endif - if( impl.mRenderingBackend != backend ) - { - impl.mRenderingBackend = backend; - impl.mRenderer.Reset(); - - if( impl.mController ) - { - // When using the vector-based rendering, the size of the GLyphs are different - TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; - impl.mController->SetGlyphType( glyphType ); - } - } - break; - } - case Toolkit::TextLabel::Property::TEXT: - { - if( impl.mController ) - { - impl.mController->SetText( value.Get< std::string >() ); - } - break; - } - case Toolkit::TextLabel::Property::FONT_FAMILY: - { - if( impl.mController ) - { - const std::string fontFamily = value.Get< std::string >(); - - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextLabel::SetProperty Property::FONT_FAMILY newFont(%s)\n", fontFamily.c_str() ); - impl.mController->SetDefaultFontFamily( fontFamily ); - } - break; - } - case Toolkit::TextLabel::Property::FONT_STYLE: - { - SetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::POINT_SIZE: - { - if( impl.mController ) - { - const float pointSize = value.Get< float >(); - - if( !Equals( impl.mController->GetDefaultPointSize(), pointSize ) ) - { - impl.mController->SetDefaultPointSize( pointSize ); - } - } - break; - } - case Toolkit::TextLabel::Property::MULTI_LINE: - { - if( impl.mController ) - { - impl.mController->SetMultiLineEnabled( value.Get< bool >() ); - } - break; - } - case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT: - { - if( impl.mController ) - { - LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ); - if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( value.Get< std::string >().c_str(), - HORIZONTAL_ALIGNMENT_STRING_TABLE, - HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT, - alignment ) ) - { - impl.mController->SetHorizontalAlignment( alignment ); - } - } - break; - } - case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT: - { - if( impl.mController ) - { - LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM ); - if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( value.Get< std::string >().c_str(), - VERTICAL_ALIGNMENT_STRING_TABLE, - VERTICAL_ALIGNMENT_STRING_TABLE_COUNT, - alignment ) ) - { - impl.mController->SetVerticalAlignment( alignment ); - } - } - break; - } - - case Toolkit::TextLabel::Property::TEXT_COLOR: - { - if( impl.mController ) - { - const Vector4 textColor = value.Get< Vector4 >(); - if( impl.mController->GetTextColor() != textColor ) - { - impl.mController->SetTextColor( textColor ); - impl.mRenderer.Reset(); - } - } - break; - } - - case Toolkit::TextLabel::Property::SHADOW_OFFSET: - { - if( impl.mController ) - { - const Vector2 shadowOffset = value.Get< Vector2 >(); - if ( impl.mController->GetShadowOffset() != shadowOffset ) - { - impl.mController->SetShadowOffset( shadowOffset ); - impl.mRenderer.Reset(); - } - } - break; - } - case Toolkit::TextLabel::Property::SHADOW_COLOR: - { - if( impl.mController ) - { - const Vector4 shadowColor = value.Get< Vector4 >(); - if ( impl.mController->GetShadowColor() != shadowColor ) - { - impl.mController->SetShadowColor( shadowColor ); - impl.mRenderer.Reset(); - } - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_COLOR: - { - if( impl.mController ) - { - const Vector4 color = value.Get< Vector4 >(); - if ( impl.mController->GetUnderlineColor() != color ) - { - impl.mController->SetUnderlineColor( color ); - impl.mRenderer.Reset(); - } - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: - { - if( impl.mController ) - { - const bool enabled = value.Get< bool >(); - if ( impl.mController->IsUnderlineEnabled() != enabled ) - { - impl.mController->SetUnderlineEnabled( enabled ); - impl.mRenderer.Reset(); - } - } - break; - } + TextLabel& impl = GetImpl( label ); - case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT: - { - if( impl.mController ) - { - float height = value.Get< float >(); - if( fabsf( impl.mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) - { - impl.mController->SetUnderlineHeight( height ); - impl.mRenderer.Reset(); - } - } - break; - } - case Toolkit::TextLabel::Property::ENABLE_MARKUP: - { - if( impl.mController ) - { - const bool enableMarkup = value.Get(); - impl.mController->SetMarkupProcessorEnabled( enableMarkup ); - } - break; - } - case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL: - { - if( impl.mController ) - { - const bool enableAutoScroll = value.Get(); - // If request to auto scroll is the same as current state then do nothing. - if ( enableAutoScroll != impl.mController->IsAutoScrollEnabled() ) - { - // If request is disable (false) and auto scrolling is enabled then need to stop it - if ( enableAutoScroll == false ) - { - if( impl.mTextScroller ) - { - impl.mTextScroller->SetLoopCount( 0 ); // Causes the current animation to finish playing (0) - } - } - // If request is enable (true) then start autoscroll as not already running - else - { - impl.mController->GetLayoutEngine().SetTextEllipsisEnabled( false ); - impl.mController->SetAutoScrollEnabled( enableAutoScroll ); - } - } - } - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED: - { - if( !impl.mTextScroller ) - { - impl.mTextScroller = Text::TextScroller::New( impl ); - } - impl.mTextScroller->SetSpeed( value.Get() ); - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT: - { - if( !impl.mTextScroller ) - { - impl.mTextScroller = Text::TextScroller::New( impl ); - } - impl.mTextScroller->SetLoopCount( value.Get() ); - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP: - { - if( !impl.mTextScroller ) - { - impl.mTextScroller = Text::TextScroller::New( impl ); - } - impl.mTextScroller->SetGap( value.Get() ); - break; - } - case Toolkit::TextLabel::Property::LINE_SPACING: - { - if( impl.mController ) - { - const float lineSpacing = value.Get(); - impl.mController->SetDefaultLineSpacing( lineSpacing ); - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE: - { - const bool update = SetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - if( update ) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextLabel::Property::SHADOW: - { - const bool update = SetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - if( update ) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextLabel::Property::EMBOSS: - { - const bool update = SetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - if( update ) - { - impl.mRenderer.Reset(); - } - break; - } - case Toolkit::TextLabel::Property::OUTLINE: - { - const bool update = SetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - if( update ) - { - impl.mRenderer.Reset(); - } - break; - } - } + // Sets the property to the to the text visual. + impl.mVisual.SetProperty( TEXT_VISUAL_PROPERTY_TABLE[index - Toolkit::TextLabel::PROPERTY_START_INDEX], value ); } } @@ -437,204 +153,127 @@ Property::Value TextLabel::GetProperty( BaseObject* object, Property::Index inde if( label ) { - TextLabel& impl( GetImpl( label ) ); - switch( index ) + TextLabel& impl = GetImpl( label ); + + if( ( Toolkit::TextLabel::Property::SHADOW_OFFSET == index ) || + ( Toolkit::TextLabel::Property::SHADOW_COLOR == index ) || + ( Toolkit::TextLabel::Property::UNDERLINE_ENABLED == index ) || + ( Toolkit::TextLabel::Property::UNDERLINE_COLOR == index ) || + ( Toolkit::TextLabel::Property::UNDERLINE_HEIGHT == index ) ) { - case Toolkit::TextLabel::Property::RENDERING_BACKEND: - { - value = impl.mRenderingBackend; - break; - } - case Toolkit::TextLabel::Property::TEXT: - { - if( impl.mController ) - { - std::string text; - impl.mController->GetText( text ); - value = text; - } - break; - } - case Toolkit::TextLabel::Property::FONT_FAMILY: - { - if( impl.mController ) - { - value = impl.mController->GetDefaultFontFamily(); - } - break; - } - case Toolkit::TextLabel::Property::FONT_STYLE: - { - GetFontStyleProperty( impl.mController, value, Text::FontStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::POINT_SIZE: - { - if( impl.mController ) - { - value = impl.mController->GetDefaultPointSize(); - } - break; - } - case Toolkit::TextLabel::Property::MULTI_LINE: - { - if( impl.mController ) - { - value = impl.mController->IsMultiLineEnabled(); - } - break; - } - case Toolkit::TextLabel::Property::HORIZONTAL_ALIGNMENT: + // TODO : Branch to be removed when the deprecated properties are finally removed. + value = impl.mVisual.GetProperty( TEXT_VISUAL_PROPERTY_TABLE[index - Toolkit::TextLabel::PROPERTY_START_INDEX] ); + + switch( index ) { - if( impl.mController ) + case Toolkit::TextLabel::Property::SHADOW_OFFSET: // Converts the deprecated property to the new one. { - const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( impl.mController->GetHorizontalAlignment(), - HORIZONTAL_ALIGNMENT_STRING_TABLE, - HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); - if( name ) + bool colorDefined = false; + Vector4 color; + bool offsetDefined = false; + Vector2 offset; + const bool empty = Text::ParseProperties( value.Get(), + colorDefined, + color, + offsetDefined, + offset ); + + if( !empty ) { - value = std::string( name ); + value = offset; } + break; } - break; - } - case Toolkit::TextLabel::Property::VERTICAL_ALIGNMENT: - { - if( impl.mController ) + case Toolkit::TextLabel::Property::SHADOW_COLOR: // Converts the deprecated property to the new one. { - const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( impl.mController->GetVerticalAlignment(), - VERTICAL_ALIGNMENT_STRING_TABLE, - VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); - if( name ) + bool colorDefined = false; + Vector4 color; + bool offsetDefined = false; + Vector2 offset; + const bool empty = Text::ParseProperties( value.Get(), + colorDefined, + color, + offsetDefined, + offset ); + + if( !empty ) { - value = std::string( name ); + value = color; } - } - break; - } - case Toolkit::TextLabel::Property::TEXT_COLOR: - { - if ( impl.mController ) - { - value = impl.mController->GetTextColor(); - } - break; - } - case Toolkit::TextLabel::Property::SHADOW_OFFSET: - { - if ( impl.mController ) - { - value = impl.mController->GetShadowOffset(); - } - break; - } - case Toolkit::TextLabel::Property::SHADOW_COLOR: - { - if ( impl.mController ) - { - value = impl.mController->GetShadowColor(); - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_COLOR: - { - if ( impl.mController ) - { - value = impl.mController->GetUnderlineColor(); - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: - { - if ( impl.mController ) - { - value = impl.mController->IsUnderlineEnabled(); - } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT: - { - if ( impl.mController ) - { - value = impl.mController->GetUnderlineHeight(); - } - break; - } - case Toolkit::TextLabel::Property::ENABLE_MARKUP: - { - if( impl.mController ) - { - value = impl.mController->IsMarkupProcessorEnabled(); - } - break; - } - case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL: - { - if( impl.mController ) - { - value = impl.mController->IsAutoScrollEnabled(); - } - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_SPEED: - { - TextLabel& impl( GetImpl( label ) ); - if ( impl.mTextScroller ) - { - value = impl.mTextScroller->GetSpeed(); - } - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT: - { - if( impl.mController ) - { - TextLabel& impl( GetImpl( label ) ); - if ( impl.mTextScroller ) + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_ENABLED: // Converts the deprecated property to the new one. + { + bool enabled = false; + bool colorDefined = false; + Vector4 color; + bool heightDefined = false; + float height = 0.f; + const bool empty = Text::ParseProperties( value.Get(), + enabled, + colorDefined, + color, + heightDefined, + height ); + + if( !empty ) { - value = impl.mTextScroller->GetLoopCount(); + value = enabled; } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_COLOR: // Converts the deprecated property to the new one. + { + bool enabled = false; + bool colorDefined = false; + Vector4 color; + bool heightDefined = false; + float height = 0.f; + const bool empty = Text::ParseProperties( value.Get(), + enabled, + colorDefined, + color, + heightDefined, + height ); + + if( !empty && colorDefined ) + { + value = color; + } + break; + } + case Toolkit::TextLabel::Property::UNDERLINE_HEIGHT: // Converts the deprecated property to the new one. + { + bool enabled = false; + bool colorDefined = false; + Vector4 color; + bool heightDefined = false; + float height = 0.f; + const bool empty = Text::ParseProperties( value.Get(), + enabled, + colorDefined, + color, + heightDefined, + height ); + + if( !empty && heightDefined ) + { + value = height; + } + break; } - break; - } - case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP: - { - TextLabel& impl( GetImpl( label ) ); - if ( impl.mTextScroller ) - { - value = impl.mTextScroller->GetGap(); - } - break; - } - case Toolkit::TextLabel::Property::LINE_SPACING: - { - if( impl.mController ) + default: { - value = impl.mController->GetDefaultLineSpacing(); + // Nothing to do. + break; } - break; - } - case Toolkit::TextLabel::Property::UNDERLINE: - { - GetUnderlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::SHADOW: - { - GetShadowProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::EMBOSS: - { - GetEmbossProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - break; - } - case Toolkit::TextLabel::Property::OUTLINE: - { - GetOutlineProperties( impl.mController, value, Text::EffectStyle::DEFAULT ); - break; } } + else + { + // Retrieves the property from the text visual. + value = impl.mVisual.GetProperty( TEXT_VISUAL_PROPERTY_TABLE[index - Toolkit::TextLabel::PROPERTY_START_INDEX] ); + } } return value; @@ -644,23 +283,23 @@ void TextLabel::OnInitialize() { Actor self = Self(); - mController = Text::Controller::New( *this ); + // Creates the text's visual. + Property::Map visualMap; + visualMap[Toolkit::Visual::Property::TYPE] = Toolkit::Visual::TEXT; + visualMap[Toolkit::TextVisual::Property::RENDERING_BACKEND] = static_cast( DEFAULT_RENDERING_BACKEND ); + + mVisual = Toolkit::VisualFactory::Get().CreateVisual( visualMap ); + RegisterVisual( Toolkit::TextLabel::Property::TEXT, self, mVisual ); - // When using the vector-based rendering, the size of the GLyphs are different - TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; - mController->SetGlyphType( glyphType ); + Internal::Visual::Base& visualBase = Toolkit::GetImplementation( mVisual ); + TextVisual* textVisual = static_cast( &visualBase ); + + // Sets the text's control interface. + textVisual->SetTextControlInterface( this ); // Use height-for-width negotiation by default self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH ); self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); - - // Enable the text ellipsis. - LayoutEngine& engine = mController->GetLayoutEngine(); - - engine.SetTextEllipsisEnabled( true ); // If false then text larger than control will overflow - engine.SetCursorWidth( 0u ); // Do not layout space for the cursor. - - self.OnStageSignal().Connect( this, &TextLabel::OnStageConnect ); } void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange::Type change ) @@ -674,10 +313,11 @@ void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange:: // Property system did not set the font so should update it. const std::string& newFont = GetImpl( styleManager ).GetDefaultFontFamily(); DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnStyleChange StyleChange::DEFAULT_FONT_CHANGE newFont(%s)\n", newFont.c_str() ); - mController->UpdateAfterFontChange( newFont ); + + const std::string fontString = "{\"family\":\"" + newFont + "\",\"type\":\"system\"}"; + mVisual.SetProperty( Toolkit::TextVisual::Property::FONT_FAMILY, fontString ); break; } - case StyleChange::DEFAULT_FONT_SIZE_CHANGE: { GetImpl( styleManager ).ApplyThemeStyle( Toolkit::Control( GetOwner() ) ); @@ -693,29 +333,22 @@ void TextLabel::OnStyleChange( Toolkit::StyleManager styleManager, StyleChange:: Vector3 TextLabel::GetNaturalSize() { - return mController->GetNaturalSize(); + Vector2 naturalSize; + mVisual.GetNaturalSize( naturalSize ); + + return Vector3( naturalSize ); } float TextLabel::GetHeightForWidth( float width ) { - return mController->GetHeightForWidth( width ); + return mVisual.GetHeightForWidth( width ); } void TextLabel::OnRelayout( const Vector2& size, RelayoutContainer& container ) { DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::OnRelayout\n" ); - const Text::Controller::UpdateTextType updateTextType = mController->Relayout( size ); - - if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) ) || - !mRenderer ) - { - if( !mRenderer ) - { - mRenderer = Backend::Get().NewRenderer( mRenderingBackend ); - } - RenderText(); - } + mVisual.SetSize( size ); } void TextLabel::RequestTextRelayout() @@ -723,115 +356,16 @@ void TextLabel::RequestTextRelayout() RelayoutRequest(); } -void TextLabel::RenderText() -{ - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::RenderText IsAutoScrollEnabled[%s] [%p]\n", ( mController->IsAutoScrollEnabled())?"true":"false", this ); - - Actor self = Self(); - Actor renderableActor; - - if( mRenderer ) - { - renderableActor = mRenderer->Render( mController->GetView(), DepthIndex::TEXT ); - } - - if( renderableActor != mRenderableActor ) - { - UnparentAndReset( mRenderableActor ); - - if( renderableActor ) - { - const Vector2& scrollOffset = mController->GetScrollPosition(); - renderableActor.SetPosition( scrollOffset.x, scrollOffset.y ); - - self.Add( renderableActor ); - } - mRenderableActor = renderableActor; - - if ( mController->IsAutoScrollEnabled() ) - { - SetUpAutoScrolling(); - } - } -} - -void TextLabel::SetUpAutoScrolling() -{ - const Size& controlSize = mController->GetView().GetControlSize(); - const Size offScreenSize = GetNaturalSize().GetVectorXY(); // As relayout of text may not be done at this point natural size is used to get size. Single line scrolling only. - const float alignmentOffset = mController->GetAutoScrollLineAlignment(); - const Text::CharacterDirection direction = mController->GetAutoScrollDirection(); - - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling alignmentOffset[%f] offScreenSize[%f,%f] controlSize[%f,%f]\n", - alignmentOffset, offScreenSize.x,offScreenSize.y , controlSize.x,controlSize.y ); - - if ( !mTextScroller ) - { - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::SetUpAutoScrolling Creating default TextScoller\n" ); - - // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults - mTextScroller = Text::TextScroller::New( *this ); - } - mTextScroller->SetParameters( mRenderableActor, controlSize, offScreenSize, direction, alignmentOffset ); - - Actor self = Self(); - self.Add( mTextScroller->GetScrollingText() ); - self.Add( mTextScroller->GetSourceCamera() ); -} - -void TextLabel::OnStageConnect( Dali::Actor actor ) -{ - if ( mHasBeenStaged ) - { - RenderText(); - } - else - { - mHasBeenStaged = true; - } -} - -void TextLabel::AddDecoration( Actor& actor, bool needsClipping ) -{ - // TextLabel does not show decorations -} - void TextLabel::OnStageConnection( int depth ) { // Call the Control::OnStageConnection() to set the depth of the background. Control::OnStageConnection( depth ); - // The depth of the text renderer is set in the RenderText() called from OnRelayout(). -} - -void TextLabel::TextChanged() -{ - // TextLabel does not provide a signal for this. -} - -void TextLabel::MaxLengthReached() -{ - // Pure Virtual from TextController Interface, only needed when inputting text -} - -void TextLabel::InputStyleChanged( Text::InputStyle::Mask inputStyleMask ) -{ - // TextLabel does not provide a signal for this. -} - -void TextLabel::ScrollingFinished() -{ - // Pure Virtual from TextScroller Interface - DALI_LOG_INFO( gLogFilter, Debug::General, "TextLabel::ScrollingFinished\n"); - mController->SetAutoScrollEnabled( false ); - mController->GetLayoutEngine().SetTextEllipsisEnabled( true ); - RequestTextRelayout(); + // The depth of the text renderer is set by the text-visual called from OnRelayout(). } TextLabel::TextLabel() -: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), - mRenderingBackend( DEFAULT_RENDERING_BACKEND ), - mHasBeenStaged( false ) +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ) { } diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.h b/dali-toolkit/internal/controls/text-controls/text-label-impl.h index 298ba1a..bdc587d 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.h +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.h @@ -1,5 +1,5 @@ -#ifndef __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__ -#define __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__ +#ifndef DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H +#define DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -21,10 +21,8 @@ // INTERNAL INCLUDES #include #include -#include -#include -#include -#include +#include +#include namespace Dali { @@ -38,7 +36,7 @@ namespace Internal /** * @brief A control which renders a short text string. */ -class TextLabel : public Control, public Text::ControlInterface, public Text::ScrollerInterface +class TextLabel : public Control, public Text::ControlInterface { public: @@ -95,42 +93,17 @@ private: // From Control virtual float GetHeightForWidth( float width ); /** - * @copydoc Text::ControlInterface::AddDecoration() - */ - virtual void AddDecoration( Actor& actor, bool needsClipping ); - - /** * @copydoc Control::OnStageConnection() */ virtual void OnStageConnection( int depth ); +// From ControlInterface + /** * @copydoc Text::ControlInterface::RequestTextRelayout() */ virtual void RequestTextRelayout(); - /** - * @copydoc Text::ControlInterface::TextChanged() - */ - virtual void TextChanged(); - - /** - * @copydoc Text::ControlInterface::MaxLengthReached() - */ - virtual void MaxLengthReached(); - - /** - * @copydoc Text::ControlInterface::InputStyleChanged() - */ - virtual void InputStyleChanged( Text::InputStyle::Mask inputStyleMask ); - -private: // from TextScroller - - /** - * @copydoc Text::ScrollerInterface::ScrollingFinished() - */ - virtual void ScrollingFinished(); - private: // Implementation /** @@ -149,27 +122,9 @@ private: TextLabel(const TextLabel&); TextLabel& operator=(const TextLabel& rhs); - // Connection needed to re-render text, when a Text Label returns to the stage - void OnStageConnect( Dali::Actor actor ); - - /** - * @brief Render view, create and attach actor(s) to this Text Label - */ - void RenderText(); - - /** - * @brief Set up Autoscrolling - */ - void SetUpAutoScrolling(); - private: // Data - Text::ControllerPtr mController; - Text::RendererPtr mRenderer; - Text::TextScrollerPtr mTextScroller; - Actor mRenderableActor; - int mRenderingBackend; - bool mHasBeenStaged:1; + Toolkit::Visual::Base mVisual; }; } // namespace Internal @@ -198,4 +153,4 @@ inline const Toolkit::Internal::TextLabel& GetImpl( const Toolkit::TextLabel& te } // namespace Dali -#endif // __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__ +#endif // DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 8437cef..57b4dbf 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -29,6 +29,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/visuals/primitive/primitive-visual.cpp \ $(toolkit_src_dir)/visuals/svg/svg-rasterize-thread.cpp \ $(toolkit_src_dir)/visuals/svg/svg-visual.cpp \ + $(toolkit_src_dir)/visuals/text/text-visual.cpp \ $(toolkit_src_dir)/visuals/wireframe/wireframe-visual.cpp \ $(toolkit_src_dir)/visuals/transition-data-impl.cpp \ $(toolkit_src_dir)/controls/alignment/alignment-impl.cpp \ @@ -107,13 +108,13 @@ toolkit_src_files = \ $(toolkit_src_dir)/text/property-string-parser.cpp \ $(toolkit_src_dir)/text/segmentation.cpp \ $(toolkit_src_dir)/text/shaper.cpp \ - $(toolkit_src_dir)/text/text-control-interface.cpp \ $(toolkit_src_dir)/text/text-controller.cpp \ $(toolkit_src_dir)/text/text-controller-impl.cpp \ $(toolkit_src_dir)/text/text-effects-style.cpp \ $(toolkit_src_dir)/text/text-font-style.cpp \ $(toolkit_src_dir)/text/text-io.cpp \ $(toolkit_src_dir)/text/text-scroller.cpp \ + $(toolkit_src_dir)/text/text-scroller-data.cpp \ $(toolkit_src_dir)/text/text-scroller-interface.cpp \ $(toolkit_src_dir)/text/text-view.cpp \ $(toolkit_src_dir)/text/text-view-interface.cpp \ diff --git a/dali-toolkit/internal/text/markup-processor-helper-functions.cpp b/dali-toolkit/internal/text/markup-processor-helper-functions.cpp index 3c02c27..8af6140 100644 --- a/dali-toolkit/internal/text/markup-processor-helper-functions.cpp +++ b/dali-toolkit/internal/text/markup-processor-helper-functions.cpp @@ -20,7 +20,10 @@ // EXTERNAL INCLUDES #include +#include #include +#include +#include namespace Dali { @@ -33,9 +36,10 @@ namespace Text namespace { -const char WHITE_SPACE = 0x20; // ASCII value of the white space. -const char LAST_UPPER_CASE = 0x5b; // ASCII value of the one after the last upper case character (Z). -const char TO_LOWER_CASE = 32; // Value to add to a upper case character to transform it into a lower case. +const char WHITE_SPACE = 0x20; // ASCII value of the white space. +const char FIRST_UPPER_CASE = 0x41; // ASCII value of the one after the first upper case character (A). +const char LAST_UPPER_CASE = 0x5b; // ASCII value of the one after the last upper case character (Z). +const char TO_LOWER_CASE = 32; // Value to add to a upper case character to transform it into a lower case. const char WEB_COLOR_TOKEN( '#' ); const char* const HEX_COLOR_TOKEN( "0x" ); @@ -65,8 +69,9 @@ bool TokenComparison( const std::string& string1, const char* const stringBuffer for( std::size_t index = 0; index < stringSize; ++index ) { - char character = *( stringBuffer2 + index ); - if( *( stringBuffer1 + index ) != ( ( ( character < LAST_UPPER_CASE ) && ( '0' != character ) ) ? character + TO_LOWER_CASE : character ) ) + const char character = *( stringBuffer2 + index ); + const bool toLower = ( character < LAST_UPPER_CASE ) && ( character >= FIRST_UPPER_CASE ); + if( *( stringBuffer1 + index ) != ( toLower ? character + TO_LOWER_CASE : character ) ) { return false; } @@ -75,10 +80,16 @@ bool TokenComparison( const std::string& string1, const char* const stringBuffer return true; } -void SkipWhiteSpace( const char*& markupStringBuffer, - const char* const markupStringEndBuffer ) +void SkipWhiteSpace( const char*& stringBuffer, + const char* const stringEndBuffer ) { - for( ; ( WHITE_SPACE >= *markupStringBuffer ) && ( markupStringBuffer < markupStringEndBuffer ); ++markupStringBuffer ); + for( ; ( WHITE_SPACE >= *stringBuffer ) && ( stringBuffer < stringEndBuffer ); ++stringBuffer ); +} + +void JumpToWhiteSpace( const char*& stringBuffer, + const char* const stringEndBuffer ) +{ + for( ; ( WHITE_SPACE != *stringBuffer ) && ( stringBuffer < stringEndBuffer ); ++stringBuffer ); } unsigned int StringToHex( const char* const uintStr ) @@ -91,6 +102,13 @@ float StringToFloat( const char* const floatStr ) return static_cast( strtod( floatStr, NULL ) ); } +void FloatToString( float value, std::string& floatStr ) +{ + std::stringstream ss; + ss << value; + floatStr = ss.str(); +} + void UintColorToVector4( unsigned int color, Vector4& retColor ) { retColor.a = static_cast( ( color & 0xFF000000 ) >> 24u ) / 255.f; @@ -160,6 +178,112 @@ void ColorStringToVector4( const char* const colorStr, Length length, Vector4& r } } +void Vector4ToColorString( const Vector4& value, std::string& vector2Str ) +{ + if( Color::BLACK == value ) + { + vector2Str = BLACK_COLOR; + return; + } + + if( Color::WHITE == value ) + { + vector2Str = WHITE_COLOR; + return; + } + + if( Color::RED == value ) + { + vector2Str = RED_COLOR; + return; + } + + if( Color::GREEN == value ) + { + vector2Str = GREEN_COLOR; + return; + } + + if( Color::BLUE == value ) + { + vector2Str = BLUE_COLOR; + return; + } + + if( Color::YELLOW == value ) + { + vector2Str = YELLOW_COLOR; + return; + } + + if( Color::MAGENTA == value ) + { + vector2Str = MAGENTA_COLOR; + return; + } + + if( Color::CYAN == value ) + { + vector2Str = CYAN_COLOR; + return; + } + + if( Color::TRANSPARENT == value ) + { + vector2Str = TRANSPARENT_COLOR; + return; + } + + const unsigned int alpha = static_cast( 255.f * value.a ); + const unsigned int red = static_cast( 255.f * value.r ); + const unsigned int green = static_cast( 255.f * value.g ); + const unsigned int blue = static_cast( 255.f * value.b ); + + std::stringstream ss; + const unsigned int size = 2u * sizeof( unsigned char ); + + ss << "0x" + << std::setfill('0') << std::setw( size ) + << std::hex << alpha + << std::setfill('0') << std::setw( size ) + << std::hex << red + << std::setfill('0') << std::setw( size ) + << std::hex << green + << std::setfill('0') << std::setw( size ) + << std::hex << blue; + vector2Str = ss.str(); +} + +void StringToVector2( const char* const vectorStr, Length length, Vector2& vector2 ) +{ + // Points to the first character of the string. + const char* strBuffer = vectorStr; + + // Points to the first character of the 'x' value. + const char* const xBuffer = strBuffer; + + // Jumps to the next white space. + JumpToWhiteSpace( strBuffer, strBuffer + length ); + + // Points to the first character of the 'y' value. + const char* const yBuffer = strBuffer; + + // Converts the shadow's offset to float. + vector2.x = StringToFloat( xBuffer ); + vector2.y = StringToFloat( yBuffer ); +} + +void Vector2ToString( const Vector2& value, std::string& vector2Str ) +{ + FloatToString( value.x, vector2Str ); + vector2Str += " "; + + std::string yStr; + FloatToString( value.y, yStr ); + + vector2Str += yStr; +} + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/markup-processor-helper-functions.h b/dali-toolkit/internal/text/markup-processor-helper-functions.h index 62be6c8..45f586c 100644 --- a/dali-toolkit/internal/text/markup-processor-helper-functions.h +++ b/dali-toolkit/internal/text/markup-processor-helper-functions.h @@ -28,6 +28,7 @@ namespace Dali { +struct Vector2; struct Vector4; namespace Toolkit @@ -78,11 +79,20 @@ bool TokenComparison( const std::string& string1, const char* const stringBuffer /** * @brief Skips any unnecessary white space. * - * @param[in,out] markupStringBuffer The mark-up string buffer. It's a const iterator pointing the current character. - * @param[in] markupStringEndBuffer Pointer to one character after the end of the mark-up string buffer. + * @param[in,out] stringBuffer The string buffer. It's a const iterator pointing the current character. + * @param[in] stringEndBuffer Pointer to one character after the end of the string buffer. */ -void SkipWhiteSpace( const char*& markupStringBuffer, - const char* const markupStringEndBuffer ); +void SkipWhiteSpace( const char*& stringBuffer, + const char* const stringEndBuffer ); + +/** + * @Brief Jumps to the next white space. + * + * @param[in,out] stringBuffer The string buffer. It's a const iterator pointing the current character. + * @param[in] stringEndBuffer Pointer to one character after the end of the string buffer. + */ +void JumpToWhiteSpace( const char*& stringBuffer, + const char* const stringEndBuffer ); /** * @brief Converts a string into an hexadecimal unsigned int. @@ -103,6 +113,14 @@ unsigned int StringToHex( const char* const uintStr ); float StringToFloat( const char* const floatStr ); /** + * @brief Converts a float into a string. + * + * @param[in] value The float value. + * @param[out] floatStr The string. + */ +void FloatToString( float value, std::string& floatStr ); + +/** * @brief Converts an ARGB color packed in 4 byte unsigned int into a Vector4 color used in Dali. * * @param[in] color An ARGB color packed in an unsigned int. @@ -114,7 +132,7 @@ void UintColorToVector4( unsigned int color, Vector4& retColor ); * @brief Converts a color packed inside a string into an ARGB Vector4 color. * * The string color could be in hexadecimal ( 0xFF0000FF ), webcolor ( #0000FF or #00F ) or some constant values: - * black, white, red, green, blue, yellow, magenta, cyan, transparent. + * black, white, red, green, blue, yellow, magenta, cyan or transparent. * * @param[in] colorStr A color packed inside a string. * @param[in] length The length of the color string. @@ -122,6 +140,35 @@ void UintColorToVector4( unsigned int color, Vector4& retColor ); */ void ColorStringToVector4( const char* const colorStr, Length length, Vector4& retColor ); +/** + * @brief Converts a color packed in a Vector4 into a string. + * + * Constant colors will be converted to the strings black, white, red, green, blue, yellow, magenta, cyan or transparent. + * + * If is not a constant color it will be converted to a string with hexadecimal ARGB content. + * + * @param[in] value The color value. + * @param[out] colorStr The string. + */ +void Vector4ToColorString( const Vector4& value, std::string& vector2Str ); + +/** + * @brief Converts a two dimension vector packed inside a string into a Vector2. + * + * @param[in] vectorStr The two dimension vector packed inside a string. + * @param[in] length The length of the string. + * @param[out] vector2 The Vector2. + */ +void StringToVector2( const char* const vectorStr, Length length, Vector2& vector2 ); + +/** + * @brief Converts a Vector2 into a string. + * + * @param[in] value The vector2 value. + * @param[out] vector2Str The string. + */ +void Vector2ToString( const Vector2& value, std::string& vector2Str ); + } // namespace Text } // namespace Toolkit diff --git a/dali-toolkit/internal/text/property-string-parser.cpp b/dali-toolkit/internal/text/property-string-parser.cpp index 42b1050..2aa05e9 100644 --- a/dali-toolkit/internal/text/property-string-parser.cpp +++ b/dali-toolkit/internal/text/property-string-parser.cpp @@ -79,27 +79,6 @@ void ParsePropertyString( const std::string& property, Property::Map& map ) } } -void StringOffsetToVector2( const std::string& offsetStr, - Vector2& offset ) -{ - offset = Vector2::ZERO; - - unsigned int wsIndex = 0u; - for( std::string::const_iterator it = offsetStr.begin(), - endIt = offsetStr.end(); - it != endIt; - ++it, ++wsIndex ) - { - if( *it == ' ' ) - { - break; - } - } - - offset[0] = StringToFloat( offsetStr.c_str() ); - offset[1] = StringToFloat( offsetStr.c_str() + wsIndex ); -} - } //namespace Text } //namespace Toolkit diff --git a/dali-toolkit/internal/text/property-string-parser.h b/dali-toolkit/internal/text/property-string-parser.h index b6ebf27..19d78b7 100644 --- a/dali-toolkit/internal/text/property-string-parser.h +++ b/dali-toolkit/internal/text/property-string-parser.h @@ -56,16 +56,6 @@ void CreatePropertyMap( const TreeNode* const node, Property::Map& map ); */ void ParsePropertyString( const std::string& property, Property::Map& map ); -/** - * @brief Converts an offset packed inside a string into a Vector2. - * - * @param[in] offsetStr The offset packed inside a string. - * @param[out] offset The offset packed in a Vector2. - * - */ -void StringOffsetToVector2( const std::string& offsetStr, - Vector2& offset ); - } //namespace Text } //namespace Toolkit diff --git a/dali-toolkit/internal/text/text-control-interface.h b/dali-toolkit/internal/text/text-control-interface.h index f5346e0..ce5af88 100644 --- a/dali-toolkit/internal/text/text-control-interface.h +++ b/dali-toolkit/internal/text/text-control-interface.h @@ -1,5 +1,5 @@ -#ifndef __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__ -#define __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__ +#ifndef DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H +#define DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -18,14 +18,9 @@ * */ -// INTERNAL INCLUDES -#include - namespace Dali { -class Actor; - namespace Toolkit { @@ -40,44 +35,15 @@ class ControlInterface public: /** - * @brief Constructor. - */ - ControlInterface(); - - /** * @brief Virtual destructor. */ - virtual ~ControlInterface(); - - /** - * @brief Add a decoration. - * - * @param[in] decoration The actor displaying a decoration. - * @param[in] needsClipping Whether the actor needs clipping. - */ - virtual void AddDecoration( Actor& actor, bool needsClipping ) = 0; + virtual ~ControlInterface() + {} /** * @brief Called to request a text relayout. */ virtual void RequestTextRelayout() = 0; - - /** - * @brief Called to signal that text has been inserted or deleted. - */ - virtual void TextChanged() = 0; - - /** - * @brief Called when the number of characters to be inserted exceeds the maximum limit - */ - virtual void MaxLengthReached() = 0; - - /** - * @brief Called to signal that input style has been changed. - * - * @param[in] inputStyleMask Mask with the bits of the input style that has changed. - */ - virtual void InputStyleChanged( InputStyle::Mask inputStyleMask ) = 0; }; } // namespace Text @@ -86,4 +52,4 @@ public: } // namespace Dali -#endif // __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__ +#endif // DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index 5769fac..7b3f2d6 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include namespace @@ -2749,7 +2750,10 @@ void Controller::Impl::ScrollTextToMatchCursor( const CursorInfo& cursorInfo ) void Controller::Impl::RequestRelayout() { - mControlInterface.RequestTextRelayout(); + if( NULL != mControlInterface ) + { + mControlInterface->RequestTextRelayout(); + } } } // namespace Text diff --git a/dali-toolkit/internal/text/text-controller-impl.h b/dali-toolkit/internal/text/text-controller-impl.h index 9b17fa7..608ea7d 100644 --- a/dali-toolkit/internal/text/text-controller-impl.h +++ b/dali-toolkit/internal/text/text-controller-impl.h @@ -1,5 +1,5 @@ -#ifndef __DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H__ -#define __DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H__ +#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H +#define DALI_TOOLKIT_TEXT_CONTROLLER_IMPL_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -285,8 +286,10 @@ struct OutlineDefaults struct Controller::Impl { - Impl( ControlInterface& controlInterface ) + Impl( ControlInterface* controlInterface, + EditableControlInterface* editableControlInterface ) : mControlInterface( controlInterface ), + mEditableControlInterface( editableControlInterface ), mLogicalModel(), mVisualModel(), mFontDefaults( NULL ), @@ -295,6 +298,7 @@ struct Controller::Impl mEmbossDefaults( NULL ), mOutlineDefaults( NULL ), mEventData( NULL ), + mAutoScrollData( NULL ), mFontClient(), mClipboard(), mView(), @@ -302,14 +306,14 @@ struct Controller::Impl mLayoutEngine(), mModifyEvents(), mTextColor( Color::BLACK ), + mScrollPosition(), mTextUpdateInfo(), mOperationsPending( NO_OPERATION ), mMaximumNumberOfCharacters( 50u ), mRecalculateNaturalSize( true ), mMarkupProcessorEnabled( false ), mClipboardHideEnabled( true ), - mAutoScrollEnabled( false ), - mAutoScrollDirectionRTL( false ) + mIsAutoScrollEnabled( false ) { mLogicalModel = LogicalModel::New(); mVisualModel = VisualModel::New(); @@ -336,10 +340,13 @@ struct Controller::Impl delete mEmbossDefaults; delete mOutlineDefaults; delete mEventData; + delete mAutoScrollData; } + // Text Controller Implementation. + /** - * @brief Request a relayout using the ControlInterface. + * @copydoc Text::Controller::RequestRelayout() */ void RequestRelayout(); @@ -686,7 +693,8 @@ private: public: - ControlInterface& mControlInterface; ///< Reference to the text controller. + ControlInterface* mControlInterface; ///< Reference to the text controller. + EditableControlInterface* mEditableControlInterface; ///< Reference to the editable text controller. LogicalModelPtr mLogicalModel; ///< Pointer to the logical model. VisualModelPtr mVisualModel; ///< Pointer to the visual model. FontDefaults* mFontDefaults; ///< Avoid allocating this when the user does not specify a font. @@ -695,6 +703,7 @@ public: EmbossDefaults* mEmbossDefaults; ///< Avoid allocating this when the user does not specify emboss parameters. OutlineDefaults* mOutlineDefaults; ///< Avoid allocating this when the user does not specify outline parameters. EventData* mEventData; ///< Avoid allocating everything for text input until EnableTextInput(). + ScrollerData* mAutoScrollData; ///< Avoid allocating this when the user does not specify the auto text scrolling feature. 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. @@ -713,10 +722,8 @@ public: bool mRecalculateNaturalSize:1; ///< Whether the natural size needs to be recalculated. bool mMarkupProcessorEnabled:1; ///< Whether the mark-up procesor is enabled. - bool mClipboardHideEnabled:1; ///< Whether the ClipboardHide function work or not - bool mAutoScrollEnabled:1; ///< Whether auto text scrolling is enabled. - CharacterDirection mAutoScrollDirectionRTL:1; ///< Direction of auto scrolling, true if rtl - + bool mClipboardHideEnabled:1; ///< Whether the ClipboardHide function work or not. + bool mIsAutoScrollEnabled:1; ///< Whether auto text scrolling is enabled. }; } // namespace Text @@ -725,4 +732,4 @@ public: } // namespace Dali -#endif // __DALI_TOOLKIT_TEXT_CONTROLLER_H__ +#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H diff --git a/dali-toolkit/internal/text/text-controller.cpp b/dali-toolkit/internal/text/text-controller.cpp index 6dfb99e..769d0e04 100644 --- a/dali-toolkit/internal/text/text-controller.cpp +++ b/dali-toolkit/internal/text/text-controller.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace { @@ -100,11 +101,28 @@ FontDescriptionRun& UpdateSelectionFontStyleRun( EventData* eventData, // public : Constructor. -ControllerPtr Controller::New( ControlInterface& controlInterface ) +ControllerPtr Controller::New() +{ + return ControllerPtr( new Controller() ); +} + +ControllerPtr Controller::New( ControlInterface* controlInterface ) { return ControllerPtr( new Controller( controlInterface ) ); } +ControllerPtr Controller::New( ControlInterface* controlInterface, + EditableControlInterface* editableControlInterface ) +{ + return ControllerPtr( new Controller( controlInterface, + editableControlInterface ) ); +} + +void Controller::SetTextControlInterface( ControlInterface* controlInterface ) +{ + mImpl->mControlInterface = controlInterface; +} + // public : Configure the text controller. void Controller::EnableTextInput( DecoratorPtr decorator ) @@ -140,9 +158,9 @@ void Controller::SetAutoScrollEnabled( bool enable ) { DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled[%s] SingleBox[%s]-> [%p]\n", (enable)?"true":"false", ( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX)?"true":"false", this ); - if ( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX ) + if( mImpl->mLayoutEngine.GetLayout() == LayoutEngine::SINGLE_LINE_BOX ) { - if ( enable ) + if( enable ) { DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::SetAutoScrollEnabled for SINGLE_LINE_BOX\n" ); mImpl->mOperationsPending = static_cast( mImpl->mOperationsPending | @@ -152,6 +170,10 @@ void Controller::SetAutoScrollEnabled( bool enable ) UPDATE_DIRECTION | REORDER ); + if( NULL == mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData = new ScrollerData(); + } } else { @@ -163,39 +185,104 @@ void Controller::SetAutoScrollEnabled( bool enable ) REORDER ); } - mImpl->mAutoScrollEnabled = enable; + mImpl->mIsAutoScrollEnabled = enable; mImpl->RequestRelayout(); } else { DALI_LOG_WARNING( "Attempted AutoScrolling on a non SINGLE_LINE_BOX, request ignored\n" ); - mImpl->mAutoScrollEnabled = false; + mImpl->mIsAutoScrollEnabled = false; } } bool Controller::IsAutoScrollEnabled() const { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", (mImpl->mAutoScrollEnabled)?"true":"false" ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::IsAutoScrollEnabled[%s]\n", mImpl->mIsAutoScrollEnabled?"true":"false" ); + + return mImpl->mIsAutoScrollEnabled; +} + +void Controller::SetAutoscrollSpeed( int scrollSpeed ) +{ + if( NULL == mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData = new ScrollerData(); + } + + mImpl->mAutoScrollData->mScrollSpeed = scrollSpeed; +} + +int Controller::GetAutoScrollSpeed() const +{ + if( NULL != mImpl->mAutoScrollData ) + { + return mImpl->mAutoScrollData->mScrollSpeed; + } + + return 0; +} + +void Controller::SetAutoScrollLoopCount( int loopCount ) +{ + if( NULL == mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData = new ScrollerData(); + } + + mImpl->mAutoScrollData->mLoopCount = loopCount; +} + +int Controller::GetAutoScrollLoopCount() const +{ + if( NULL != mImpl->mAutoScrollData ) + { + return mImpl->mAutoScrollData->mLoopCount; + } - return mImpl->mAutoScrollEnabled; + return 0; } -CharacterDirection Controller::GetAutoScrollDirection() const +void Controller::SetAutoScrollWrapGap( float wrapGap ) { - return mImpl->mAutoScrollDirectionRTL; + if( NULL == mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData = new ScrollerData(); + } + + mImpl->mAutoScrollData->mWrapGap = wrapGap; } -float Controller::GetAutoScrollLineAlignment() const +float Controller::GetAutoScrollWrapGap() const { - float offset = 0.f; + if( NULL != mImpl->mAutoScrollData ) + { + return mImpl->mAutoScrollData->mWrapGap; + } + + return 0.f; +} - if( mImpl->mVisualModel && - ( 0u != mImpl->mVisualModel->mLines.Count() ) ) +const ScrollerData* const Controller::GetAutoScrollData() +{ + if( NULL != mImpl->mAutoScrollData ) { - offset = ( *mImpl->mVisualModel->mLines.Begin() ).alignmentOffset; + // Need to update the data with the latest layout. + if( mImpl->mVisualModel ) + { + mImpl->mAutoScrollData->mControlSize = mImpl->mVisualModel->mControlSize; + mImpl->mAutoScrollData->mOffscreenSize = GetNaturalSize().GetVectorXY(); + + mImpl->mAutoScrollData->mAlignmentOffset = 0.f; + if( 0u != mImpl->mVisualModel->mLines.Count() ) + { + mImpl->mAutoScrollData->mAlignmentOffset = ( *mImpl->mVisualModel->mLines.Begin() ).alignmentOffset; + } + } + + return mImpl->mAutoScrollData; } - return offset; + return NULL; } void Controller::SetHorizontalScrollEnabled( bool enable ) @@ -460,8 +547,11 @@ void Controller::SetText( const std::string& text ) mImpl->mEventData->mEventQueue.clear(); } - // Do this last since it provides callbacks into application code - mImpl->mControlInterface.TextChanged(); + // Do this last since it provides callbacks into application code. + if( NULL != mImpl->mEditableControlInterface ) + { + mImpl->mEditableControlInterface->TextChanged(); + } } void Controller::GetText( std::string& text ) const @@ -742,26 +832,6 @@ const Vector4& Controller::GetShadowColor() const return mImpl->mVisualModel->GetShadowColor(); } -void Controller::SetDefaultShadowProperties( const std::string& shadowProperties ) -{ - if( NULL == mImpl->mShadowDefaults ) - { - mImpl->mShadowDefaults = new ShadowDefaults(); - } - - mImpl->mShadowDefaults->properties = shadowProperties; -} - -const std::string& Controller::GetDefaultShadowProperties() const -{ - if( NULL != mImpl->mShadowDefaults ) - { - return mImpl->mShadowDefaults->properties; - } - - return EMPTY_STRING; -} - void Controller::SetUnderlineColor( const Vector4& color ) { mImpl->mVisualModel->SetUnderlineColor( color ); @@ -798,26 +868,6 @@ float Controller::GetUnderlineHeight() const return mImpl->mVisualModel->GetUnderlineHeight(); } -void Controller::SetDefaultUnderlineProperties( const std::string& underlineProperties ) -{ - if( NULL == mImpl->mUnderlineDefaults ) - { - mImpl->mUnderlineDefaults = new UnderlineDefaults(); - } - - mImpl->mUnderlineDefaults->properties = underlineProperties; -} - -const std::string& Controller::GetDefaultUnderlineProperties() const -{ - if( NULL != mImpl->mUnderlineDefaults ) - { - return mImpl->mUnderlineDefaults->properties; - } - - return EMPTY_STRING; -} - void Controller::SetDefaultEmbossProperties( const std::string& embossProperties ) { if( NULL == mImpl->mEmbossDefaults ) @@ -1262,7 +1312,7 @@ const std::string& Controller::GetInputShadowProperties() const return mImpl->mEventData->mInputStyle.shadowProperties; } - return GetDefaultShadowProperties(); + return EMPTY_STRING; } void Controller::SetInputUnderlineProperties( const std::string& underlineProperties ) @@ -1280,7 +1330,7 @@ const std::string& Controller::GetInputUnderlineProperties() const return mImpl->mEventData->mInputStyle.underlineProperties; } - return GetDefaultUnderlineProperties(); + return EMPTY_STRING; } void Controller::SetInputEmbossProperties( const std::string& embossProperties ) @@ -1477,7 +1527,7 @@ float Controller::GetHeightForWidth( float width ) Controller::UpdateTextType Controller::Relayout( const Size& size ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, (mImpl->mAutoScrollEnabled)?"true":"false" ); + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "-->Controller::Relayout %p size %f,%f, autoScroll[%s]\n", this, size.width, size.height, mImpl->mIsAutoScrollEnabled ?"true":"false" ); UpdateTextType updateTextType = NONE_UPDATED; @@ -1583,6 +1633,11 @@ Controller::UpdateTextType Controller::Relayout( const Size& size ) return updateTextType; } +void Controller::RequestRelayout() +{ + mImpl->RequestRelayout(); +} + // public : Input style change signals. bool Controller::IsInputStyleChangedSignalsQueueEmpty() @@ -1605,8 +1660,11 @@ void Controller::ProcessInputStyleChangedSignals() { const InputStyle::Mask mask = *it; - // Emit the input style changed signal. - mImpl->mControlInterface.InputStyleChanged( mask ); + if( NULL != mImpl->mEditableControlInterface ) + { + // Emit the input style changed signal. + mImpl->mEditableControlInterface->InputStyleChanged( mask ); + } } mImpl->mEventData->mInputStyleChangedQueue.Clear(); @@ -1731,10 +1789,11 @@ bool Controller::KeyEvent( const Dali::KeyEvent& keyEvent ) mImpl->RequestRelayout(); } - if( textChanged ) + if( textChanged && + ( NULL != mImpl->mEditableControlInterface ) ) { // Do this last since it provides callbacks into application code - mImpl->mControlInterface.TextChanged(); + mImpl->mEditableControlInterface->TextChanged(); } return true; @@ -1965,10 +2024,11 @@ ImfManager::ImfCallbackData Controller::OnImfEvent( ImfManager& imfManager, cons ImfManager::ImfCallbackData callbackData( ( retrieveText || retrieveCursor ), cursorPosition, text, false ); - if( requestRelayout ) + if( requestRelayout && + ( NULL != mImpl->mEditableControlInterface ) ) { // Do this last since it provides callbacks into application code - mImpl->mControlInterface.TextChanged(); + mImpl->mEditableControlInterface->TextChanged(); } return callbackData; @@ -2001,7 +2061,10 @@ void Controller::GetTargetSize( Vector2& targetSize ) void Controller::AddDecoration( Actor& actor, bool needsClipping ) { - mImpl->mControlInterface.AddDecoration( actor, needsClipping ); + if( NULL != mImpl->mEditableControlInterface ) + { + mImpl->mEditableControlInterface->AddDecoration( actor, needsClipping ); + } } void Controller::DecorationEvent( HandleType handleType, HandleState state, float x, float y ) @@ -2088,7 +2151,11 @@ void Controller::TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Butt mImpl->mEventData->mScrollAfterDelete = true; mImpl->RequestRelayout(); - mImpl->mControlInterface.TextChanged(); + + if( NULL != mImpl->mEditableControlInterface ) + { + mImpl->mEditableControlInterface->TextChanged(); + } break; } case Toolkit::TextSelectionPopup::COPY: @@ -2135,6 +2202,17 @@ void Controller::TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Butt } } +// private : Inherit from TextScroller. + +void Controller::ScrollingFinished() +{ + // Pure Virtual from TextScroller Interface + SetAutoScrollEnabled( false ); + GetLayoutEngine().SetTextEllipsisEnabled( true ); + + mImpl->RequestRelayout(); +} + // private : Update. void Controller::InsertText( const std::string& text, Controller::InsertType type ) @@ -2375,8 +2453,11 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ mImpl->ResetImfManager(); - // Do this last since it provides callbacks into application code - mImpl->mControlInterface.MaxLengthReached(); + if( NULL != mImpl->mEditableControlInterface ) + { + // Do this last since it provides callbacks into application code + mImpl->mEditableControlInterface->MaxLengthReached(); + } } } @@ -2386,8 +2467,11 @@ void Controller::PasteText( const std::string& stringToPaste ) mImpl->ChangeState( EventData::EDITING ); mImpl->RequestRelayout(); - // Do this last since it provides callbacks into application code - mImpl->mControlInterface.TextChanged(); + if( NULL != mImpl->mEditableControlInterface ) + { + // Do this last since it provides callbacks into application code + mImpl->mEditableControlInterface->TextChanged(); + } } bool Controller::RemoveText( int cursorOffset, @@ -2594,7 +2678,10 @@ bool Controller::DoRelayout( const Size& size, if ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) ) { - mImpl->mAutoScrollDirectionRTL = false; + if( NULL != mImpl->mAutoScrollData ) + { + mImpl->mAutoScrollData->mAutoScrollDirectionRTL = false; + } } // Reorder the lines @@ -2630,9 +2717,11 @@ bool Controller::DoRelayout( const Size& size, if ( ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) ) && ( numberOfLines > 0 ) ) { const LineRun* const firstline = mImpl->mVisualModel->mLines.Begin(); - if ( firstline ) + if( firstline && + mImpl->mIsAutoScrollEnabled && + ( NULL != mImpl->mAutoScrollData ) ) { - mImpl->mAutoScrollDirectionRTL = firstline->direction; + mImpl->mAutoScrollData->mAutoScrollDirectionRTL = firstline->direction; } } } @@ -2664,7 +2753,7 @@ bool Controller::DoRelayout( const Size& size, #if defined(DEBUG_ENABLED) std::string currentText; GetText( currentText ); - DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mAutoScrollDirectionRTL[%s] [%s]\n", this, (mImpl->mAutoScrollDirectionRTL)?"true":"false", currentText.c_str() ); + DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::DoRelayout [%p] mImpl->mAutoScrollDirectionRTL[%s] [%s]\n", this, ( ( NULL != mImpl->mAutoScrollData ) && mImpl->mAutoScrollData->mAutoScrollDirectionRTL)?"true":"false", currentText.c_str() ); #endif DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::DoRelayout, view updated %s\n", ( viewUpdated ? "true" : "false" ) ); return viewUpdated; @@ -3011,10 +3100,22 @@ void Controller::ResetScrollPosition() // private : Private contructors & copy operator. -Controller::Controller( ControlInterface& controlInterface ) +Controller::Controller() : mImpl( NULL ) { - mImpl = new Controller::Impl( controlInterface ); + mImpl = new Controller::Impl( NULL, NULL ); +} + +Controller::Controller( ControlInterface* controlInterface ) +{ + mImpl = new Controller::Impl( controlInterface, NULL ); +} + +Controller::Controller( ControlInterface* controlInterface, + EditableControlInterface* editableControlInterface ) +{ + mImpl = new Controller::Impl( controlInterface, + editableControlInterface ); } // The copy constructor and operator are left unimplemented. diff --git a/dali-toolkit/internal/text/text-controller.h b/dali-toolkit/internal/text/text-controller.h index 07e1665..ce5c51a 100644 --- a/dali-toolkit/internal/text/text-controller.h +++ b/dali-toolkit/internal/text/text-controller.h @@ -1,5 +1,5 @@ -#ifndef __DALI_TOOLKIT_TEXT_CONTROLLER_H__ -#define __DALI_TOOLKIT_TEXT_CONTROLLER_H__ +#ifndef DALI_TOOLKIT_TEXT_CONTROLLER_H +#define DALI_TOOLKIT_TEXT_CONTROLLER_H /* * Copyright (c) 2016 Samsung Electronics Co., Ltd. @@ -26,7 +26,7 @@ #include #include #include -#include +#include namespace Dali { @@ -38,10 +38,12 @@ namespace Text { class Controller; +class ControlInterface; +class EditableControlInterface; class View; +struct ScrollerData; typedef IntrusivePtr ControllerPtr; -typedef Dali::Toolkit::Text::ControlInterface ControlInterface; /** * @brief A Text Controller is used by UI Controls which display text. @@ -54,7 +56,7 @@ typedef Dali::Toolkit::Text::ControlInterface ControlInterface; * * The text selection popup button callbacks are as well handled via the TextSelectionPopupCallbackInterface interface. */ -class Controller : public RefObject, public Decorator::ControllerInterface, public TextSelectionPopupCallbackInterface +class Controller : public RefObject, public Decorator::ControllerInterface, public TextSelectionPopupCallbackInterface, public Text::ScrollerInterface { public: // Enumerated types. @@ -123,10 +125,36 @@ public: // Constructor. /** * @brief Create a new instance of a Controller. * - * @param[in] controlInterface An interface used to request a text relayout. * @return A pointer to a new Controller. */ - static ControllerPtr New( ControlInterface& controlInterface ); + static ControllerPtr New(); + + /** + * @brief Create a new instance of a Controller. + * + * @param[in] controlInterface The control's interface. + * + * @return A pointer to a new Controller. + */ + static ControllerPtr New( ControlInterface* controlInterface ); + + /** + * @brief Create a new instance of a Controller. + * + * @param[in] controlInterface The control's interface. + * @param[in] editableControlInterface The editable control's interface. + * + * @return A pointer to a new Controller. + */ + static ControllerPtr New( ControlInterface* controlInterface, + EditableControlInterface* editableControlInterface ); + + /** + * @brief Sets the text-control interface. + * + * @param[in] controlInterface The text-control interface. + */ + void SetTextControlInterface( ControlInterface* controlInterface ); public: // Configure the text controller. @@ -182,17 +210,53 @@ public: // Configure the text controller. bool IsAutoScrollEnabled() const; /** - * @brief Get direction of the text from the first line of text, - * @return bool rtl (right to left) is true + * @brief Sets the speed the text should automatically scroll at. + * + * @param[in] scrollSpeed The speed of scrolling in pixels per second. + */ + void SetAutoscrollSpeed( int scrollSpeed ); + + /** + * @brief Retrieves the auto scroll speed. + * + * @return The auto scroll speed in pixels per second. + */ + int GetAutoScrollSpeed() const; + + /** + * @brief Sets the number of loops the text should scroll. + * + * @param[in] loopCount The number of loops. + */ + void SetAutoScrollLoopCount( int loopCount ); + + /** + * @brief Retrieves the number of loops the text should scroll. + * + * @return The numebr of loops. + */ + int GetAutoScrollLoopCount() const; + + /** + * @brief Sets the gap before text wraps around when scrolling. + * + * @param[in] wrapGap The gap in pixels. + */ + void SetAutoScrollWrapGap( float wrapGap ); + + /** + * @brief Retrieves the gap before text wraps around when scrolling. + * + * @return The gap in pixels. */ - CharacterDirection GetAutoScrollDirection() const; + float GetAutoScrollWrapGap() const; /** - * @brief Get the alignment offset of the first line of text. + * @brief Retrieves the text's autoscroll data. * - * @return The alignment offset. + * @return The text's autoscroll data. */ - float GetAutoScrollLineAlignment() const; + const ScrollerData* const GetAutoScrollData(); /** * @brief Enables the horizontal scrolling. @@ -480,22 +544,6 @@ public: // Default style & Input style const Vector4& GetShadowColor() const; /** - * @brief Sets the shadow's properties string. - * - * @note The string is stored to be recovered. - * - * @param[in] shadowProperties The shadow's properties string. - */ - void SetDefaultShadowProperties( const std::string& shadowProperties ); - - /** - * @brief Retrieves the shadow's properties string. - * - * @return The shadow's properties string. - */ - const std::string& GetDefaultShadowProperties() const; - - /** * @brief Set the underline color. * * @param[in] color color of underline. @@ -538,22 +586,6 @@ public: // Default style & Input style float GetUnderlineHeight() const; /** - * @brief Sets the underline's properties string. - * - * @note The string is stored to be recovered. - * - * @param[in] underlineProperties The underline's properties string. - */ - void SetDefaultUnderlineProperties( const std::string& underlineProperties ); - - /** - * @brief Retrieves the underline's properties string. - * - * @return The underline's properties string. - */ - const std::string& GetDefaultUnderlineProperties() const; - - /** * @brief Sets the emboss's properties string. * * @note The string is stored to be recovered. @@ -821,6 +853,11 @@ public: // Relayout. */ UpdateTextType Relayout( const Size& size ); + /** + * @brief Request a relayout using the ControlInterface. + */ + void RequestRelayout(); + public: // Input style change signals. /** @@ -919,6 +956,13 @@ protected: // Inherit from TextSelectionPopup::TextPopupButtonCallbackInterface. */ virtual void TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Buttons button ); +private: // Inherit from TextScroller + + /** + * @copydoc Text::ScrollerInterface::ScrollingFinished() + */ + virtual void ScrollingFinished(); + private: // Update. /** @@ -1058,7 +1102,18 @@ private: // Private contructors & copy operator. /** * @brief Private constructor. */ - Controller( ControlInterface& controlInterface ); + Controller(); + + /** + * @brief Private constructor. + */ + Controller( ControlInterface* controlInterface ); + + /** + * @brief Private constructor. + */ + Controller( ControlInterface* controlInterface, + EditableControlInterface* editableControlInterface ); // Undefined Controller( const Controller& handle ); @@ -1085,4 +1140,4 @@ private: } // namespace Dali -#endif // __DALI_TOOLKIT_TEXT_CONTROLLER_H__ +#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H diff --git a/dali-toolkit/internal/text/text-editable-control-interface.h b/dali-toolkit/internal/text/text-editable-control-interface.h new file mode 100644 index 0000000..e54704c --- /dev/null +++ b/dali-toolkit/internal/text/text-editable-control-interface.h @@ -0,0 +1,80 @@ +#ifndef DALI_TOOLKIT_TEXT_EDITABLE_CONTROL_INTERFACE_H +#define DALI_TOOLKIT_TEXT_EDITABLE_CONTROL_INTERFACE_H + +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +class Actor; + +namespace Toolkit +{ + +namespace Text +{ + +/** + * @brief An interface that the Text::Controller uses to notify about text changes and add decoration to the text control. + */ +class EditableControlInterface +{ +public: + + /** + * @brief Virtual destructor. + */ + virtual ~EditableControlInterface() + {} + + /** + * @brief Called to signal that text has been inserted or deleted. + */ + virtual void TextChanged() = 0; + + /** + * @brief Called when the number of characters to be inserted exceeds the maximum limit + */ + virtual void MaxLengthReached() = 0; + + /** + * @brief Called to signal that input style has been changed. + * + * @param[in] inputStyleMask Mask with the bits of the input style that has changed. + */ + virtual void InputStyleChanged( InputStyle::Mask inputStyleMask ) = 0; + + /** + * @brief Add a decoration. + * + * @param[in] decoration The actor displaying a decoration. + * @param[in] needsClipping Whether the actor needs clipping. + */ + virtual void AddDecoration( Actor& actor, bool needsClipping ) = 0; +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_EDITABLE_CONTROL_INTERFACE_H diff --git a/dali-toolkit/internal/text/text-effects-style.cpp b/dali-toolkit/internal/text/text-effects-style.cpp index 31580a2..083cf47 100644 --- a/dali-toolkit/internal/text/text-effects-style.cpp +++ b/dali-toolkit/internal/text/text-effects-style.cpp @@ -35,72 +35,137 @@ namespace { const std::string COLOR_KEY( "color" ); const std::string OFFSET_KEY( "offset" ); -const std::string THICKNESS_KEY( "thickness" ); +const std::string HEIGHT_KEY( "height" ); +const std::string ENABLE_KEY( "enable" ); +const std::string TRUE_TOKEN( "true" ); } -bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type ) +bool ParseProperties( const std::string& shadowProperties, + bool& colorDefined, + Vector4& color, + bool& offsetDefined, + Vector2& offset ) { - bool update = false; + // Parses and applies the style. + Property::Map map; + Text::ParsePropertyString( shadowProperties, map ); - if( controller ) + const bool empty = map.Empty(); + + if( !empty ) { - const std::string properties = value.Get< std::string >(); + /// Color key. + Property::Value* colorValue = map.Find( COLOR_KEY ); - switch( type ) + colorDefined = colorValue != NULL; + if( colorDefined ) { - case EffectStyle::DEFAULT: - { - // Stores the default underline's properties string to be recovered by the GetUnderlineProperties() function. - controller->SetDefaultUnderlineProperties( properties ); - break; - } - case EffectStyle::INPUT: - { - // Stores the input underline's properties string to be recovered by the GetUnderlineProperties() function. - controller->SetInputUnderlineProperties( properties ); - break; - } + const std::string colorStr = colorValue->Get(); + + Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); } - // Parses and applies the style. - Property::Map map; - ParsePropertyString( properties, map ); + /// Offset key. + Property::Value* offsetValue = map.Find( OFFSET_KEY ); - if( !map.Empty() ) + offsetDefined = offsetValue != NULL; + if( offsetDefined ) { - /// Color key - Property::Value* colorValue = map.Find( COLOR_KEY ); + const std::string offsetStr = offsetValue->Get(); - Vector4 color; - const bool colorDefined = colorValue != NULL; - if( colorDefined ) - { - const std::string colorStr = colorValue->Get(); + StringToVector2( offsetStr.c_str(), offsetStr.size(), offset ); + } + } - ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); - } + return empty; +} + +bool ParseProperties( const std::string& underlineProperties, + bool& enabled, + bool& colorDefined, + Vector4& color, + bool& heightDefined, + float& height ) +{ + // Parses and applies the style. + Property::Map map; + Text::ParsePropertyString( underlineProperties, map ); - /// Thickness key - Property::Value* thicknessValue = map.Find( THICKNESS_KEY ); + const bool empty = map.Empty(); - float thickness = 0.f; - const bool thicknessDefined = thicknessValue != NULL; - if( thicknessDefined ) - { - const std::string thicknessStr = thicknessValue->Get(); + if( !empty ) + { + /// Enable key. + Property::Value* enableValue = map.Find( ENABLE_KEY ); - thickness = StringToFloat( thicknessStr.c_str() ); - } + enabled = false; + const bool enabledDefined = enableValue != NULL; + if( enabledDefined ) + { + const std::string enableStr = enableValue->Get(); + enabled = Text::TokenComparison( TRUE_TOKEN, enableStr.c_str(), enableStr.size() ); + } + + /// Color key. + Property::Value* colorValue = map.Find( COLOR_KEY ); + colorDefined = colorValue != NULL; + if( colorDefined ) + { + const std::string colorStr = colorValue->Get(); + + Text::ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); + } + + /// Height key. + Property::Value* heightValue = map.Find( HEIGHT_KEY ); + + height = 0.f; + heightDefined = heightValue != NULL; + if( heightDefined ) + { + const std::string heightStr = heightValue->Get(); + + height = StringToFloat( heightStr.c_str() ); + } + } + + return empty; +} + +bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& value, EffectStyle::Type type ) +{ + bool update = false; + + if( controller ) + { + const std::string properties = value.Get(); + + bool enabled = false; + bool colorDefined = false; + Vector4 color; + bool heightDefined = false; + float height = 0.f; + + const bool empty = ParseProperties( properties, + enabled, + colorDefined, + color, + heightDefined, + height ); + + if( !empty ) + { switch( type ) { case EffectStyle::DEFAULT: { - if( !controller->IsUnderlineEnabled() ) + if( enabled != controller->IsUnderlineEnabled() ) { - controller->SetUnderlineEnabled( true ); + controller->SetUnderlineEnabled( enabled ); update = true; } + // Sets the default underline values. if( colorDefined && ( controller->GetUnderlineColor() != color ) ) { @@ -108,9 +173,9 @@ bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& va update = true; } - if( thicknessDefined && fabsf( controller->GetUnderlineHeight() - thickness ) > Math::MACHINE_EPSILON_1000 ) + if( heightDefined && ( fabsf( controller->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) ) { - controller->SetUnderlineHeight( thickness ); + controller->SetUnderlineHeight( height ); update = true; } break; @@ -125,11 +190,25 @@ bool SetUnderlineProperties( ControllerPtr controller, const Property::Value& va } else { - // Disable underline. - if( controller->IsUnderlineEnabled() ) + switch( type ) { - controller->SetUnderlineEnabled( false ); - update = true; + case EffectStyle::DEFAULT: + { + // Disable underline. + if( controller->IsUnderlineEnabled() ) + { + controller->SetUnderlineEnabled( false ); + update = true; + } + break; + } + case EffectStyle::INPUT: + { + // Sets the input underline values. + // TODO: to be implemented. + controller->SetInputUnderlineProperties( properties ); + break; + } } } } @@ -145,7 +224,23 @@ void GetUnderlineProperties( ControllerPtr controller, Property::Value& value, E { case EffectStyle::DEFAULT: { - value = controller->GetDefaultUnderlineProperties(); + const bool enabled = controller->IsUnderlineEnabled(); + const Vector4& color = controller->GetUnderlineColor(); + const float height = controller->GetUnderlineHeight(); + + std::string underlineProperties = "{\"enable\":"; + const std::string enabledStr = enabled ? "true" : "false"; + underlineProperties += "\"" + enabledStr + "\","; + + std::string colorStr; + Vector4ToColorString( color, colorStr ); + underlineProperties += "\"color\":\"" + colorStr + "\","; + + std::string heightStr; + FloatToString( height, heightStr ); + underlineProperties += "\"height\":\"" + heightStr + "\"}"; + + value = underlineProperties; break; } case EffectStyle::INPUT: @@ -165,52 +260,19 @@ bool SetShadowProperties( ControllerPtr controller, const Property::Value& value { const std::string properties = value.Get< std::string >(); - switch( type ) - { - case EffectStyle::DEFAULT: - { - // Stores the default shadow's properties string to be recovered by the GetShadowProperties() function. - controller->SetDefaultShadowProperties( properties ); - break; - } - case EffectStyle::INPUT: - { - // Stores the input shadow's properties string to be recovered by the GetShadowProperties() function. - controller->SetInputShadowProperties( properties ); - break; - } - } + bool colorDefined = false; + Vector4 color; + bool offsetDefined = false; + Vector2 offset; - // Parses and applies the style. - Property::Map map; - ParsePropertyString( properties, map ); + const bool empty = ParseProperties( properties, + colorDefined, + color, + offsetDefined, + offset ); - if( !map.Empty() ) + if( !empty ) { - /// Color key - Property::Value* colorValue = map.Find( COLOR_KEY ); - - Vector4 color; - const bool colorDefined = colorValue != NULL; - if( colorDefined ) - { - const std::string colorStr = colorValue->Get(); - - ColorStringToVector4( colorStr.c_str(), colorStr.size(), color ); - } - - /// Offset key - Property::Value* offsetValue = map.Find( OFFSET_KEY ); - - Vector2 offset; - const bool offsetDefined = offsetValue != NULL; - if( offsetDefined ) - { - const std::string offsetStr = offsetValue->Get(); - - StringOffsetToVector2( offsetStr, offset ); - } - switch( type ) { case EffectStyle::DEFAULT: @@ -237,6 +299,28 @@ bool SetShadowProperties( ControllerPtr controller, const Property::Value& value } } } + else + { + switch( type ) + { + case EffectStyle::DEFAULT: + { + // Disable shadow. + if( Vector2::ZERO != controller->GetShadowOffset() ) + { + controller->SetShadowOffset( Vector2::ZERO ); + } + break; + } + case EffectStyle::INPUT: + { + // Sets the input shadow values. + // TODO: to be implemented. + controller->SetInputShadowProperties( properties ); + break; + } + } + } } return update; @@ -250,7 +334,20 @@ void GetShadowProperties( ControllerPtr controller, Property::Value& value, Effe { case EffectStyle::DEFAULT: { - value = controller->GetDefaultShadowProperties(); + const Vector4& color = controller->GetShadowColor(); + const Vector2& offset = controller->GetShadowOffset(); + + std::string shadowProperties = "{"; + + std::string colorStr; + Vector4ToColorString( color, colorStr ); + shadowProperties += "\"color\":\"" + colorStr + "\","; + + std::string offsetStr; + Vector2ToString( offset, offsetStr ); + shadowProperties += "\"offset\":\"" + offsetStr + "\"}"; + + value = shadowProperties; break; } case EffectStyle::INPUT: diff --git a/dali-toolkit/internal/text/text-effects-style.h b/dali-toolkit/internal/text/text-effects-style.h index 9feb75c..fb21fe9 100644 --- a/dali-toolkit/internal/text/text-effects-style.h +++ b/dali-toolkit/internal/text/text-effects-style.h @@ -18,12 +18,8 @@ * */ -// EXTERNAL INCLUDES -#include - // INTERNAL INCLUDES #include -#include namespace Dali { @@ -44,6 +40,36 @@ namespace EffectStyle }; /** + * @brief Parses the shadow properties. + * + * @param[out] colorDefined Whether the shadow's color is defined. + * @param[out] color The shadow's color. + * @param[out] offsetDefined Whether the shadow's offset is defined. + * @param[out] offset The shadow's offset. + */ +bool ParseProperties( const std::string& shadowProperties, + bool& colorDefined, + Vector4& color, + bool& offsetDefined, + Vector2& offset ); + +/** + * @brief Parses the underline properties. + * + * @param[out] enabled Whether the underline is enabled. + * @param[out] colorDefined Whether the underline's color is defined. + * @param[out] color The underline's color. + * @param[out] heightDefined Whether the underline's height is defined. + * @param[out] height The underline's height. + */ +bool ParseProperties( const std::string& underlineProperties, + bool& enabled, + bool& colorDefined, + Vector4& color, + bool& heightDefined, + float& height ); + +/** * @brief Sets the underline properties. * * @param[in] controller The text's controller. diff --git a/dali-toolkit/internal/text/text-font-style.cpp b/dali-toolkit/internal/text/text-font-style.cpp index 6fff87e..b3b9e84 100644 --- a/dali-toolkit/internal/text/text-font-style.cpp +++ b/dali-toolkit/internal/text/text-font-style.cpp @@ -23,6 +23,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -39,6 +40,10 @@ const std::string STYLE_KEY( "style" ); const std::string WEIGHT_KEY( "weight" ); const std::string WIDTH_KEY( "width" ); const std::string SLANT_KEY( "slant" ); +const std::string FAMILY_KEY( "family" ); +const std::string TYPE_KEY( "type" ); + +const std::string SYSTEM_TOKEN( "system" ); #if defined(DEBUG_ENABLED) Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_CONTROLS"); @@ -46,6 +51,59 @@ Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_C } // namespace +void SetFontFamilyProperty( ControllerPtr controller, const Property::Value& value ) +{ + if( controller ) + { + const std::string fontFamilyValue = value.Get(); + + if( fontFamilyValue.empty() ) + { + // Resets the default's font family name. + controller->SetDefaultFontFamily( "" ); + return; + } + + Property::Map map; + ParsePropertyString( fontFamilyValue, map ); + + if( map.Empty() ) + { + // There is no map. The font has been passed as a font's family name with no format. + controller->SetDefaultFontFamily( fontFamilyValue ); + } + else + { + /// Family key + Property::Value* familyValue = map.Find( FAMILY_KEY ); + + std::string fontFamilyName; + if( NULL != familyValue ) + { + fontFamilyName = familyValue->Get(); + } + + /// Type key + Property::Value* typeValue = map.Find( TYPE_KEY ); + + std::string typeStr; + if( NULL != typeValue ) + { + typeStr = typeValue->Get(); + } + + if( TokenComparison( SYSTEM_TOKEN, typeStr.c_str(), typeStr.size() ) ) + { + controller->UpdateAfterFontChange( fontFamilyName ); + } + else + { + controller->SetDefaultFontFamily( fontFamilyName ); + } + } + } +} + void SetFontStyleProperty( ControllerPtr controller, const Property::Value& value, FontStyle::Type type ) { if( controller ) diff --git a/dali-toolkit/internal/text/text-font-style.h b/dali-toolkit/internal/text/text-font-style.h index 425131d..e74bcfb 100644 --- a/dali-toolkit/internal/text/text-font-style.h +++ b/dali-toolkit/internal/text/text-font-style.h @@ -23,7 +23,6 @@ // INTERNAL INCLUDES #include -#include namespace Dali { @@ -90,6 +89,14 @@ namespace FontStyle }; /** + * @brief Sets the font family property. + * + * @param[in] controller The text's controller. + * @param[in] value The value of the font's family. + */ +void SetFontFamilyProperty( ControllerPtr controller, const Property::Value& value ); + +/** * @brief Sets the font's style property. * * @param[in] controller The text's controller. diff --git a/dali-toolkit/internal/text/text-control-interface.cpp b/dali-toolkit/internal/text/text-scroller-data.cpp similarity index 65% rename from dali-toolkit/internal/text/text-control-interface.cpp rename to dali-toolkit/internal/text/text-scroller-data.cpp index 8ac77d1..d938911 100644 --- a/dali-toolkit/internal/text/text-control-interface.cpp +++ b/dali-toolkit/internal/text/text-scroller-data.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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. @@ -15,8 +15,8 @@ * */ -// CLASS HEADER -#include +// FILE HEADER +#include namespace Dali { @@ -27,13 +27,18 @@ namespace Toolkit namespace Text { -ControlInterface::ControlInterface() -{ -} +const int MINIMUM_SCROLL_SPEED = 1; -ControlInterface::~ControlInterface() -{ -} +ScrollerData::ScrollerData() +: mScrollSpeed( MINIMUM_SCROLL_SPEED ), + mLoopCount( 1 ), + mWrapGap( 0.f ), + mAlignmentOffset( 0.f ), + mAutoScrollDirectionRTL( false ) +{} + +ScrollerData::~ScrollerData() +{} } // namespace Text diff --git a/dali-toolkit/internal/text/text-scroller-data.h b/dali-toolkit/internal/text/text-scroller-data.h new file mode 100644 index 0000000..3ba08c9 --- /dev/null +++ b/dali-toolkit/internal/text/text-scroller-data.h @@ -0,0 +1,62 @@ +#ifndef DALI_TOOLKIT_TEXT_SCROLLER_DATA_H +#define DALI_TOOLKIT_TEXT_SCROLLER_DATA_H + +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Text +{ + +extern const int MINIMUM_SCROLL_SPEED; // Speed should be set by Property system. + +/** + * @brief Stores the autoscroll data. + */ +struct ScrollerData +{ + ScrollerData(); + ~ScrollerData(); + + Size mControlSize; ///< The size of the control to scroll within. + Size mOffscreenSize; ///< The size of the sourceActor. + int mScrollSpeed; ///< Speed which text should automatically scroll at. + int mLoopCount; ///< Number of time the text should scroll. + float mWrapGap; ///< Gap before text wraps around when scrolling. + float mAlignmentOffset; ///< The alignment offset of the first line of text to be scrolled. + CharacterDirection mAutoScrollDirectionRTL; ///< Direction of auto scrolling, true if rtl. +}; + +} // namespace Text + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_SCROLLER_H + diff --git a/dali-toolkit/internal/text/text-scroller.cpp b/dali-toolkit/internal/text/text-scroller.cpp index d2f9348..ee1d241 100644 --- a/dali-toolkit/internal/text/text-scroller.cpp +++ b/dali-toolkit/internal/text/text-scroller.cpp @@ -31,6 +31,7 @@ // INTERNAL INCLUDES #include +#include namespace Dali { @@ -38,6 +39,11 @@ namespace Dali namespace Toolkit { +namespace Text +{ +extern const int MINIMUM_SCROLL_SPEED; +} // namespace + namespace { @@ -45,8 +51,6 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_SCROLLING"); #endif -const int MINIMUM_SCROLL_SPEED = 1; // Speed should be set by Property system. - const char* VERTEX_SHADER_SCROLL = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n varying highp vec2 vTexCoord;\n @@ -195,50 +199,6 @@ TextScrollerPtr TextScroller::New( ScrollerInterface& scrollerInterface ) return textScroller; } -void TextScroller::SetGap( int gap ) -{ - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetGap gap[%d]\n", gap ); - mWrapGap = static_cast(gap); -} - -int TextScroller::GetGap() const -{ - return static_cast(mWrapGap); -} - -void TextScroller::SetSpeed( int scrollSpeed ) -{ - mScrollSpeed = std::max( MINIMUM_SCROLL_SPEED, scrollSpeed ); -} - -int TextScroller::GetSpeed() const -{ - return mScrollSpeed; -} - -void TextScroller::SetLoopCount( int loopCount ) -{ - if ( loopCount > 0 ) - { - mLoopCount = loopCount; - } - - if ( mScrollAnimation && mScrollAnimation.GetState() == Animation::PLAYING ) - { - if ( loopCount == 0 ) // Request to stop looping - { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount Single loop forced\n" ); - mScrollAnimation.SetLoopCount( 1 ); // As animation already playing this allows the current animation to finish instead of trying to stop mid-way - } - } - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount [%d] Status[%s]\n", mLoopCount, (loopCount)?"looping":"stop" ); -} - -int TextScroller::GetLoopCount() const -{ - return mLoopCount; -} - Actor TextScroller::GetSourceCamera() const { return mOffscreenCameraActor; @@ -249,11 +209,9 @@ Actor TextScroller::GetScrollingText() const return mScrollingTextActor; } -TextScroller::TextScroller( ScrollerInterface& scrollerInterface ) : mScrollerInterface( scrollerInterface ), - mScrollDeltaIndex( Property::INVALID_INDEX ), - mScrollSpeed( MINIMUM_SCROLL_SPEED ), - mLoopCount( 1 ), - mWrapGap( 0.0f ) +TextScroller::TextScroller( ScrollerInterface& scrollerInterface ) +: mScrollerInterface( scrollerInterface ), + mScrollDeltaIndex( Property::INVALID_INDEX ) { DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller Default Constructor\n" ); } @@ -263,49 +221,71 @@ TextScroller::~TextScroller() CleanUp(); } -void TextScroller::SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, float alignmentOffset ) +void TextScroller::StartScrolling( Actor sourceActor, + const ScrollerData& data ) { - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters controlSize[%f,%f] offscreenSize[%f,%f] direction[%d] alignmentOffset[%f]\n", - controlSize.x, controlSize.y, offScreenSize.x, offScreenSize.y, direction, alignmentOffset ); - - FrameBufferImage offscreenRenderTargetForText = FrameBufferImage::New( offScreenSize.width, offScreenSize.height, Pixel::RGBA8888 ); + DALI_LOG_INFO( gLogFilter, + Debug::Verbose, + "TextScroller::StartScrolling controlSize[%f,%f] offscreenSize[%f,%f] direction[%d] alignmentOffset[%f]\n", + data.mControlSize.x, data.mControlSize.y, + data.mOffscreenSize.x, data.mOffscreenSize.y, + data.mAutoScrollDirectionRTL, + data.mAlignmentOffset ); + + FrameBufferImage offscreenRenderTargetForText = FrameBufferImage::New( data.mOffscreenSize.width, data.mOffscreenSize.height, Pixel::RGBA8888 ); Renderer renderer; - CreateCameraActor( offScreenSize, mOffscreenCameraActor ); + CreateCameraActor( data.mOffscreenSize, mOffscreenCameraActor ); CreateRenderer( offscreenRenderTargetForText, renderer ); CreateRenderTask( sourceActor, mOffscreenCameraActor, offscreenRenderTargetForText, mRenderTask ); // Reposition camera to match alignment of target, RTL text has direction=true - if ( direction ) + if( data.mAutoScrollDirectionRTL ) { - mOffscreenCameraActor.SetX( alignmentOffset + offScreenSize.width*0.5f ); + mOffscreenCameraActor.SetX( data.mAlignmentOffset + data.mOffscreenSize.width * 0.5f ); } else { - mOffscreenCameraActor.SetX( offScreenSize.width * 0.5f ); + mOffscreenCameraActor.SetX( data.mOffscreenSize.width * 0.5f ); } - mOffscreenCameraActor.SetY( offScreenSize.height * 0.5f ); + mOffscreenCameraActor.SetY( data.mOffscreenSize.height * 0.5f ); - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters mWrapGap[%f]\n", mWrapGap ) + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetParameters mWrapGap[%f]\n", data.mWrapGap ) mScrollingTextActor = Actor::New(); mScrollingTextActor.AddRenderer( renderer ); - mScrollingTextActor.RegisterProperty( "uTextureSize", offScreenSize ); - mScrollingTextActor.RegisterProperty( "uRtl", ((direction)?1.0f:0.0f) ); - mScrollingTextActor.RegisterProperty( "uGap", mWrapGap ); - mScrollingTextActor.SetSize( controlSize.width, std::min( offScreenSize.height, controlSize.height ) ); + mScrollingTextActor.RegisterProperty( "uTextureSize", data.mOffscreenSize ); + mScrollingTextActor.RegisterProperty( "uRtl", ( data.mAutoScrollDirectionRTL ? 1.f : 0.f ) ); + mScrollingTextActor.RegisterProperty( "uGap", data.mWrapGap ); + mScrollingTextActor.SetSize( data.mControlSize.width, std::min( data.mOffscreenSize.height, data.mControlSize.height ) ); mScrollDeltaIndex = mScrollingTextActor.RegisterProperty( "uDelta", 0.0f ); - float scrollAmount = std::max( offScreenSize.width + mWrapGap, controlSize.width ); - float scrollDuration = scrollAmount / mScrollSpeed; + float scrollAmount = std::max( data.mOffscreenSize.width + data.mWrapGap, data.mControlSize.width ); + float scrollSpeed = std::max( MINIMUM_SCROLL_SPEED, data.mScrollSpeed ); + float scrollDuration = scrollAmount / scrollSpeed; - if ( direction ) + if( data.mAutoScrollDirectionRTL ) { scrollAmount = -scrollAmount; // reverse direction of scrollung } - StartScrolling( scrollAmount, scrollDuration, mLoopCount ); + mScrollAnimation = Animation::New( scrollDuration ); + mScrollAnimation.AnimateTo( Property( mScrollingTextActor, mScrollDeltaIndex ), scrollAmount ); + mScrollAnimation.SetEndAction( Animation::Discard ); + mScrollAnimation.SetLoopCount( data.mLoopCount ); + mScrollAnimation.FinishedSignal().Connect( this, &TextScroller::AutoScrollAnimationFinished ); + mScrollAnimation.Play(); +} + +void TextScroller::StopScrolling() +{ + if( mScrollAnimation && + ( mScrollAnimation.GetState() == Animation::PLAYING ) ) + { + DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetLoopCount Single loop forced\n" ); + mScrollAnimation.SetLoopCount( 1 ); // As animation already playing this allows the current animation to finish instead of trying to stop mid-way + } } void TextScroller::AutoScrollAnimationFinished( Dali::Animation& animation ) @@ -315,18 +295,6 @@ void TextScroller::AutoScrollAnimationFinished( Dali::Animation& animation ) mScrollerInterface.ScrollingFinished(); } -void TextScroller::StartScrolling( float scrollAmount, float scrollDuration, int loopCount ) -{ - DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::StartScrolling scrollAmount[%f] scrollDuration[%f], loop[%d] speed[%d]\n", scrollAmount, scrollDuration, loopCount, mScrollSpeed ); - - mScrollAnimation = Animation::New( scrollDuration ); - mScrollAnimation.AnimateTo( Property( mScrollingTextActor, mScrollDeltaIndex ), scrollAmount ); - mScrollAnimation.SetEndAction( Animation::Discard ); - mScrollAnimation.SetLoopCount( loopCount ); - mScrollAnimation.FinishedSignal().Connect( this, &TextScroller::AutoScrollAnimationFinished ); - mScrollAnimation.Play(); -} - void TextScroller::CleanUp() { if ( Stage::IsInstalled() ) diff --git a/dali-toolkit/internal/text/text-scroller.h b/dali-toolkit/internal/text/text-scroller.h index 17824b6..a40be3f 100644 --- a/dali-toolkit/internal/text/text-scroller.h +++ b/dali-toolkit/internal/text/text-scroller.h @@ -37,6 +37,7 @@ namespace Text class TextScroller; class ScrollerInterface; +struct ScrollerData; typedef IntrusivePtr TextScrollerPtr; @@ -46,7 +47,6 @@ typedef IntrusivePtr TextScrollerPtr; class TextScroller : public RefObject, public ConnectionTracker { public: - /** * @brief Text Scrolling helper, used to automatically scroll text, SetParameters should be called before scrolling is needed. * CleanUp removes the Scrolling actors from stage whilst keeping the Scroller object alive and preserving Speed, Gap and Loop count. @@ -56,52 +56,19 @@ public: static TextScrollerPtr New( ScrollerInterface& scrollerInterface ); /** - * @brief Set parameters relating to source required for scrolling + * @brief Starts the text scrolling. * * @param[in] sourceActor source actor to be scrolled - * @param[in] controlSize size of the control to scroll within - * @param[in] offScreenSize size of the sourceActor - * @param[in] direction text direction true for right to left text - * @param[in] alignmentOffset alignment of source text + * @param[in] data Parameters needed to set up the text scrolling. * */ - void SetParameters( Actor sourceActor, const Size& controlSize, const Size& offScreenSize, CharacterDirection direction, float alignmentOffset ); - - /** - * @brief Set the gap distance to elapse before the text wraps around - * @param[in] gap distance to elapse - */ - void SetGap( int gap ); - - /** - * @brief Get the distance before scrolling wraps - * @return gap distance to elapse - */ - int GetGap() const; - - /** - * @brief Set speed the text should scroll - * @param[in] scrollSpeed pixels per second - */ - void SetSpeed( int scrollSpeed ); + void StartScrolling( Actor sourceActor, + const ScrollerData& data ); /** - * @brief Get the speed of text scrolling - * @return speed in pixels per second + * @brief Stops the text scrolling. */ - int GetSpeed() const; - - /** - * @brief Set the number of times the text scrolling should loop, can stop current scrolling by passing in 0; - * @param[in] loopCount number of times the scrolled text should loop, 0 to stop scrolling - */ - void SetLoopCount( int loopCount ); - - /** - * @brief Get the number of loops - * @return int number of loops - */ - int GetLoopCount() const; + void StopScrolling(); /** * @brief Get the camera used to look at source, should be added to the parent of target actor. @@ -140,14 +107,6 @@ private: // Implementation void AutoScrollAnimationFinished( Dali::Animation& animation ); /** - * @brief variables required to set up scrolling animation - * @param[in] scrollAmount distance to animate text for the given duration - * @param[in] scrollDuration duration of aninmation - * @param[in] loopCount number of times to loop the scrolling text - */ - void StartScrolling( float scrollAmount, float scrollDuration, int loopCount ); - - /** * @brief When scrolling ended, the actors are cleaned up so no longer staged. */ void CleanUp(); @@ -161,10 +120,6 @@ private: Property::Index mScrollDeltaIndex; // Property used by shader to represent distance to scroll Animation mScrollAnimation; // Animation used to update the mScrollDeltaIndex - int mScrollSpeed; ///< Speed which text should automatically scroll at - int mLoopCount; ///< Number of time the text should scroll - float mWrapGap; ///< Gap before text wraps around when scrolling - }; // TextScroller class } // namespace Text diff --git a/dali-toolkit/internal/visuals/border/border-visual.cpp b/dali-toolkit/internal/visuals/border/border-visual.cpp index 0c27103..ba326d0 100644 --- a/dali-toolkit/internal/visuals/border/border-visual.cpp +++ b/dali-toolkit/internal/visuals/border/border-visual.cpp @@ -102,6 +102,11 @@ const char* FRAGMENT_SHADER_ANTI_ALIASING = DALI_COMPOSE_SHADER( ); } +BorderVisualPtr BorderVisual::New( VisualFactoryCache& factoryCache ) +{ + return new BorderVisual( factoryCache ); +} + BorderVisual::BorderVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), mBorderColor( Color::TRANSPARENT ), diff --git a/dali-toolkit/internal/visuals/border/border-visual.h b/dali-toolkit/internal/visuals/border/border-visual.h index c1e30d8..3fce5d6 100644 --- a/dali-toolkit/internal/visuals/border/border-visual.h +++ b/dali-toolkit/internal/visuals/border/border-visual.h @@ -20,6 +20,7 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include @@ -33,6 +34,9 @@ namespace Toolkit namespace Internal { +class BorderVisual; +typedef IntrusivePtr< BorderVisual > BorderVisualPtr; + /** * The visual which renders a solid color to the control's quad border fixed to a specified size. * @@ -44,12 +48,21 @@ namespace Internal * | borderSize | FLOAT | * | antiAliasing | BOOLEAN | */ - class BorderVisual : public Visual::Base { public: /** + * @brief Create a new border visual. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. + */ + static BorderVisualPtr New( VisualFactoryCache& factoryCache ); + +protected: + + /** * @brief Constructor. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object @@ -61,8 +74,6 @@ public: */ virtual ~BorderVisual(); -protected: - /** * @copydoc Visual::Base::DoInitialize */ diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index a1ef6d2..8736d54 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -65,6 +65,11 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( ); } +ColorVisualPtr ColorVisual::New( VisualFactoryCache& factoryCache ) +{ + return new ColorVisual( factoryCache ); +} + ColorVisual::ColorVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), mMixColorIndex( Property::INVALID_INDEX ) diff --git a/dali-toolkit/internal/visuals/color/color-visual.h b/dali-toolkit/internal/visuals/color/color-visual.h index 88fb152..6552ac6 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.h +++ b/dali-toolkit/internal/visuals/color/color-visual.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_INTERNAL_COLOR_VISUAL_H /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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. @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include @@ -30,6 +33,9 @@ namespace Toolkit namespace Internal { +class ColorVisual; +typedef IntrusivePtr< ColorVisual > ColorVisualPtr; + /** * The visual which renders a solid color to the control's quad * @@ -44,16 +50,12 @@ class ColorVisual: public Visual::Base public: /** - * @brief Constructor. + * @brief Create a new color visual. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. */ - ColorVisual( VisualFactoryCache& factoryCache ); - - /** - * @brief A reference counted object may only be deleted by calling Unreference(). - */ - virtual ~ColorVisual(); + static ColorVisualPtr New( VisualFactoryCache& factoryCache ); public: // from Visual @@ -80,6 +82,18 @@ public: // from Visual protected: /** + * @brief Constructor. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + */ + ColorVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~ColorVisual(); + + /** * @copydoc Visual::Base::DoInitialize */ virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp index f30ff03..b662821 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp @@ -185,6 +185,10 @@ Dali::WrapMode::Type GetWrapMode( Toolkit::GradientVisual::SpreadMethod::Type sp } // unnamed namespace +GradientVisualPtr GradientVisual::New( VisualFactoryCache& factoryCache ) +{ + return new GradientVisual( factoryCache ); +} GradientVisual::GradientVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.h b/dali-toolkit/internal/visuals/gradient/gradient-visual.h index 1726c51..5171b12 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.h +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_INTERNAL_GRADIENT_VISUAL_H /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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. @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -33,6 +36,8 @@ namespace Internal { class Gradient; +class GradientVisual; +typedef IntrusivePtr< GradientVisual > GradientVisualPtr; /** * The visual which renders smooth transition of colors to the control's quad. @@ -80,16 +85,12 @@ public: }; /** - * @brief Constructor. + * @brief Create a new gradient visual. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. */ - GradientVisual( VisualFactoryCache& factoryCache ); - - /** - * @brief A reference counted object may only be deleted by calling Unreference(). - */ - ~GradientVisual(); + static GradientVisualPtr New( VisualFactoryCache& factoryCache ); public: // from Visual @@ -114,6 +115,19 @@ public: // from Visual virtual Dali::Property::Value DoGetProperty( Dali::Property::Index index ); protected: + + /** + * @brief Constructor. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + */ + GradientVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~GradientVisual(); + /** * @copydoc Visual::Base::DoInitialize */ diff --git a/dali-toolkit/internal/visuals/image/batch-image-visual.cpp b/dali-toolkit/internal/visuals/image/batch-image-visual.cpp index 46244aa..973355a 100644 --- a/dali-toolkit/internal/visuals/image/batch-image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/batch-image-visual.cpp @@ -85,11 +85,16 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( }\n ); -} //unnamed namespace +} // unnamed namespace + +BatchImageVisualPtr BatchImageVisual::New( VisualFactoryCache& factoryCache ) +{ + return new BatchImageVisual( factoryCache ); +} BatchImageVisual::BatchImageVisual( VisualFactoryCache& factoryCache ) - : Visual::Base( factoryCache ), - mDesiredSize() +: Visual::Base( factoryCache ), + mDesiredSize() { } diff --git a/dali-toolkit/internal/visuals/image/batch-image-visual.h b/dali-toolkit/internal/visuals/image/batch-image-visual.h index e5536e9..7151100 100644 --- a/dali-toolkit/internal/visuals/image/batch-image-visual.h +++ b/dali-toolkit/internal/visuals/image/batch-image-visual.h @@ -18,13 +18,13 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL HEADER #include #include -// EXTERNAL INCLUDES -#include - namespace Dali { namespace Toolkit @@ -32,21 +32,20 @@ namespace Toolkit namespace Internal { +class BatchImageVisual; +typedef IntrusivePtr< BatchImageVisual > BatchImageVisualPtr; + class BatchImageVisual: public Visual::Base, public ConnectionTracker { public: /** - * @brief Constructor. + * @brief Create a new batch-image visual. * - * @param[in] factoryCache The VisualFactoryCache object - */ - BatchImageVisual( VisualFactoryCache& factoryCache ); - - /** - * @brief A reference counted object may only be deleted by calling Unreference(). + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. */ - ~BatchImageVisual(); + static BatchImageVisualPtr New( VisualFactoryCache& factoryCache ); public: // from Visual @@ -78,6 +77,18 @@ public: // from Visual protected: /** + * @brief Constructor. + * + * @param[in] factoryCache The VisualFactoryCache object + */ + BatchImageVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + ~BatchImageVisual(); + + /** * @copydoc Visua::Base::DoInitialize */ virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index f4652dd..0cfdfc8 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -16,7 +16,7 @@ */ // CLASS HEADER -#include "image-visual.h" +#include // EXTERNAL HEADER #include // for strncasecmp @@ -186,19 +186,92 @@ Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridS return geometry; } -} //unnamed namespace +} // unnamed namespace + +ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache ) +{ + return new ImageVisual( factoryCache ); +} + +ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, + const std::string& imageUrl, + ImageDimensions size, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode ) +{ + return new ImageVisual( factoryCache, imageUrl, size, fittingMode, samplingMode ); +} + +ImageVisualPtr ImageVisual::New( VisualFactoryCache& factoryCache, const Image& image ) +{ + return new ImageVisual( factoryCache, image ); +} ImageVisual::ImageVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), + mImage(), + mPixels(), + mTextureSet(), + mPixelArea( FULL_TEXTURE_RECT ), + mPlacementActor(), + mImageUrl(), + mNativeFragmentShaderCode(), + mDesiredSize(), + mFittingMode( FittingMode::DEFAULT ), + mSamplingMode( SamplingMode::DEFAULT ), + mWrapModeU( WrapMode::DEFAULT ), + mWrapModeV( WrapMode::DEFAULT ), + mNativeImageFlag( false ) +{ +} + +ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, + const std::string& imageUrl, + ImageDimensions size, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode ) +: Visual::Base( factoryCache ), + mImage(), + mPixels(), + mTextureSet(), + mPixelArea( FULL_TEXTURE_RECT ), + mPlacementActor(), + mImageUrl( imageUrl ), + mNativeFragmentShaderCode(), + mDesiredSize( size ), + mFittingMode( fittingMode ), + mSamplingMode( samplingMode ), + mWrapModeU( WrapMode::DEFAULT ), + mWrapModeV( WrapMode::DEFAULT ), + mNativeImageFlag( false ) +{ +} + +ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, const Image& image ) +: Visual::Base( factoryCache ), + mImage( image ), + mPixels(), mPixelArea( FULL_TEXTURE_RECT ), + mPlacementActor(), + mImageUrl(), + mNativeFragmentShaderCode(), mDesiredSize(), mFittingMode( FittingMode::DEFAULT ), mSamplingMode( SamplingMode::DEFAULT ), mWrapModeU( WrapMode::DEFAULT ), mWrapModeV( WrapMode::DEFAULT ), - mNativeFragmentShaderCode( ), mNativeImageFlag( false ) { + NativeImage newNativeImage = NativeImage::DownCast( image ); + if( newNativeImage ) + { + SetNativeFragmentShaderCode( newNativeImage ); + mNativeImageFlag = true; + } + else + { + mNativeImageFlag = false; + } } ImageVisual::~ImageVisual() @@ -221,13 +294,17 @@ void ImageVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap ) Property::Value* fittingValue = propertyMap.Find( Toolkit::ImageVisual::Property::FITTING_MODE, IMAGE_FITTING_MODE ); if( fittingValue ) { - Scripting::GetEnumerationProperty( *fittingValue, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, mFittingMode ); + int value; + Scripting::GetEnumerationProperty( *fittingValue, FITTING_MODE_TABLE, FITTING_MODE_TABLE_COUNT, value ); + mFittingMode = Dali::FittingMode::Type( value ); } Property::Value* samplingValue = propertyMap.Find( Toolkit::ImageVisual::Property::SAMPLING_MODE, IMAGE_SAMPLING_MODE ); if( samplingValue ) { - Scripting::GetEnumerationProperty( *samplingValue, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, mSamplingMode ); + int value; + Scripting::GetEnumerationProperty( *samplingValue, SAMPLING_MODE_TABLE, SAMPLING_MODE_TABLE_COUNT, value ); + mSamplingMode = Dali::SamplingMode::Type( value ); } int desiredWidth = 0; @@ -253,13 +330,17 @@ void ImageVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap ) Property::Value* wrapModeValueU = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_U, IMAGE_WRAP_MODE_U ); if( wrapModeValueU ) { - Scripting::GetEnumerationProperty( *wrapModeValueU, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, mWrapModeU ); + int value; + Scripting::GetEnumerationProperty( *wrapModeValueU, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, value ); + mWrapModeU = Dali::WrapMode::Type( value ); } Property::Value* wrapModeValueV = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_V, IMAGE_WRAP_MODE_V ); if( wrapModeValueV ) { - Scripting::GetEnumerationProperty( *wrapModeValueV, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, mWrapModeV ); + int value; + Scripting::GetEnumerationProperty( *wrapModeValueV, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, value ); + mWrapModeV = Dali::WrapMode::Type( value ); } mDesiredSize = ImageDimensions( desiredWidth, desiredHeight ); @@ -282,22 +363,9 @@ void ImageVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap ) // if sync loading is required, the loading should start immediately when new image url is set or the actor is off stage // ( for on-stage actor with image url unchanged, resource loading is already finished) - if( ( !mImpl->mRenderer || imageURLValue) && IsSynchronousResourceLoading() ) + if( imageURLValue && IsSynchronousResourceLoading() ) { - DoSynchronousResourceLoading(); - } - - // remove old renderer if exit - if( mImpl->mRenderer ) - { - if( actor ) //remove old renderer from actor - { - actor.RemoveRenderer( mImpl->mRenderer ); - } - if( !oldImageUrl.empty() ) //clean old renderer from cache - { - CleanCache( oldImageUrl ); - } + LoadResourceSynchronously(); } NativeImage nativeImage = NativeImage::DownCast( mImage ); @@ -339,7 +407,7 @@ void ImageVisual::GetNaturalSize( Vector2& naturalSize ) const naturalSize = Vector2::ZERO; } -Renderer ImageVisual::CreateRenderer() const +void ImageVisual::CreateRenderer() { Geometry geometry; Shader shader; @@ -348,7 +416,8 @@ Renderer ImageVisual::CreateRenderer() const // Renderer can't be shared between NativeImage and other image types. if( !mNativeFragmentShaderCode.empty() ) { - return CreateNativeImageRenderer(); + CreateNativeImageRenderer(); + return; } if( !mImpl->mCustomShader ) @@ -378,12 +447,13 @@ Renderer ImageVisual::CreateRenderer() const } } - Renderer renderer = Renderer::New( geometry, shader ); - - return renderer; + mImpl->mRenderer = Renderer::New( geometry, shader ); + // apply the texture set as well so it's only done in one place + DALI_ASSERT_DEBUG( mTextureSet ); + mImpl->mRenderer.SetTextures( mTextureSet ); } -Renderer ImageVisual::CreateNativeImageRenderer() const +void ImageVisual::CreateNativeImageRenderer() { Geometry geometry; Shader shader; @@ -407,10 +477,10 @@ Renderer ImageVisual::CreateNativeImageRenderer() const } } - TextureSet textureSet = TextureSet::New(); - Renderer renderer = Renderer::New( geometry, shader ); - renderer.SetTextures( textureSet ); - return renderer; + mImpl->mRenderer = Renderer::New( geometry, shader ); + // apply the texture set as well so it's only done in one place + DALI_ASSERT_DEBUG( mTextureSet ); + mImpl->mRenderer.SetTextures( mTextureSet ); } @@ -419,7 +489,7 @@ bool ImageVisual::IsSynchronousResourceLoading() const return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING; } -void ImageVisual::DoSynchronousResourceLoading() +void ImageVisual::LoadResourceSynchronously() { if( !mImageUrl.empty() ) { @@ -429,64 +499,49 @@ void ImageVisual::DoSynchronousResourceLoading() } } -Image ImageVisual::LoadImage( const std::string& url, bool synchronousLoading ) +void ImageVisual::CreateTextureSet( Vector4& textureRect, const std::string& url, bool synchronousLoading, bool attemptAtlasing ) { - if( synchronousLoading ) - { - if( !mPixels ) - { - // use broken image - return VisualFactoryCache::GetBrokenVisualImage(); - } - Atlas image = Atlas::New( mPixels.GetWidth(), mPixels.GetHeight(), mPixels.GetPixelFormat() ); - image.Upload( mPixels, 0, 0 ); - return image; - } - else - { - ResourceImage resourceImage = Dali::ResourceImage::New( url, mDesiredSize, mFittingMode, mSamplingMode ); - resourceImage.LoadingFinishedSignal().Connect( this, &ImageVisual::OnImageLoaded ); - return resourceImage; - } -} - -TextureSet ImageVisual::CreateTextureSet( Vector4& textureRect, const std::string& url, bool synchronousLoading ) -{ - TextureSet textureSet; textureRect = FULL_TEXTURE_RECT; if( synchronousLoading ) { if( !mPixels ) { // use broken image - textureSet = TextureSet::New(); - TextureSetImage( textureSet, 0u, VisualFactoryCache::GetBrokenVisualImage() ); + mTextureSet = TextureSet::New(); + TextureSetImage( mTextureSet, 0u, VisualFactoryCache::GetBrokenVisualImage() ); } else { - textureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, mPixels ); - mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; - if( !textureSet ) // big image, no atlasing + if( attemptAtlasing ) + { + mTextureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, mPixels ); + mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; + } + if( !mTextureSet ) // big image, no atlasing or atlasing failed { mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; - Atlas image = Atlas::New( mPixels.GetWidth(), mPixels.GetHeight(), mPixels.GetPixelFormat() ); - image.Upload( mPixels, 0, 0 ); - textureSet = TextureSet::New(); - TextureSetImage( textureSet, 0u, image ); + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, mPixels.GetPixelFormat(), + mPixels.GetWidth(), mPixels.GetHeight() ); + texture.Upload( mPixels ); + mTextureSet = TextureSet::New(); + mTextureSet.SetTexture( 0u, texture ); } } } else { - textureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, url, mDesiredSize, mFittingMode, true, this ); - mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; - if( !textureSet ) // big image, no atlasing + if( attemptAtlasing ) + { + mTextureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, url, mDesiredSize, mFittingMode, true, this ); + mImpl->mFlags |= Impl::IS_ATLASING_APPLIED; + } + if( !mTextureSet ) // big image, no atlasing or atlasing failed { mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; ResourceImage resourceImage = Dali::ResourceImage::New( url, mDesiredSize, mFittingMode, mSamplingMode ); resourceImage.LoadingFinishedSignal().Connect( this, &ImageVisual::OnImageLoaded ); - textureSet = TextureSet::New(); - TextureSetImage( textureSet, 0u, resourceImage ); + mTextureSet = TextureSet::New(); + TextureSetImage( mTextureSet, 0u, resourceImage ); } } @@ -494,10 +549,8 @@ TextureSet ImageVisual::CreateTextureSet( Vector4& textureRect, const std::strin { Sampler sampler = Sampler::New(); sampler.SetWrapMode( mWrapModeU, mWrapModeV ); - textureSet.SetSampler( 0u, sampler ); + mTextureSet.SetSampler( 0u, sampler ); } - - return textureSet; } void ImageVisual::InitializeRenderer( const std::string& imageUrl ) @@ -528,11 +581,10 @@ void ImageVisual::InitializeRenderer( const std::string& imageUrl ) if( !mImpl->mRenderer ) // new renderer is needed { Vector4 atlasRect; - TextureSet textureSet = CreateTextureSet(atlasRect, imageUrl, IsSynchronousResourceLoading() ); - Geometry geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) ); - Shader shader( GetImageShader(mFactoryCache, mImpl->mFlags & Impl::IS_ATLASING_APPLIED, defaultWrapMode) ); - mImpl->mRenderer = Renderer::New( geometry, shader ); - mImpl->mRenderer.SetTextures( textureSet ); + // texture set has to be created first as we need to know if atlasing succeeded or not + // when selecting the shader + CreateTextureSet( atlasRect, imageUrl, IsSynchronousResourceLoading(), true ); + CreateRenderer(); if( mImpl->mFlags & Impl::IS_ATLASING_APPLIED ) // the texture is packed inside atlas { @@ -556,9 +608,9 @@ void ImageVisual::InitializeRenderer( const std::string& imageUrl ) { // for custom shader or remote image, renderer is not cached and atlas is not applied mImpl->mFlags &= ~Impl::IS_FROM_CACHE; - mImpl->mRenderer = CreateRenderer(); - Image image = LoadImage( imageUrl, IsSynchronousResourceLoading() ); - ApplyImageToSampler( image ); + Vector4 atlasRect; // ignored in this case + CreateTextureSet( atlasRect, imageUrl, IsSynchronousResourceLoading(), false ); + CreateRenderer(); } } @@ -566,7 +618,9 @@ void ImageVisual::InitializeRenderer( const Image& image ) { mImpl->mFlags &= ~Impl::IS_FROM_CACHE; - mImpl->mRenderer = CreateRenderer(); + // don't reuse CreateTextureSet + mTextureSet = TextureSet::New(); + CreateRenderer(); if( image ) { @@ -626,6 +680,7 @@ void ImageVisual::DoSetOffStage( Actor& actor ) mImpl->mRenderer.Reset(); } mPlacementActor.Reset(); + mTextureSet.Reset(); // release texture when going offstage } void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const @@ -709,145 +764,16 @@ Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlas return shader; } -void ImageVisual::SetImage( Actor& actor, const std::string& imageUrl, ImageDimensions size, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode ) -{ - if( mImageUrl != imageUrl ) - { - std::string oldImageUrl = mImageUrl; - mImageUrl = imageUrl; - mDesiredSize = size; - mFittingMode = fittingMode; - mSamplingMode = samplingMode; - mImage.Reset(); - - if( IsSynchronousResourceLoading() ) - { - DoSynchronousResourceLoading(); - } - - if( mImpl->mRenderer ) - { - if( GetIsFromCache() ) // if renderer is from cache, remove the old one - { - //remove old renderer - if( actor ) - { - actor.RemoveRenderer( mImpl->mRenderer ); - } - - //clean the cache - if( !oldImageUrl.empty() ) - { - CleanCache(oldImageUrl); - } - - if( actor && actor.OnStage() ) // if actor on stage, create a new renderer and apply to actor - { - SetOnStage(actor); - } - } - else // if renderer is not from cache, reuse the same renderer and only change the texture - { - Image image = LoadImage( imageUrl, IsSynchronousResourceLoading() ); - ApplyImageToSampler( image ); - } - } - } -} - -void ImageVisual::SetImage( Actor& actor, const Image& image ) -{ - if( mImage != image ) - { - NativeImage newNativeImage = NativeImage::DownCast( image ); - bool newRendererFlag = true; - - if( newNativeImage && !mNativeImageFlag ) - { - SetNativeFragmentShaderCode( newNativeImage ); - } - - if( ( newNativeImage && mNativeImageFlag ) || ( !newNativeImage && !mNativeImageFlag ) ) - { - newRendererFlag = false; - } - - if( newNativeImage ) - { - mNativeImageFlag = true; - } - else - { - mNativeFragmentShaderCode.clear(); - mNativeImageFlag = false; - } - - mImage = image; - - if( mImpl->mRenderer ) - { - // if renderer is from cache, remove the old one, and create new renderer - if( GetIsFromCache() ) - { - //remove old renderer - if( actor ) - { - actor.RemoveRenderer( mImpl->mRenderer ); - } - - //clean the cache - if( !mImageUrl.empty() ) - { - CleanCache(mImageUrl); - } - mImageUrl.clear(); - - if( actor && actor.OnStage() ) // if actor on stage, create a new renderer and apply to actor - { - SetOnStage(actor); - } - } - // if input image is nativeImage and mImage is regular image or the reverse, remove the old one, and create new renderer - else if( newRendererFlag ) - { - //remove old renderer - if( actor ) - { - actor.RemoveRenderer( mImpl->mRenderer ); - } - - if( actor && actor.OnStage() ) // if actor on stage, create a new renderer and apply to actor - { - SetOnStage(actor); - } - } - else // if renderer is not from cache, reuse the same renderer and only change the texture - { - ApplyImageToSampler( image ); - } - } - - mImageUrl.clear(); - mDesiredSize = ImageDimensions(); - mFittingMode = FittingMode::DEFAULT; - mSamplingMode = SamplingMode::DEFAULT; - } -} - void ImageVisual::ApplyImageToSampler( const Image& image ) { if( image ) { - TextureSet textureSet = mImpl->mRenderer.GetTextures(); - if( !textureSet ) - { - textureSet = TextureSet::New(); - mImpl->mRenderer.SetTextures( textureSet ); - } - TextureSetImage( textureSet, 0u, image ); + DALI_ASSERT_DEBUG( mTextureSet ); // texture set should always exist by this time + + TextureSetImage( mTextureSet, 0u, image ); Sampler sampler = Sampler::New(); sampler.SetWrapMode( mWrapModeU, mWrapModeV ); - textureSet.SetSampler( 0u, sampler ); + mTextureSet.SetSampler( 0u, sampler ); } } @@ -865,20 +791,21 @@ void ImageVisual::OnImageLoaded( ResourceImage image ) void ImageVisual::CleanCache(const std::string& url) { - TextureSet textureSet = mImpl->mRenderer.GetTextures(); - - Vector4 atlasRect( 0.f, 0.f, 1.f, 1.f ); - Property::Index index = mImpl->mRenderer.GetPropertyIndex( ATLAS_RECT_UNIFORM_NAME ); - if( index != Property::INVALID_INDEX ) + if( IsFromCache() ) { - Property::Value atlasRectValue = mImpl->mRenderer.GetProperty( index ); - atlasRectValue.Get( atlasRect ); - } + Vector4 atlasRect( 0.f, 0.f, 1.f, 1.f ); + Property::Index index = mImpl->mRenderer.GetPropertyIndex( ATLAS_RECT_UNIFORM_NAME ); + if( index != Property::INVALID_INDEX ) + { + Property::Value atlasRectValue = mImpl->mRenderer.GetProperty( index ); + atlasRectValue.Get( atlasRect ); + } - mImpl->mRenderer.Reset(); - if( mFactoryCache.CleanRendererCache( url ) && index != Property::INVALID_INDEX ) - { - mFactoryCache.GetAtlasManager()->Remove( textureSet, atlasRect ); + mImpl->mRenderer.Reset(); + if( mFactoryCache.CleanRendererCache( url ) && index != Property::INVALID_INDEX ) + { + mFactoryCache.GetAtlasManager()->Remove( mTextureSet, atlasRect ); + } } } diff --git a/dali-toolkit/internal/visuals/image/image-visual.h b/dali-toolkit/internal/visuals/image/image-visual.h index 3079c93..24d652b 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.h +++ b/dali-toolkit/internal/visuals/image/image-visual.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_INTERNAL_IMAGE_VISUAL_H /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 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. @@ -18,16 +18,17 @@ * */ -// INTERNAL INCLUDES -#include -#include - // EXTERNAL INCLUDES +#include #include #include #include #include +// INTERNAL INCLUDES +#include +#include + namespace Dali { @@ -79,16 +80,37 @@ class ImageVisual: public Visual::Base, public ConnectionTracker, public AtlasUp public: /** - * @brief Constructor. + * @brief Create a new image visual. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. + */ + static ImageVisualPtr New( VisualFactoryCache& factoryCache ); + + /** + * @brief Create a new image visual with a URL. + * + * The visual will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage * * @param[in] factoryCache The VisualFactoryCache object + * @param[in] imageUrl The URL of the image resource to use + * @param[in] size The width and height to fit the loaded image to. + * @param[in] fittingMode The FittingMode of the resource to load + * @param[in] samplingMode The SamplingMode of the resource to load */ - ImageVisual( VisualFactoryCache& factoryCache ); + static ImageVisualPtr New( VisualFactoryCache& factoryCache, + const std::string& imageUrl, + ImageDimensions size = ImageDimensions(), + FittingMode::Type fittingMode = FittingMode::DEFAULT, + Dali::SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR ); /** - * @brief A reference counted object may only be deleted by calling Unreference(). + * @brief Create a new image visual with an Image type. + * + * @param[in] factoryCache The VisualFactoryCache object + * @param[in] image The image to use */ - ~ImageVisual(); + static ImageVisualPtr New( VisualFactoryCache& factoryCache, const Image& image ); public: // from Visual @@ -113,6 +135,44 @@ public: // from Visual virtual Dali::Property::Value DoGetProperty( Dali::Property::Index index ); protected: + + /** + * @brief Constructor. + * + * @param[in] factoryCache The VisualFactoryCache object + */ + ImageVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief Constructor with a URL. + * + * The visual will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage + * + * @param[in] factoryCache The VisualFactoryCache object + * @param[in] imageUrl The URL of the image resource to use + * @param[in] size The width and height to fit the loaded image to. + * @param[in] fittingMode The FittingMode of the resource to load + * @param[in] samplingMode The SamplingMode of the resource to load + */ + ImageVisual( VisualFactoryCache& factoryCache, + const std::string& imageUrl, + ImageDimensions size, + FittingMode::Type fittingMode, + Dali::SamplingMode::Type samplingMode ); + + /** + * @brief Constructor with an Image type. + * + * @param[in] factoryCache The VisualFactoryCache object + * @param[in] image The image to use + */ + ImageVisual( VisualFactoryCache& factoryCache, const Image& image ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~ImageVisual(); + /** * @copydoc Visual::Base::DoInitialize */ @@ -139,30 +199,6 @@ public: static Shader GetImageShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping ); /** - * @brief Sets the image of this visual to the resource at imageUrl - * The visual will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage - * - * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor - * @param[in] imageUrl The URL of the image resource to use - * @param[in] size The width and height to fit the loaded image to. - * @param[in] fittingMode The FittingMode of the resource to load - * @param[in] samplingMode The SamplingMode of the resource to load - */ - void SetImage( Actor& actor, - const std::string& imageUrl, - ImageDimensions size=ImageDimensions(), - FittingMode::Type fittingMode = FittingMode::DEFAULT, - Dali::SamplingMode::Type samplingMode = SamplingMode::BOX_THEN_LINEAR ); - - /** - * @brief Sets the image to be rendered by this visual - * - * @param[in] actor The Actor the renderer is applied to if, empty if the renderer has not been applied to any Actor - * @param[in] image The image to use - */ - void SetImage( Actor& actor, const Image& image ); - - /** * @copydoc AtlasUploadObserver::UploadCompleted * * To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready. @@ -195,43 +231,33 @@ private: /** * @brief Creates the Dali::Renderer (potentially from the renderer cache), initializing it - * - * @return Returns the created Dali::Renderer */ - Renderer CreateRenderer() const; + void CreateRenderer(); /** * @brief Creates the Dali::Renderer for NativeImage with custom sampler type and prefix, initializing it - * - * @return Returns the created Dali::Renderer */ - Renderer CreateNativeImageRenderer() const; + void CreateNativeImageRenderer(); /** * @brief Query whether resources requires to be loaded synchronously. - * @return Returns true if synchronoud resource loading is required, false otherwise. + * @return Returns true if synchronous resource loading is required, false otherwise. */ bool IsSynchronousResourceLoading() const; /** - * @brief Do the synchronous resource loading - */ - void DoSynchronousResourceLoading(); - - /** - * Load the image. - * @param[in] url The URL of the image resource to use. - * @param[in] synchronousLoading If true, the resource is loaded synchronously, otherwise asynchronously. + * @brief Load the resource synchronously */ - Image LoadImage( const std::string& url, bool synchronousLoading ); + void LoadResourceSynchronously(); /** - * Load the image and create a texture set to hold the texture, with automatic atlasing applied. - * @param [out] textureRect The texture area of the resource image in the atlas. + * Creates the texture set and adds the texture to it + * @param[out] textureRect The texture area of the texture in the atlas. * @param[in] url The URL of the image resource to use. * @param[in] synchronousLoading If true, the resource is loaded synchronously, otherwise asynchronously. + * @param[in] attemptAtlasing If true will attempt atlasing, otherwise create unique texture */ - TextureSet CreateTextureSet( Vector4& textureRect, const std::string& url, bool synchronousLoading ); + void CreateTextureSet( Vector4& textureRect, const std::string& url, bool synchronousLoading, bool attemptAtlasing ); /** * Callback function of image resource loading succeed @@ -256,20 +282,21 @@ private: void SetNativeFragmentShaderCode( Dali::NativeImage& nativeImage ); private: + Image mImage; PixelData mPixels; + TextureSet mTextureSet; Vector4 mPixelArea; WeakHandle mPlacementActor; - std::string mImageUrl; - Dali::ImageDimensions mDesiredSize; - Dali::FittingMode::Type mFittingMode; - Dali::SamplingMode::Type mSamplingMode; - Dali::WrapMode::Type mWrapModeU; - Dali::WrapMode::Type mWrapModeV; - std::string mNativeFragmentShaderCode; - bool mNativeImageFlag; + + Dali::ImageDimensions mDesiredSize; + Dali::FittingMode::Type mFittingMode:3; + Dali::SamplingMode::Type mSamplingMode:4; + Dali::WrapMode::Type mWrapModeU:3; + Dali::WrapMode::Type mWrapModeV:3; + bool mNativeImageFlag:1; }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/mesh/mesh-visual.cpp b/dali-toolkit/internal/visuals/mesh/mesh-visual.cpp index 5f8d4e0..28ff3d1 100644 --- a/dali-toolkit/internal/visuals/mesh/mesh-visual.cpp +++ b/dali-toolkit/internal/visuals/mesh/mesh-visual.cpp @@ -288,7 +288,12 @@ const char* NORMAL_MAP_FRAGMENT_SHADER = DALI_COMPOSE_SHADER( }\n ); -} // namespace +} // unnamed namespace + +MeshVisualPtr MeshVisual::New( VisualFactoryCache& factoryCache ) +{ + return new MeshVisual( factoryCache ); +} MeshVisual::MeshVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), diff --git a/dali-toolkit/internal/visuals/mesh/mesh-visual.h b/dali-toolkit/internal/visuals/mesh/mesh-visual.h index a05f848..1762f46 100644 --- a/dali-toolkit/internal/visuals/mesh/mesh-visual.h +++ b/dali-toolkit/internal/visuals/mesh/mesh-visual.h @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include // INTERNAL INCLUDES #include @@ -36,6 +37,9 @@ namespace Toolkit namespace Internal { +class MeshVisual; +typedef IntrusivePtr< MeshVisual > MeshVisualPtr; + /** * The visual which renders a 3D object to the control's quad * @@ -56,16 +60,12 @@ class MeshVisual: public Visual::Base public: /** - * @brief Constructor. + * @brief Create a new mesh visual. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. */ - MeshVisual( VisualFactoryCache& factoryCache ); - - /** - * @brief A reference counted object may only be deleted by calling Unreference(). - */ - virtual ~MeshVisual(); + static MeshVisualPtr New( VisualFactoryCache& factoryCache ); public: // from Visual @@ -92,6 +92,18 @@ public: // from Visual protected: /** + * @brief Constructor. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + */ + MeshVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~MeshVisual(); + + /** * @copydoc Visual::Base::DoInitialize */ virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp index 77d522e..036f978 100644 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp @@ -200,9 +200,41 @@ void RegisterStretchProperties( Renderer& renderer, const char * uniformName, co /////////////////NPatchVisual//////////////// -NPatchVisual::NPatchVisual( VisualFactoryCache& factoryCache ) +NPatchVisualPtr NPatchVisual::New( VisualFactoryCache& factoryCache ) +{ + return new NPatchVisual( factoryCache ); +} + +NPatchVisualPtr NPatchVisual::New( VisualFactoryCache& factoryCache, const std::string& imageUrl, bool borderOnly ) +{ + NPatchVisual* nPatchVisual = new NPatchVisual( factoryCache, borderOnly ); + nPatchVisual->mImageUrl = imageUrl; + + NinePatchImage image = NinePatchImage::New( imageUrl ); + nPatchVisual->InitializeFromImage( image ); + + return nPatchVisual; +} + +NPatchVisualPtr NPatchVisual::New( VisualFactoryCache& factoryCache, NinePatchImage image, bool borderOnly ) +{ + NPatchVisual* nPatchVisual = new NPatchVisual( factoryCache, borderOnly ); + nPatchVisual->mImage = image; + + nPatchVisual->InitializeFromImage( image ); + + return nPatchVisual; +} + +NPatchVisual::NPatchVisual( VisualFactoryCache& factoryCache, bool borderOnly ) : Visual::Base( factoryCache ), - mBorderOnly( false ) + mImage(), + mCroppedImage(), + mImageUrl(), + mStretchPixelsX(), + mStretchPixelsY(), + mImageSize(), + mBorderOnly( borderOnly ) { } @@ -452,60 +484,6 @@ void NPatchVisual::ChangeRenderer( bool oldBorderOnly, size_t oldGridX, size_t o } } -void NPatchVisual::SetImage( const std::string& imageUrl, bool borderOnly ) -{ - bool oldBorderOnly = mBorderOnly; - size_t oldGridX = mStretchPixelsX.Size(); - size_t oldGridY = mStretchPixelsY.Size(); - - mBorderOnly = borderOnly; - mImage.Reset(); - if( mImageUrl == imageUrl ) - { - return; - } - - mImageUrl = imageUrl; - if( mImpl->mRenderer ) - { - NinePatchImage nPatch = NinePatchImage::New( mImageUrl ); - InitializeFromImage( nPatch ); - - ChangeRenderer( oldBorderOnly, oldGridX, oldGridY ); - - if( mCroppedImage ) - { - ApplyImageToSampler(); - } - } -} - -void NPatchVisual::SetImage( NinePatchImage image, bool borderOnly ) -{ - bool oldBorderOnly = mBorderOnly; - size_t oldGridX = mStretchPixelsX.Size(); - size_t oldGridY = mStretchPixelsY.Size(); - - mBorderOnly = borderOnly; - mImageUrl.empty(); - if( mImage == image ) - { - return; - } - - mImage = image; - if( mImpl->mRenderer ) - { - InitializeFromImage( mImage ); - ChangeRenderer( oldBorderOnly, oldGridX, oldGridY ); - - if( mCroppedImage ) - { - ApplyImageToSampler(); - } - } -} - void NPatchVisual::InitializeFromImage( NinePatchImage nPatch ) { mCroppedImage = nPatch.CreateCroppedBufferImage(); diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.h b/dali-toolkit/internal/visuals/npatch/npatch-visual.h index 366d2b5..07918ee 100644 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.h +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.h @@ -18,10 +18,8 @@ * */ -// INTERNAL INCLUDES -#include - // EXTERNAL INCLUDES +#include #include #include #include @@ -29,6 +27,9 @@ #include #include +// INTERNAL INCLUDES +#include + namespace Dali { @@ -38,6 +39,9 @@ namespace Toolkit namespace Internal { +class NPatchVisual; +typedef IntrusivePtr< NPatchVisual > NPatchVisualPtr; + /** * The visual which renders an 9 patch image to the control's quad * @@ -54,16 +58,32 @@ class NPatchVisual: public Visual::Base public: /** - * @brief Constructor. + * @brief Create a new n-patch visual. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. */ - NPatchVisual( VisualFactoryCache& factoryCache ); + static NPatchVisualPtr New( VisualFactoryCache& factoryCache ); /** - * @brief A reference counted object may only be deleted by calling Unreference(). + * @brief Create an N-patch visual using an image URL. + * + * The visual will load the image synchronously when the associated actor is put on stage, and destroy the image when it is off stage + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @param[in] imageUrl The URL to 9 patch image resource to use + * @param[in] borderOnly A Flag to indicate if the image should omit the centre of the n-patch and only render the border + */ + static NPatchVisualPtr New( VisualFactoryCache& factoryCache, const std::string& imageUrl, bool borderOnly = false ); + + /** + * @brief Create an N-patch visual with a NinePatchImage resource. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @param[in] image The NinePatchImage to use + * @param[in] borderOnly A Flag to indicate if the image should omit the centre of the n-patch and only render the border */ - ~NPatchVisual(); + static NPatchVisualPtr New( VisualFactoryCache& factoryCache, NinePatchImage image, bool borderOnly = false ); public: // from Visual @@ -90,38 +110,32 @@ public: // from Visual protected: /** - * @copydoc Visual::Base::DoInitialize + * @brief Constructor. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @param[in] borderOnly A Flag to indicate if the image should omit the centre of the n-patch and only render the border */ - virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); + NPatchVisual( VisualFactoryCache& factoryCache, bool borderOnly = false ); /** - * @copydoc Visual::Base::DoSetOnStage + * @brief A reference counted object may only be deleted by calling Unreference(). */ - virtual void DoSetOnStage( Actor& actor ); + virtual ~NPatchVisual(); /** - * @copydoc Visual::Base::DoSetOffStage + * @copydoc Visual::Base::DoInitialize */ - virtual void DoSetOffStage( Actor& actor ); - -public: + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); /** - * @brief Sets the 9 patch image of this visual to the resource at imageUrl - * The visual will load the image synchronously when the associated actor is put on stage, and destroy the image when it is off stage - * - * @param[in] imageUrl The URL to 9 patch image resource to use - * @param[in] borderOnly A Flag to indicate if the image should omit the centre of the n-patch and only render the border + * @copydoc Visual::Base::DoSetOnStage */ - void SetImage( const std::string& imageUrl, bool borderOnly = false ); + virtual void DoSetOnStage( Actor& actor ); /** - * @brief Sets the 9 patch image of this viusal to the 9 patch image - * - * @param[in] image The NinePatchImage to use - * @param[in] borderOnly A Flag to indicate if the image should omit the centre of the n-patch and only render the border + * @copydoc Visual::Base::DoSetOffStage */ - void SetImage( NinePatchImage image, bool borderOnly = false ); + virtual void DoSetOffStage( Actor& actor ); private: diff --git a/dali-toolkit/internal/visuals/primitive/primitive-visual.cpp b/dali-toolkit/internal/visuals/primitive/primitive-visual.cpp index 956714b..6142ad1 100644 --- a/dali-toolkit/internal/visuals/primitive/primitive-visual.cpp +++ b/dali-toolkit/internal/visuals/primitive/primitive-visual.cpp @@ -160,7 +160,12 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( }\n ); -} // namespace +} // unnamed namespace + +PrimitiveVisualPtr PrimitiveVisual::New( VisualFactoryCache& factoryCache ) +{ + return new PrimitiveVisual( factoryCache ); +} PrimitiveVisual::PrimitiveVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), diff --git a/dali-toolkit/internal/visuals/primitive/primitive-visual.h b/dali-toolkit/internal/visuals/primitive/primitive-visual.h index 04f1d3d..59979f8 100644 --- a/dali-toolkit/internal/visuals/primitive/primitive-visual.h +++ b/dali-toolkit/internal/visuals/primitive/primitive-visual.h @@ -44,6 +44,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +// EXTERNAL INCLUDES +#include // INTERNAL INCLUDES #include @@ -58,6 +60,9 @@ namespace Toolkit namespace Internal { +class PrimitiveVisual; +typedef IntrusivePtr< PrimitiveVisual > PrimitiveVisualPtr; + /** * The visual which renders a simple 3D shape to the control's quad * @@ -97,16 +102,12 @@ class PrimitiveVisual: public Visual::Base public: /** - * @brief Constructor. + * @brief Create a new primitive visual. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. */ - PrimitiveVisual( VisualFactoryCache& factoryCache ); - - /** - * @brief A reference counted object may only be deleted by calling Unreference(). - */ - virtual ~PrimitiveVisual(); + static PrimitiveVisualPtr New( VisualFactoryCache& factoryCache ); public: // from Visual @@ -138,6 +139,18 @@ public: // from Visual protected: /** + * @brief Constructor. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + */ + PrimitiveVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~PrimitiveVisual(); + + /** * @copydoc Visual::Base::DoInitialize */ virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index 6c0bcfb..f3ad956 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -53,10 +53,24 @@ namespace Toolkit namespace Internal { +SvgVisualPtr SvgVisual::New( VisualFactoryCache& factoryCache ) +{ + return new SvgVisual( factoryCache ); +} + +SvgVisualPtr SvgVisual::New( VisualFactoryCache& factoryCache, const std::string& imageUrl, ImageDimensions size ) +{ + SvgVisual* svgVisual = new SvgVisual( factoryCache ); + svgVisual->ParseFromUrl( imageUrl, size ); + return svgVisual; +} + SvgVisual::SvgVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), mAtlasRect( FULL_TEXTURE_RECT ), - mParsedImage( NULL ) + mImageUrl(), + mParsedImage( NULL ), + mPlacementActor() { // the rasterized image is with pre-multiplied alpha format mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA; @@ -78,7 +92,7 @@ void SvgVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap ) std::string imageUrl; if( imageURLValue->Get( imageUrl ) ) { - SetImage( imageUrl ); + ParseFromUrl( imageUrl ); } else { @@ -133,7 +147,7 @@ void SvgVisual::GetNaturalSize( Vector2& naturalSize ) const void SvgVisual::SetSize( const Vector2& size ) { - if(mImpl->mSize != size && mParsedImage && GetIsOnStage() ) + if(mImpl->mSize != size && mParsedImage && IsOnStage() ) { AddRasterizationTask( size ); } @@ -161,30 +175,18 @@ Dali::Property::Value SvgVisual::DoGetProperty( Dali::Property::Index index ) return Dali::Property::Value(); } -void SvgVisual::SetImage( const std::string& imageUrl, ImageDimensions size ) +void SvgVisual::ParseFromUrl( const std::string& imageUrl, ImageDimensions size ) { - if( mImageUrl != imageUrl ) - { - mImageUrl = imageUrl; - - NSVGimage* parsedImageOld = mParsedImage; + mImageUrl = imageUrl; - Vector2 dpi = Stage::GetCurrent().GetDpi(); - float meanDpi = (dpi.height + dpi.width) * 0.5f; - mParsedImage = nsvgParseFromFile(mImageUrl.c_str(), UNITS, meanDpi); + Vector2 dpi = Stage::GetCurrent().GetDpi(); + float meanDpi = (dpi.height + dpi.width) * 0.5f; + mParsedImage = nsvgParseFromFile( imageUrl.c_str(), UNITS, meanDpi ); - if( size.GetWidth() != 0u && size.GetHeight() != 0u) - { - mImpl->mSize.x = size.GetWidth(); - mImpl->mSize.y = size.GetHeight(); - } - - if( mImpl->mSize != Vector2::ZERO && GetIsOnStage() ) - { - AddRasterizationTask( mImpl->mSize ); - } - - mFactoryCache.GetSVGRasterizationThread()->DeleteImage( parsedImageOld ); + if( size.GetWidth() != 0u && size.GetHeight() != 0u) + { + mImpl->mSize.x = size.GetWidth(); + mImpl->mSize.y = size.GetHeight(); } } @@ -203,7 +205,7 @@ void SvgVisual::AddRasterizationTask( const Vector2& size ) void SvgVisual::ApplyRasterizedImage( PixelData rasterizedPixelData ) { - if( GetIsOnStage() ) + if( IsOnStage() ) { TextureSet currentTextureSet = mImpl->mRenderer.GetTextures(); if( mAtlasRect != FULL_TEXTURE_RECT ) @@ -225,8 +227,9 @@ void SvgVisual::ApplyRasterizedImage( PixelData rasterizedPixelData ) } else // no atlasing { - Atlas texture = Atlas::New( rasterizedPixelData.GetWidth(), rasterizedPixelData.GetHeight() ); - texture.Upload( rasterizedPixelData, 0, 0 ); + Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, Pixel::RGBA8888, + rasterizedPixelData.GetWidth(), rasterizedPixelData.GetHeight() ); + texture.Upload( rasterizedPixelData ); mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED; if( mAtlasRect == FULL_TEXTURE_RECT ) @@ -244,7 +247,7 @@ void SvgVisual::ApplyRasterizedImage( PixelData rasterizedPixelData ) if( textureSet ) { - TextureSetImage( textureSet, 0u, texture ); + textureSet.SetTexture( 0, texture ); } } diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.h b/dali-toolkit/internal/visuals/svg/svg-visual.h index c040f47..5dbd24e 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.h +++ b/dali-toolkit/internal/visuals/svg/svg-visual.h @@ -18,7 +18,8 @@ * */ -//EXTERNAL INCLUDES +// EXTERNAL INCLUDES +#include #include // INTERNAL INCLUDES @@ -35,6 +36,9 @@ namespace Toolkit namespace Internal { +class SvgVisual; +typedef IntrusivePtr< SvgVisual > SvgVisualPtr; + /** * The visual which renders a svg image * @@ -50,16 +54,24 @@ class SvgVisual: public Visual::Base public: /** - * @brief Constructor. + * @brief Create a new SVG visual. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. */ - SvgVisual( VisualFactoryCache& factoryCache ); + static SvgVisualPtr New( VisualFactoryCache& factoryCache ); /** - * @brief A reference counted object may only be deleted by calling Unreference(). + * @brief Create the SVG Visual using the image URL. + * + * The visual will parse the SVG image once it is set. + * And rasterize it into BufferImage synchronously when the associated actor is put on stage, and destroy the BufferImage when it is off stage + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @param[in] imageUrl The URL to svg resource to use + * @param[in] size The required size for the SVG */ - ~SvgVisual(); + static SvgVisualPtr New( VisualFactoryCache& factoryCache, const std::string& imageUrl, ImageDimensions size = ImageDimensions() ); public: // from Visual @@ -91,6 +103,18 @@ public: // from Visual protected: /** + * @brief Constructor. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + */ + SvgVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~SvgVisual(); + + /** * @copydoc Visual::Base::DoInitialize */ virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); @@ -108,15 +132,6 @@ protected: public: /** - * @brief Sets the svg image of this visual to the resource at imageUrl - * The visual will parse the svg image once it is set. - * And rasterize it into BufferImage synchronously when the associated actor is put on stage, and destroy the BufferImage when it is off stage - * - * @param[in] imageUrl The URL to svg resource to use - */ - void SetImage( const std::string& imageUrl, ImageDimensions size = ImageDimensions() ); - - /** * @bried Apply the rasterized image to the visual. * * @param[in] rasterizedPixelData The pixel buffer with the rasterized pixels @@ -124,6 +139,15 @@ public: void ApplyRasterizedImage( PixelData rasterizedPixelData ); private: + + /** + * @brief Parses the SVG Image from the set URL. + * + * @param[in] imageUrl The URL of the image to parse the SVG from. + * @param[in] size The required size of the SVG + */ + void ParseFromUrl( const std::string& imageUrl, ImageDimensions size = ImageDimensions() ); + /** * @bried Rasterize the svg with the given size, and add it to the visual. * diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp new file mode 100644 index 0000000..3f9dd1e --- /dev/null +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -0,0 +1,874 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL HEADER +#include +// #include + +// INTERNAL HEADER +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Dali::Toolkit::Text::LayoutEngine; + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + +// Property names. +const char * const RENDERING_BACKEND_PROPERTY( "renderingBackend" ); +const char * const TEXT_PROPERTY( "text" ); +const char * const FONT_FAMILY_PROPERTY( "fontFamily" ); +const char * const FONT_STYLE_PROPERTY( "fontStyle" ); +const char * const POINT_SIZE_PROPERTY( "pointSize" ); +const char * const MULTI_LINE_PROPERTY( "multiLine" ); +const char * const HORIZONTAL_ALIGNMENT_PROPERTY( "horizontalAlignment" ); +const char * const VERTICAL_ALIGNMENT_PROPERTY( "verticalAlignment" ); +const char * const TEXT_COLOR_PROPERTY( "textColor" ); +const char * const ENABLE_MARKUP_PROPERTY( "enableMarkup" ); +const char * const ENABLE_AUTO_SCROLL_PROPERTY( "enableAutoScroll" ); +const char * const AUTO_SCROLL_SPEED_PROPERTY( "autoScrollSpeed" ); +const char * const AUTO_SCROLL_LOOP_COUNT_PROPERTY( "autoScrollLoopCount" ); +const char * const AUTO_SCROLL_GAP_PROPERTY( "autoScrollGap" ); +const char * const LINE_SPACING_PROPERTY( "lineSpacing" ); +const char * const UNDERLINE_PROPERTY( "underline" ); +const char * const SHADOW_PROPERTY( "shadow" ); +const char * const OUTLINE_PROPERTY( "outline" ); +const char * const BATCHING_ENABLED_PROPERTY( "batchingEnabled" ); + +const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] = +{ + { "BEGIN", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_BEGIN }, + { "CENTER", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_CENTER }, + { "END", Toolkit::Text::LayoutEngine::HORIZONTAL_ALIGN_END }, +}; +const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE ) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); + +const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] = +{ + { "TOP", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_TOP }, + { "CENTER", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_CENTER }, + { "BOTTOM", Toolkit::Text::LayoutEngine::VERTICAL_ALIGN_BOTTOM }, +}; +const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof( VERTICAL_ALIGNMENT_STRING_TABLE ) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); + +std::string GetHorizontalAlignment( LayoutEngine::HorizontalAlignment alignment ) +{ + const char* name = Scripting::GetEnumerationName( alignment, + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); + + return std::string( name ); +} + +std::string GetVerticalAlignment( LayoutEngine::VerticalAlignment alignment ) +{ + const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( alignment, + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); + + return std::string( name ); +} + +const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( + attribute mediump vec2 aPosition;\n + uniform mediump mat4 uMvpMatrix;\n + uniform mediump vec3 uSize;\n + uniform mediump vec4 pixelArea; + varying mediump vec2 vTexCoord;\n + \n + void main()\n + {\n + mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n + vertexPosition.xyz *= uSize;\n + vertexPosition = uMvpMatrix * vertexPosition;\n + \n + vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n + gl_Position = vertexPosition;\n + }\n +); + +const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord;\n + uniform sampler2D sTexture;\n + uniform mediump vec4 uAtlasRect;\n + uniform lowp vec4 uColor;\n + \n + void main()\n + {\n + mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );\n + gl_FragColor = texture2D( sTexture, texCoord ) * uColor;\n + }\n +); + +Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridSize ) +{ + Geometry geometry; + + if( gridSize == ImageDimensions( 1, 1 ) ) + { + geometry = factoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); + if( !geometry ) + { + geometry = VisualFactoryCache::CreateQuadGeometry(); + factoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry ); + } + } + else + { + geometry = VisualFactoryCache::CreateGridGeometry( gridSize ); + } + + return geometry; +} + +} // unnamed namespace + +TextVisualPtr TextVisual::New( VisualFactoryCache& factoryCache ) +{ + return new TextVisual( factoryCache ); +} + +void TextVisual::SetTextControlInterface( Text::ControlInterface* controlInterface ) +{ + if( mController ) + { + mController->SetTextControlInterface( controlInterface ); + } +} + +void TextVisual::SetSize( const Vector2& size ) +{ + const Text::Controller::UpdateTextType updateTextType = mController->Relayout( size ); + + if( ( Text::Controller::NONE_UPDATED != ( Text::Controller::MODEL_UPDATED & updateTextType ) ) || + !mRenderer ) + { + if( !mRenderer ) + { + mRenderer = Text::Backend::Get().NewRenderer( mRenderingBackend ); + } + + RenderText(); + } +} + +float TextVisual::GetHeightForWidth( float width ) const +{ + return mController->GetHeightForWidth( width ); +} + +void TextVisual::GetNaturalSize( Vector2& naturalSize ) const +{ + naturalSize = mController->GetNaturalSize().GetVectorXY(); +} + +void TextVisual::DoCreatePropertyMap( Property::Map& map ) const +{ + Property::Value value; + + map.Clear(); + map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::TEXT ); + + map.Insert( Toolkit::TextVisual::Property::RENDERING_BACKEND, mRenderingBackend ); + + std::string text; + mController->GetText( text ); + map.Insert( Toolkit::TextVisual::Property::TEXT, text ); + + map.Insert( Toolkit::TextVisual::Property::FONT_FAMILY, mController->GetDefaultFontFamily() ); + + GetFontStyleProperty( mController, value, Text::FontStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::FONT_STYLE, value ); + + map.Insert( Toolkit::TextVisual::Property::POINT_SIZE, mController->GetDefaultPointSize() ); + + map.Insert( Toolkit::TextVisual::Property::MULTI_LINE, mController->IsMultiLineEnabled() ); + + map.Insert( Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, GetHorizontalAlignment( mController->GetHorizontalAlignment() ) ); + + map.Insert( Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, GetVerticalAlignment( mController->GetVerticalAlignment() ) ); + + map.Insert( Toolkit::TextVisual::Property::TEXT_COLOR, mController->GetTextColor() ); + + map.Insert( Toolkit::TextVisual::Property::ENABLE_MARKUP, mController->IsMarkupProcessorEnabled() ); + + map.Insert( Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL, mController->IsAutoScrollEnabled() ); + + map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED, mController->GetAutoScrollSpeed() ); + + map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT, mController->GetAutoScrollLoopCount() ); + + map.Insert( Toolkit::TextVisual::Property::AUTO_SCROLL_GAP, mController->GetAutoScrollWrapGap() ); + + map.Insert( Toolkit::TextVisual::Property::LINE_SPACING, mController->GetDefaultLineSpacing() ); + + GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::UNDERLINE, value ); + + GetShadowProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::SHADOW, value ); + + GetOutlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + map.Insert( Toolkit::TextVisual::Property::OUTLINE, value ); + + map.Insert( Toolkit::TextVisual::Property::BATCHING_ENABLED, false ); // TODO +} + +TextVisual::TextVisual( VisualFactoryCache& factoryCache ) +: Visual::Base( factoryCache ), + mController( Text::Controller::New() ), + mRenderingBackend( Toolkit::Text::DEFAULT_RENDERING_BACKEND ), + mHasBeenStaged( false ) +{ +} + +TextVisual::~TextVisual() +{ +} + +void TextVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap ) +{ + mSelf = actor; + + for( Property::Map::SizeType index = 0u, count = propertyMap.Count(); index < count; ++index ) + { + const KeyValuePair& keyValue = propertyMap.GetKeyValue( index ); + + switch( keyValue.first.type ) + { + case Property::Key::INDEX: + { + if( Toolkit::Visual::Property::TYPE != keyValue.first.indexKey ) // Toolkit::Visual::Property::TYPE is not a TextVisual's property. + { + DoSetProperty( keyValue.first.indexKey, keyValue.second ); + } + break; + } + case Property::Key::STRING: + { + if( keyValue.first.stringKey == RENDERING_BACKEND_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::RENDERING_BACKEND, keyValue.second ); + } + else if( keyValue.first.stringKey == TEXT_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::TEXT, keyValue.second ); + } + else if( keyValue.first.stringKey == FONT_FAMILY_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::FONT_FAMILY, keyValue.second ); + } + else if( keyValue.first.stringKey == FONT_STYLE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::FONT_STYLE, keyValue.second ); + } + else if( keyValue.first.stringKey == POINT_SIZE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::POINT_SIZE, keyValue.second ); + } + else if( keyValue.first.stringKey == MULTI_LINE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::MULTI_LINE, keyValue.second ); + } + else if( keyValue.first.stringKey == HORIZONTAL_ALIGNMENT_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT, keyValue.second ); + } + else if( keyValue.first.stringKey == VERTICAL_ALIGNMENT_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT, keyValue.second ); + } + else if( keyValue.first.stringKey == TEXT_COLOR_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::TEXT_COLOR, keyValue.second ); + } + else if( keyValue.first.stringKey == ENABLE_MARKUP_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::ENABLE_MARKUP, keyValue.second ); + } + else if( keyValue.first.stringKey == ENABLE_AUTO_SCROLL_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL, keyValue.second ); + } + else if( keyValue.first.stringKey == AUTO_SCROLL_SPEED_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED, keyValue.second ); + } + else if( keyValue.first.stringKey == AUTO_SCROLL_LOOP_COUNT_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT, keyValue.second ); + } + else if( keyValue.first.stringKey == AUTO_SCROLL_GAP_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::AUTO_SCROLL_GAP, keyValue.second ); + } + else if( keyValue.first.stringKey == LINE_SPACING_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::LINE_SPACING, keyValue.second ); + } + else if( keyValue.first.stringKey == UNDERLINE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::UNDERLINE, keyValue.second ); + } + else if( keyValue.first.stringKey == SHADOW_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::SHADOW, keyValue.second ); + } + else if( keyValue.first.stringKey == OUTLINE_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::OUTLINE, keyValue.second ); + } + else if( keyValue.first.stringKey == BATCHING_ENABLED_PROPERTY ) + { + DoSetProperty( Toolkit::TextVisual::Property::BATCHING_ENABLED, keyValue.second ); + } + break; + } + } + } + + // Retrieve the layout engine to set whether to elide the text and set the cursor's width. + Text::LayoutEngine& engine = mController->GetLayoutEngine(); + + // Elide the text if it exceeds the boundaries. + engine.SetTextEllipsisEnabled( true ); + + // Sets 0 as cursor's width. + engine.SetCursorWidth( 0u ); // Do not layout space for the cursor. +} + +void TextVisual::DoSetOnStage( Actor& actor ) +{ + // TODO Create the actual renderer(s) for the text!!!! + // Will crash if no mImpl->mRenderer is set. + Geometry geometry; + Shader shader; + + geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) ); + + shader = mFactoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP ); + if( !shader ) + { + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP ); + mFactoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader ); + } + + mImpl->mRenderer = Renderer::New( geometry, shader ); + + mSelf = actor; + + if( mHasBeenStaged ) + { + RenderText(); + } + else + { + mHasBeenStaged = true; + } +} + +void TextVisual::DoSetOffStage( Actor& actor ) +{ + mSelf.Reset(); +} + +void TextVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue ) +{ + switch( index ) + { + case Toolkit::TextVisual::Property::RENDERING_BACKEND: + { + int backend = propertyValue.Get(); + +#ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING + if( Text::RENDERING_VECTOR_BASED == backend ) + { + backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering + } +#endif + if( mRenderingBackend != backend ) + { + mRenderingBackend = backend; + mRenderer.Reset(); + + // When using the vector-based rendering, the size of the GLyphs are different + TextAbstraction::GlyphType glyphType = ( Text::RENDERING_VECTOR_BASED == mRenderingBackend ) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH; + mController->SetGlyphType( glyphType ); + } + break; + } + case Toolkit::TextVisual::Property::TEXT: + { + mController->SetText( propertyValue.Get() ); + break; + } + case Toolkit::TextVisual::Property::FONT_FAMILY: + { + SetFontFamilyProperty( mController, propertyValue ); + break; + } + case Toolkit::TextVisual::Property::FONT_STYLE: + { + SetFontStyleProperty( mController, propertyValue, Text::FontStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::POINT_SIZE: + { + const float pointSize = propertyValue.Get(); + + if( !Equals( mController->GetDefaultPointSize(), pointSize ) ) + { + mController->SetDefaultPointSize( pointSize ); + } + break; + } + case Toolkit::TextVisual::Property::MULTI_LINE: + { + mController->SetMultiLineEnabled( propertyValue.Get() ); + break; + } + case Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT: + { + LayoutEngine::HorizontalAlignment alignment( LayoutEngine::HORIZONTAL_ALIGN_BEGIN ); + if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::HorizontalAlignment >( propertyValue.Get< std::string >().c_str(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT, + alignment ) ) + { + mController->SetHorizontalAlignment( alignment ); + } + break; + } + case Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT: + { + LayoutEngine::VerticalAlignment alignment( LayoutEngine::VERTICAL_ALIGN_BOTTOM ); + if( Scripting::GetEnumeration< Toolkit::Text::LayoutEngine::VerticalAlignment >( propertyValue.Get< std::string >().c_str(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT, + alignment ) ) + { + mController->SetVerticalAlignment( alignment ); + } + break; + } + case Toolkit::TextVisual::Property::TEXT_COLOR: + { + const Vector4 textColor = propertyValue.Get< Vector4 >(); + if( mController->GetTextColor() != textColor ) + { + mController->SetTextColor( textColor ); + mRenderer.Reset(); + } + break; + } + case Toolkit::TextVisual::Property::ENABLE_MARKUP: + { + const bool enableMarkup = propertyValue.Get(); + mController->SetMarkupProcessorEnabled( enableMarkup ); + break; + } + case Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL: + { + const bool enableAutoScroll = propertyValue.Get(); + + // If request to auto scroll is the same as current state then do nothing. + if( enableAutoScroll != mController->IsAutoScrollEnabled() ) + { + // If request is disable (false) and auto scrolling is enabled then need to stop it + if( !enableAutoScroll ) + { + StopTextAutoScrolling(); // Causes the current animation to finish playing. + } + // If request is enable (true) then start autoscroll as not already running + else + { + mController->GetLayoutEngine().SetTextEllipsisEnabled( false ); + mController->SetAutoScrollEnabled( enableAutoScroll ); + mController->RequestRelayout(); + } + } + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED: + { + mController->SetAutoscrollSpeed( propertyValue.Get() ); + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT: + { + const int loopCount = propertyValue.Get(); + if( loopCount > 0 ) + { + mController->SetAutoScrollLoopCount( loopCount ); + } + else + { + StopTextAutoScrolling(); // Causes the current animation to finish playing. + } + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_GAP: + { + mController->SetAutoScrollWrapGap( propertyValue.Get() ); + break; + } + case Toolkit::TextVisual::Property::LINE_SPACING: + { + const float lineSpacing = propertyValue.Get(); + mController->SetDefaultLineSpacing( lineSpacing ); + mRenderer.Reset(); + break; + } + case Toolkit::TextVisual::Property::UNDERLINE: + { + // TODO : This switch can be removed when the deprecated SHADOW_OFFSET and SHADOW_COLOR properties are finally removed. + // Only the code for the STRING case should be kept. + switch( propertyValue.GetType() ) + { + case Property::VECTOR4: + { + const Vector4 color = propertyValue.Get(); + if( mController->GetUnderlineColor() != color ) + { + mController->SetUnderlineColor( color ); + mRenderer.Reset(); + } + break; + } + case Property::FLOAT: + { + float height = propertyValue.Get(); + if( fabsf( mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 ) + { + mController->SetUnderlineHeight( height ); + mRenderer.Reset(); + } + break; + } + case Property::BOOLEAN: + { + const bool enabled = propertyValue.Get(); + if( mController->IsUnderlineEnabled() != enabled ) + { + mController->SetUnderlineEnabled( enabled ); + mRenderer.Reset(); + } + break; + } + case Property::STRING: + { + const bool update = SetUnderlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + if( update ) + { + mRenderer.Reset(); + } + break; + } + default: + { + // Nothing to do. + break; + } + } + + break; + } + case Toolkit::TextVisual::Property::SHADOW: + { + // TODO : This switch can be removed when the deprecated SHADOW_OFFSET and SHADOW_COLOR properties are finally removed. + // Only the code for the STRING case should be kept. + switch( propertyValue.GetType() ) + { + case Property::VECTOR2: + { + const Vector2 shadowOffset = propertyValue.Get(); + if( mController->GetShadowOffset() != shadowOffset ) + { + mController->SetShadowOffset( shadowOffset ); + mRenderer.Reset(); + } + break; + } + case Property::VECTOR4: + { + const Vector4 shadowColor = propertyValue.Get(); + if( mController->GetShadowColor() != shadowColor ) + { + mController->SetShadowColor( shadowColor ); + mRenderer.Reset(); + } + break; + } + case Property::STRING: + { + const bool update = SetShadowProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + if( update ) + { + mRenderer.Reset(); + } + break; + } + default: + { + // Nothing to do. + break; + } + } + break; + } + case Toolkit::TextVisual::Property::EMBOSS: + { + const bool update = SetEmbossProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + if( update ) + { + mRenderer.Reset(); + } + break; + } + case Toolkit::TextVisual::Property::OUTLINE: + { + const bool update = SetOutlineProperties( mController, propertyValue, Text::EffectStyle::DEFAULT ); + if( update ) + { + mRenderer.Reset(); + } + break; + } + case Toolkit::TextVisual::Property::BATCHING_ENABLED: + { + // TODO + break; + } + default: + { + // Should not arrive here. + DALI_ASSERT_DEBUG( false ); + } + } +} + +Dali::Property::Value TextVisual::DoGetProperty( Dali::Property::Index index ) +{ + Dali::Property::Value value; + + switch( index ) + { + case Toolkit::TextVisual::Property::RENDERING_BACKEND: + { + value = mRenderingBackend; + break; + } + case Toolkit::TextVisual::Property::TEXT: + { + std::string text; + mController->GetText( text ); + value = text; + break; + } + case Toolkit::TextVisual::Property::FONT_FAMILY: + { + value = mController->GetDefaultFontFamily(); + break; + } + case Toolkit::TextVisual::Property::FONT_STYLE: + { + GetFontStyleProperty( mController, value, Text::FontStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::POINT_SIZE: + { + value = mController->GetDefaultPointSize(); + break; + } + case Toolkit::TextVisual::Property::MULTI_LINE: + { + value = mController->IsMultiLineEnabled(); + break; + } + case Toolkit::TextVisual::Property::HORIZONTAL_ALIGNMENT: + { + const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::HorizontalAlignment >( mController->GetHorizontalAlignment(), + HORIZONTAL_ALIGNMENT_STRING_TABLE, + HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT ); + if( name ) + { + value = std::string( name ); + } + break; + } + case Toolkit::TextVisual::Property::VERTICAL_ALIGNMENT: + { + const char* name = Scripting::GetEnumerationName< Toolkit::Text::LayoutEngine::VerticalAlignment >( mController->GetVerticalAlignment(), + VERTICAL_ALIGNMENT_STRING_TABLE, + VERTICAL_ALIGNMENT_STRING_TABLE_COUNT ); + if( name ) + { + value = std::string( name ); + } + break; + } + case Toolkit::TextVisual::Property::TEXT_COLOR: + { + value = mController->GetTextColor(); + break; + } + case Toolkit::TextVisual::Property::ENABLE_MARKUP: + { + value = mController->IsMarkupProcessorEnabled(); + break; + } + case Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL: + { + value = mController->IsAutoScrollEnabled(); + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_SPEED: + { + value = mController->GetAutoScrollSpeed(); + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT: + { + value = mController->GetAutoScrollLoopCount(); + break; + } + case Toolkit::TextVisual::Property::AUTO_SCROLL_GAP: + { + value = mController->GetAutoScrollWrapGap(); + break; + } + case Toolkit::TextVisual::Property::LINE_SPACING: + { + value = mController->GetDefaultLineSpacing(); + break; + } + case Toolkit::TextVisual::Property::UNDERLINE: + { + GetUnderlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::SHADOW: + { + GetShadowProperties( mController, value, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::EMBOSS: + { + GetEmbossProperties( mController, value, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::OUTLINE: + { + GetOutlineProperties( mController, value, Text::EffectStyle::DEFAULT ); + break; + } + case Toolkit::TextVisual::Property::BATCHING_ENABLED: + { + // TODO + break; + } + default: + { + // Should not arrive here. + DALI_ASSERT_DEBUG( false ); + } + } + + return value; +} + +void TextVisual::RenderText() +{ + Actor renderableActor; + + if( mRenderer ) + { + renderableActor = mRenderer->Render( mController->GetView(), Toolkit::DepthIndex::TEXT ); + } + + if( renderableActor != mRenderableActor ) + { + UnparentAndReset( mRenderableActor ); + + if( renderableActor ) + { + const Vector2& scrollOffset = mController->GetScrollPosition(); + renderableActor.SetPosition( scrollOffset.x, scrollOffset.y ); + + mSelf.Add( renderableActor ); + } + mRenderableActor = renderableActor; + + if( mController->IsAutoScrollEnabled() ) + { + SetUpAutoScrolling(); + } + } +} + +void TextVisual::StopTextAutoScrolling() +{ + if( mTextScroller ) + { + mTextScroller->StopScrolling(); + } +} + +void TextVisual::SetUpAutoScrolling() +{ + const Text::ScrollerData* const data = mController->GetAutoScrollData(); + + if( NULL != data ) + { + if( !mTextScroller ) + { + // If speed, loopCount or gap not set via property system then will need to create a TextScroller with defaults + mTextScroller = Text::TextScroller::New( *mController ); + } + + mTextScroller->StartScrolling( mRenderableActor, + *data ); + + mSelf.Add( mTextScroller->GetScrollingText() ); + mSelf.Add( mTextScroller->GetSourceCamera() ); + } +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/visuals/text/text-visual.h b/dali-toolkit/internal/visuals/text/text-visual.h new file mode 100644 index 0000000..c609990 --- /dev/null +++ b/dali-toolkit/internal/visuals/text/text-visual.h @@ -0,0 +1,187 @@ +#ifndef DALI_TOOLKIT_INTERNAL_TEXT_VISUAL_H +#define DALI_TOOLKIT_INTERNAL_TEXT_VISUAL_H + +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +class TextVisual; +typedef IntrusivePtr< TextVisual > TextVisualPtr; + +/** + * The visual which renders text + * + * The following properties are optional: + * + * | %Property Name | Type | + * |---------------------|---------| + * | renderingBackend | INTEGER | + * | text | STRING | + * | fontFamily | STRING | + * | fontStyle | STRING | + * | pointSize | FLOAT | + * | multiLine | BOOLEAN | + * | horizontalAlignment | STRING | + * | verticalAlignment | STRING | + * | textColor | VECTOR4 | + * | enableMarkup | BOOLEAN | + * | enableAutoScroll | BOOLEAN | + * | autoScrollSpeed | INTEGER | + * | autoScrollLoopCount | INTEGER | + * | autoScrollGap | INTEGER | + * | lineSpacing | FLOAT | + * | underline | STRING | + * | shadow | STRING | + * | outline | STRING | + * | batchingEnabled | BOOLEAN | + * + */ +class TextVisual : public Visual::Base +{ +public: + + /** + * @brief Create a new text visual. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. + */ + static TextVisualPtr New( VisualFactoryCache& factoryCache ); + + /** + * @brief Sets the text control interface which is needed to communicate with a control. + * @param[in] controlInterface Pointer to the control-interface. + */ + void SetTextControlInterface( Text::ControlInterface* controlInterface ); + +public: // from Visual::Base + + /** + * @copydoc Visual::Base::GetHeightForWidth() + */ + float GetHeightForWidth( float width ) const; + + /** + * @copydoc Visual::Base::GetNaturalSize() + */ + virtual void SetSize( const Vector2& size ); + + /** + * @copydoc Visual::Base::GetNaturalSize() + */ + virtual void GetNaturalSize( Vector2& naturalSize ) const; + + /** + * @copydoc Visual::Base::CreatePropertyMap() + */ + virtual void DoCreatePropertyMap( Property::Map& map ) const; + +protected: + + /** + * @brief Constructor. + * + * @param[in] factoryCache The VisualFactoryCache object + */ + TextVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~TextVisual(); + + // from Visual::Base + + /** + * @copydoc Visual::Base::DoInitialize() + */ + virtual void DoInitialize( Actor& actor, const Property::Map& propertyMap ); + + /** + * @copydoc Visual::Base::DoSetOnStage() + */ + virtual void DoSetOnStage( Actor& actor ); + + /** + * @copydoc Visual::Base::DoSetOffStage() + */ + virtual void DoSetOffStage( Actor& actor ); + + /** + *@copydoc Visual::Base::DoSetProperty + */ + virtual void DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue ); + + /** + * @copydoc Visual::Base::DoGetProperty + */ + virtual Dali::Property::Value DoGetProperty( Dali::Property::Index index ); + +private: + + /** + * @brief Render view, create and attach actor(s) to this TextView. + * @todo In a next patch a new text render back-end won't add extra actors. + */ + void RenderText(); + + /** + * @brief Stops the text auto scroll. + */ + void StopTextAutoScrolling(); + + /** + * @brief Set up Autoscrolling. + */ + void SetUpAutoScrolling(); + +private: + Text::ControllerPtr mController; ///< The text's controller. + Actor mSelf; + + Text::RendererPtr mRenderer; + Text::TextScrollerPtr mTextScroller; + Actor mRenderableActor; + + int mRenderingBackend; + bool mHasBeenStaged : 1; +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif /* DALI_TOOLKIT_INTERNAL_TEXT_VISUAL_H */ diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 922f561..48df29a 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -94,6 +94,11 @@ const Vector2& Visual::Base::GetSize() const return mImpl->mSize; } +float Visual::Base::GetHeightForWidth( float width ) const +{ + return 0.f; +} + void Visual::Base::GetNaturalSize( Vector2& naturalSize ) const { naturalSize = Vector2::ZERO; @@ -126,7 +131,7 @@ void Visual::Base::SetOnStage( Actor& actor ) void Visual::Base::SetOffStage( Actor& actor ) { - if( GetIsOnStage() ) + if( IsOnStage() ) { DoSetOffStage( actor ); @@ -134,6 +139,16 @@ void Visual::Base::SetOffStage( Actor& actor ) } } +void Visual::Base::CreatePropertyMap( Property::Map& map ) const +{ + DoCreatePropertyMap( map ); + + if( mImpl->mCustomShader ) + { + mImpl->mCustomShader->CreatePropertyMap( map ); + } +} + void Visual::Base::EnablePreMultipliedAlpha( bool preMultipled ) { if(preMultipled) @@ -162,22 +177,12 @@ void Visual::Base::DoSetOffStage( Actor& actor ) mImpl->mRenderer.Reset(); } -void Visual::Base::CreatePropertyMap( Property::Map& map ) const -{ - DoCreatePropertyMap( map ); - - if( mImpl->mCustomShader ) - { - mImpl->mCustomShader->CreatePropertyMap( map ); - } -} - -bool Visual::Base::GetIsOnStage() const +bool Visual::Base::IsOnStage() const { return mImpl->mFlags & Impl::IS_ON_STAGE; } -bool Visual::Base::GetIsFromCache() const +bool Visual::Base::IsFromCache() const { return mImpl->mFlags & Impl::IS_FROM_CACHE; } diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index 5c48c1d..475a5fa 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -19,6 +19,7 @@ */ // EXTERNAL INCLUDES +#include #include #include #include @@ -95,6 +96,11 @@ public: const Vector2& GetSize() const; /** + * @copydoc Toolkit::Visual::Base::GetHeightForWidth + */ + virtual float GetHeightForWidth( float width ) const; + + /** * @copydoc Toolkit::Visual::Base::GetNaturalSize */ virtual void GetNaturalSize( Vector2& naturalSize ) const; @@ -130,7 +136,7 @@ public: * * @param[in] preMultipled whether alpha is pre-multiplied. */ - void EnablePreMultipliedAlpha( bool preMultipled ); + void EnablePreMultipliedAlpha( bool preMultipled ); /** * @brief Query whether alpha is pre-multiplied. @@ -204,19 +210,20 @@ protected: virtual void DoSetOffStage( Actor& actor ); protected: + /** * @brief Gets the on stage state for this Visual * * @return Returns true if this Visual is on stage, false if it is off the stage */ - bool GetIsOnStage() const; + bool IsOnStage() const; /** * @brief Gets whether the Dali::Renderer is from a shared cache (and therefore any modifications will affect other users of that renderer) * * @return Returns true if the renderer is from shared cache, false otherwise */ - bool GetIsFromCache() const; + bool IsFromCache() const; protected: /** @@ -250,6 +257,8 @@ protected: VisualFactoryCache& mFactoryCache; }; +typedef IntrusivePtr BasePtr; + } // namspace Visual } // namespace Internal diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.cpp b/dali-toolkit/internal/visuals/visual-factory-impl.cpp index 6baaec2..c7a9f33 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-impl.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -99,10 +100,10 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property // Return a new WireframeVisual if we have debug enabled if( mDebugEnabled ) { - return Toolkit::Visual::Base( new WireframeVisual( *( mFactoryCache.Get() ) ) ); + return Toolkit::Visual::Base( WireframeVisual::New( *( mFactoryCache.Get() ) ).Get() ); } - Visual::Base* visualPtr = NULL; + Visual::BasePtr visualPtr; Property::Value* typeValue = propertyMap.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE ); Toolkit::Visual::Type visualType = Toolkit::Visual::IMAGE; // Default to IMAGE type. @@ -115,19 +116,19 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property { case Toolkit::Visual::BORDER: { - visualPtr = new BorderVisual( *( mFactoryCache.Get() ) ); + visualPtr = BorderVisual::New( *( mFactoryCache.Get() ) ); break; } case Toolkit::Visual::COLOR: { - visualPtr = new ColorVisual( *( mFactoryCache.Get() ) ); + visualPtr = ColorVisual::New( *( mFactoryCache.Get() ) ); break; } case Toolkit::Visual::GRADIENT: { - visualPtr = new GradientVisual( *( mFactoryCache.Get() ) ); + visualPtr = GradientVisual::New( *( mFactoryCache.Get() ) ); break; } @@ -141,11 +142,11 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property UrlType::Type type = ResolveUrlType( imageUrl ); if( UrlType::N_PATCH == type ) { - visualPtr = new NPatchVisual( *( mFactoryCache.Get() ) ); + visualPtr = NPatchVisual::New( *( mFactoryCache.Get() ) ); } else if( UrlType::SVG == type ) { - visualPtr = new SvgVisual( *( mFactoryCache.Get() ) ); + visualPtr = SvgVisual::New( *( mFactoryCache.Get() ) ); } else // Regular image { @@ -158,12 +159,12 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property if( batchingEnabled ) { - visualPtr = new BatchImageVisual( *( mFactoryCache.Get() ) ); + visualPtr = BatchImageVisual::New( *( mFactoryCache.Get() ) ); break; } else { - visualPtr = new ImageVisual( *( mFactoryCache.Get() ) ); + visualPtr = ImageVisual::New( *( mFactoryCache.Get() ) ); } } } @@ -173,22 +174,27 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property case Toolkit::Visual::MESH: { - visualPtr = new MeshVisual( *( mFactoryCache.Get() ) ); + visualPtr = MeshVisual::New( *( mFactoryCache.Get() ) ); break; } case Toolkit::Visual::PRIMITIVE: { - visualPtr = new PrimitiveVisual( *( mFactoryCache.Get() ) ); + visualPtr = PrimitiveVisual::New( *( mFactoryCache.Get() ) ); break; } case Toolkit::Visual::WIREFRAME: { - visualPtr = new WireframeVisual( *( mFactoryCache.Get() ) ); + visualPtr = WireframeVisual::New( *( mFactoryCache.Get() ) ); break; } + case Toolkit::Visual::TEXT: + { + visualPtr = TextVisual::New( *( mFactoryCache.Get() ) ); + break; + } } if( visualPtr ) @@ -201,7 +207,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property DALI_LOG_ERROR( "Renderer type unknown\n" ); } - return Toolkit::Visual::Base( visualPtr ); + return Toolkit::Visual::Base( visualPtr.Get() ); } Toolkit::Visual::Base VisualFactory::CreateVisual( const Image& image ) @@ -213,25 +219,22 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Image& image ) if( mDebugEnabled ) { - return Toolkit::Visual::Base( new WireframeVisual( *( mFactoryCache.Get() ) ) ); + return Toolkit::Visual::Base( WireframeVisual::New( *( mFactoryCache.Get() ) ).Get() ); } + Visual::BasePtr visualPtr; + NinePatchImage npatchImage = NinePatchImage::DownCast( image ); if( npatchImage ) { - NPatchVisual* visualPtr = new NPatchVisual( *( mFactoryCache.Get() ) ); - visualPtr->SetImage( npatchImage ); - - return Toolkit::Visual::Base( visualPtr ); + visualPtr = NPatchVisual::New( *( mFactoryCache.Get() ), npatchImage ); } else { - ImageVisual* visualPtr = new ImageVisual( *( mFactoryCache.Get() ) ); - Actor actor; - visualPtr->SetImage( actor, image ); - - return Toolkit::Visual::Base( visualPtr ); + visualPtr = ImageVisual::New( *( mFactoryCache.Get() ), image ); } + + return Toolkit::Visual::Base( visualPtr.Get() ); } Toolkit::Visual::Base VisualFactory::CreateVisual( const std::string& url, ImageDimensions size ) @@ -243,32 +246,27 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const std::string& url, Image if( mDebugEnabled ) { - return Toolkit::Visual::Base( new WireframeVisual( *( mFactoryCache.Get() ) ) ); + return Toolkit::Visual::Base( WireframeVisual::New( *( mFactoryCache.Get() ) ).Get() ); } + Visual::BasePtr visualPtr; + // first resolve url type to know which visual to create UrlType::Type type = ResolveUrlType( url ); if( UrlType::N_PATCH == type ) { - NPatchVisual* visualPtr = new NPatchVisual( *( mFactoryCache.Get() ) ); - visualPtr->SetImage( url ); - - return Toolkit::Visual::Base( visualPtr ); + visualPtr = NPatchVisual::New( *( mFactoryCache.Get() ), url ); } else if( UrlType::SVG == type ) { - SvgVisual* visualPtr = new SvgVisual( *( mFactoryCache.Get() ) ); - visualPtr->SetImage( url, size ); - return Toolkit::Visual::Base( visualPtr ); + visualPtr = SvgVisual::New( *( mFactoryCache.Get() ), url, size ); } else // Regular image { - ImageVisual* visualPtr = new ImageVisual( *( mFactoryCache.Get() )); - Actor actor; - visualPtr->SetImage( actor, url, size ); - - return Toolkit::Visual::Base( visualPtr ); + visualPtr = ImageVisual::New( *( mFactoryCache.Get() ), url, size ); } + + return Toolkit::Visual::Base( visualPtr.Get() ); } } // namespace Internal diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.h b/dali-toolkit/internal/visuals/visual-factory-impl.h index 484a688..501a854 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.h +++ b/dali-toolkit/internal/visuals/visual-factory-impl.h @@ -65,7 +65,6 @@ public: */ Toolkit::Visual::Base CreateVisual( const std::string& image, ImageDimensions size ); - protected: /** diff --git a/dali-toolkit/internal/visuals/wireframe/wireframe-visual.cpp b/dali-toolkit/internal/visuals/wireframe/wireframe-visual.cpp index 551e14f..09a7a8d 100644 --- a/dali-toolkit/internal/visuals/wireframe/wireframe-visual.cpp +++ b/dali-toolkit/internal/visuals/wireframe/wireframe-visual.cpp @@ -64,6 +64,10 @@ void main()\n } +WireframeVisualPtr WireframeVisual::New( VisualFactoryCache& factoryCache ) +{ + return new WireframeVisual( factoryCache ); +} WireframeVisual::WireframeVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ) @@ -71,7 +75,8 @@ WireframeVisual::WireframeVisual( VisualFactoryCache& factoryCache ) } WireframeVisual::~WireframeVisual() -{} +{ +} void WireframeVisual::DoSetOnStage( Actor& actor ) { diff --git a/dali-toolkit/internal/visuals/wireframe/wireframe-visual.h b/dali-toolkit/internal/visuals/wireframe/wireframe-visual.h index 805e2c7..c4ff5c4 100644 --- a/dali-toolkit/internal/visuals/wireframe/wireframe-visual.h +++ b/dali-toolkit/internal/visuals/wireframe/wireframe-visual.h @@ -18,6 +18,9 @@ * */ +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include @@ -30,15 +33,27 @@ namespace Toolkit namespace Internal { +class WireframeVisual; +typedef IntrusivePtr< WireframeVisual > WireframeVisualPtr; + /** - * The visual which renders a wireframe outline to the control's quad. - * + * @brief Renders a wireframe outline to the control's quad. */ class WireframeVisual: public Visual::Base { public: /** + * @brief Create a new wireframe visual. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @return A smart-pointer to the newly allocated visual. + */ + static WireframeVisualPtr New( VisualFactoryCache& factoryCache ); + +protected: + + /** * @brief Constructor. * * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object @@ -50,8 +65,6 @@ public: */ virtual ~WireframeVisual(); -protected: - /** * @copydoc Visual::Base::DoSetOnStage */ diff --git a/dali-toolkit/public-api/controls/text-controls/text-label.h b/dali-toolkit/public-api/controls/text-controls/text-label.h index c9322aa..9c216c2 100644 --- a/dali-toolkit/public-api/controls/text-controls/text-label.h +++ b/dali-toolkit/public-api/controls/text-controls/text-label.h @@ -122,7 +122,7 @@ public: /** * @brief The single-line or multi-line layout option - * @details name "multiLine", type FLOAT, default SINGLE_LINE_BOX + * @details name "multiLine", type BOOLEAN, default false * @SINCE_1_0.0 */ MULTI_LINE, @@ -150,7 +150,7 @@ public: /** * @brief The drop shadow offset 0 indicates no shadow - * @details name "shadowOffset", type VECTOR4 + * @details name "shadowOffset", type VECTOR2 * @DEPRECATED_1_1.37 Use SHADOW instead */ SHADOW_OFFSET, @@ -192,13 +192,13 @@ public: /** * @brief Start or stop auto scrolling, - * @details name "enableMarkup", type BOOLEAN, default is false + * @details name "enableAutoScroll", type BOOLEAN, default is false * @SINCE_1_1.35 */ ENABLE_AUTO_SCROLL, /** - * @brief Start or stop auto scrolling, + * @brief Sets the speed of scrolling in pixels per second, * @details name "autoScrollSpeed", type INT, default in style sheet * @SINCE_1_1.35 */ diff --git a/dali-toolkit/public-api/file.list b/dali-toolkit/public-api/file.list index 96b9818..3734525 100755 --- a/dali-toolkit/public-api/file.list +++ b/dali-toolkit/public-api/file.list @@ -113,4 +113,5 @@ public_api_visuals_header_files = \ $(public_api_src_dir)/visuals/image-visual-properties.h \ $(public_api_src_dir)/visuals/mesh-visual-properties.h \ $(public_api_src_dir)/visuals/primitive-visual-properties.h \ + $(public_api_src_dir)/visuals/text-visual-properties.h \ $(public_api_src_dir)/visuals/visual-properties.h diff --git a/dali-toolkit/public-api/visuals/text-visual-properties.h b/dali-toolkit/public-api/visuals/text-visual-properties.h new file mode 100644 index 0000000..39a5eb3 --- /dev/null +++ b/dali-toolkit/public-api/visuals/text-visual-properties.h @@ -0,0 +1,188 @@ +#ifndef DALI_TOOLKIT_TEXT_VISUAL_PROPERTIES_H +#define DALI_TOOLKIT_TEXT_VISUAL_PROPERTIES_H + +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace TextVisual +{ + +namespace Property +{ + +enum +{ + /** + * @brief The type of rendering e.g. bitmap-based + * @details name "renderingBackend", type INTEGER, default RENDERING_SHARED_ATLAS + * @SINCE_1_2.11 + */ + RENDERING_BACKEND = VISUAL_PROPERTY_START_INDEX, + + /** + * @brief The text to display in UTF-8 format, + * @details name "text", type STRING + * @SINCE_1_2.11 + */ + TEXT, + + /** + * @brief The requested font family to use, + * @details name "fontFamily", type STRING + * @SINCE_1_2.11 + */ + FONT_FAMILY, + + /** + * @brief The requested font style to use, + * @details name "fontStyle", type STRING + * @SINCE_1_2.11 + */ + FONT_STYLE, + + /** + * @brief The size of font in points + * @details name "pointSize", type FLOAT + * @SINCE_1_2.11 + */ + POINT_SIZE, + + /** + * @brief The single-line or multi-line layout option + * @details name "multiLine", type BOOLEAN, default false + * @SINCE_1_2.11 + */ + MULTI_LINE, + + /** + * @brief The line horizontal alignment + * @details name "horizontalAlignment", type STRING, values "BEGIN", "CENTER", "END", default BEGIN + * @SINCE_1_2.11 + */ + HORIZONTAL_ALIGNMENT, + + /** + * @brief The line vertical alignment + * @details name "verticalAlignment", type STRING, values "TOP", "CENTER", "BOTTOM", default TOP + * @SINCE_1_2.11 + */ + VERTICAL_ALIGNMENT, + + /** + * @brief The color of the text + * @details name "textColor", type VECTOR4 + * @SINCE_1_2.11 + */ + TEXT_COLOR, + + /** + * @brief Whether the mark-up processing is enabled + * @details name "enableMarkup", type BOOLEAN + * @SINCE_1_2.11 + */ + ENABLE_MARKUP, + + /** + * @brief Start or stop auto scrolling, + * @details name "enableAutoScroll", type BOOLEAN, default is false + * @SINCE_1_2.11 + */ + ENABLE_AUTO_SCROLL, + + /** + * @brief Sets the speed of scrolling in pixels per second, + * @details name "autoScrollSpeed", type INTEGER, default in style sheet + * @SINCE_1_2.11 + */ + AUTO_SCROLL_SPEED, + + /** + * @brief Number of complete loops when scrolling enabled + * @details name "autoScrollLoopCount", type INTEGER, default in style sheet + * @SINCE_1_2.11 + */ + AUTO_SCROLL_LOOP_COUNT, + + /** + * @brief Gap before before scrolling wraps + * @details name "autoScrollGap", type INTEGER, default in style sheet but can be overridden to prevent same text being show at start and end. + * @SINCE_1_2.11 + */ + AUTO_SCROLL_GAP, + + /** + * @brief The default extra space between lines in points. + * @details name "lineSpacing", type FLOAT. + * @SINCE_1_2.11 + */ + LINE_SPACING, + + /** + * @brief The default underline parameters. + * @details name "underline", type STRING. + * @SINCE_1_2.11 + */ + UNDERLINE, + + /** + * @brief The default shadow parameters. + * @details name "shadow", type STRING. + * @SINCE_1_2.11 + */ + SHADOW, + + /** + * @brief The default emboss parameters. + * @details name "emboss", type STRING. + * @SINCE_1_2.11 + */ + EMBOSS, + + /** + * @brief The default outline parameters. + * @details name "outline", type STRING. + * @SINCE_1_2.11 + */ + OUTLINE, + + /** + * @brief This enables Text visuals to automatically be converted to Batch-Text visuals. + * @details Name "batchingEnabled", type Property::BOOLEAN. + * @SINCE_1_2.11 + * @note Optional. If not specified, the default is false. + */ + BATCHING_ENABLED, +}; + +} // namespace Property + +} // namespace TextVisual + +} // namespace Toolkit + +} // namespace Dali + +#endif // DALI_TOOLKIT_TEXT_VISUAL_PROPERTIES_H diff --git a/dali-toolkit/public-api/visuals/visual-properties.h b/dali-toolkit/public-api/visuals/visual-properties.h index 989d938..c64a73c 100644 --- a/dali-toolkit/public-api/visuals/visual-properties.h +++ b/dali-toolkit/public-api/visuals/visual-properties.h @@ -43,6 +43,7 @@ enum Type MESH, ///< Renders a mesh using an "obj" file, optionally with textures provided by an "mtl" file. @SINCE_1_1.45 PRIMITIVE, ///< Renders a simple 3D shape, such as a cube or sphere. @SINCE_1_1.45 WIREFRAME, ///< Renders a simple wire-frame outlining a quad. @SINCE_1_2_2 + TEXT, ///< Renders text. @SINCE_1_2.11 }; namespace Property diff --git a/plugins/dali-swig/examples/firstscreen/App.cs b/plugins/dali-swig/examples/firstscreen/App.cs new file mode 100644 index 0000000..e96d98d --- /dev/null +++ b/plugins/dali-swig/examples/firstscreen/App.cs @@ -0,0 +1,392 @@ +using Dali; +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace FirstScreen +{ + public class FirstScreenApp + { + private int _currentPostersContainerID; + private int _totalPostersContainers; + + private Application _application; + private Stage _stage; + private Vector2 _stageSize; + + private List _postersContainer; + + private ScrollContainer _menuContainer; + private Vector3 _menuItemSize; + + private Layer _bottomClipLayer; + private Layer _topClipLayer; + private View _topContainer; + private View _bottomContainer; + + private EdenEffect _edenEffect; + private string _imagePath; + + private ImageView _keyboardFocusIndicator; + private ImageView _launcherSeparator; + private ImageView[] launcherIcon; + private Animation _showBottomContainerAnimation; + private Animation _hideBottomContainerAnimation; + + public FirstScreenApp(Application application) + { + _application = application; + _application.Initialized += OnInitialize; + } + + public static void Run() + { + FirstScreenApp tVApp = new FirstScreenApp(Application.NewApplication()); + tVApp.MainLoop(); + } + + public void MainLoop() + { + _application.MainLoop(); + } + + // Create Items for Poster ScrollContainer + private void CreatePosters() + { + for (int j = 0; j < _totalPostersContainers; j++) + { + View posterContainer = _postersContainer[j].Container; + for (int i = 0; i < Constants.PostersItemsCount; i++) + { + if (j % _totalPostersContainers == 0) + { + View item = new ImageView(_imagePath + "/poster"+j+"/"+ (i % 6)+ ".jpg"); + item.SetName ("poster-item-" + _postersContainer[j].ItemCount); + _postersContainer[j].AddItem(item); + } + else + { + View item = new ImageView(_imagePath + "/poster"+j+"/"+ (i % 6)+ ".jpg"); + item.SetName ("poster-item-" + _postersContainer[j].ItemCount); + _postersContainer[j].AddItem(item); + } + } + + if (j == 0) + { + _postersContainer[j].Show(); + } + else + { + _postersContainer[j].Hide(); + } + + _postersContainer[j].SetFocused(false); + } + + _currentPostersContainerID = 0; + } + + // Create Items for Menu ScrollContainer + private void CreateMenu() + { + View menuContainer = _menuContainer.Container; + menuContainer.Position = new Vector3(Constants.LauncherWidth, 0.0f, 0.0f); + + for(int i = 0; i < Constants.MenuItemsCount; i++) + { + View menuItem = new ImageView(_imagePath + "/menu/" + i % 7 + ".png"); + menuItem.SetName("menu-item-" + _menuContainer.ItemCount); + _menuContainer.AddItem(menuItem); + } + } + + private Actor OnKeyboardPreFocusChangeSignal(object source, KeyboardFocusManager.PreFocusChangeEventArgs e) + { + Actor actor = _menuContainer.ItemRoot; + + if (e.Direction == View.KeyboardFocus.Direction.UP) + { + // Move the Focus to Poster ScrollContainer and hide Bottom Container (Menu ScrollContainer) + if (_menuContainer.IsFocused) + { + actor = _postersContainer[_currentPostersContainerID].GetCurrentFocusedActor(); + _menuContainer.SetFocused(false); + _postersContainer[_currentPostersContainerID].SetFocused(true); + HideBottomContainer(); + + // Also apply Focus animation on Focused item on Poster ScrollContainer + _postersContainer[_currentPostersContainerID].FocusAnimation(_edenEffect, EdenEffectDirection.BottomToTop); + } + } + else if (e.Direction == View.KeyboardFocus.Direction.DOWN) + { + // Show Bottom Container (Menu ScrollContainer) and move the Focus to it + if (!_menuContainer.IsFocused) + { + ShowBottomContainer(); + actor = _menuContainer.GetCurrentFocusedActor(); + _postersContainer[_currentPostersContainerID].SetFocused(false); + _menuContainer.SetFocused(true); + + // Also apply Focus animation on Focused item on Menu ScrollContainer + _menuContainer.FocusAnimation(_edenEffect, EdenEffectDirection.TopToBottom); + } + } + else if (e.Direction == View.KeyboardFocus.Direction.LEFT) + { + if (_menuContainer.IsFocused) + { + // Move the Focus to the left item/image of currently focused item on Menu ScrollContainer + actor = _menuContainer.FocusPrevious(); + + int id = _menuContainer.FocusedItemID % _totalPostersContainers; + if (id != _currentPostersContainerID) + { + _postersContainer[_currentPostersContainerID].Hide(); + _currentPostersContainerID = id; + + _postersContainer[_currentPostersContainerID].Show(); + } + } + else + { + // Move the Focus to the left item/image of currently focused item on Poster ScrollContainer + actor = _postersContainer[_currentPostersContainerID].FocusPrevious(); + } + } + else if (e.Direction == View.KeyboardFocus.Direction.RIGHT) + { + if (_menuContainer.IsFocused) + { + // Move the Focus to the right item/image of currently focused item on Menu ScrollContainer + actor = _menuContainer.FocusNext(); + + int id = _menuContainer.FocusedItemID % _totalPostersContainers; + if (id != _currentPostersContainerID) + { + _postersContainer[_currentPostersContainerID].Hide(); + _currentPostersContainerID = id; + _postersContainer[_currentPostersContainerID].Show(); + } + } + else + { + // Move the Focus to the right item/image of currently focused item on Poster ScrollContainer + actor = _postersContainer[_currentPostersContainerID].FocusNext(); + } + } + + return actor; + } + + // Hide Bottom Container (Menu ScrollContainer) when it is not focused + private void HideBottomContainer() + { + _topClipLayer.ClippingBox = new RectInteger(0, + Convert.ToInt32(_stageSize.height * Constants.TopContainerPositionFactor), + Convert.ToInt32((_stageSize.width)), + Convert.ToInt32((_stageSize.height * Constants.TopClipLayerExpandHeightFactor))); // X, Y, Width, Height + + _hideBottomContainerAnimation.AnimateTo(new Property(_bottomContainer, Actor.Property.POSITION), + new Property.Value(new Vector3(0.0f, _stageSize.height * Constants.BottomContainerHidePositionFactor, 0.0f)), + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + _hideBottomContainerAnimation.Play(); + } + + // Show (unhide) Bottom Container (Menu ScrollContainer) when it is focused + private void ShowBottomContainer() + { + _topClipLayer.ClippingBox = new RectInteger(0, + Convert.ToInt32(_stageSize.height * Constants.TopContainerPositionFactor), + Convert.ToInt32((_stageSize.width)), + Convert.ToInt32((_stageSize.height * Constants.TopClipLayerHeightFactor))); // X, Y, Width, Height + + _showBottomContainerAnimation.AnimateTo(new Property(_bottomContainer, Actor.Property.POSITION), + new Property.Value(new Vector3(0.0f, _stageSize.height * Constants.BottomContainerShowPositionFactor, 0.0f)), + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + _showBottomContainerAnimation.Play(); + } + + // First screen demo Application initialisation + private void OnInitialize(object source, AUIApplicationInitEventArgs e) + { + _stage = Stage.GetCurrent(); + _stageSize = _stage.GetSize(); +// _stage.SetBackgroundColor(NDalic.TRANSPARENT); + + _totalPostersContainers = Constants.TotalPostersContainers; + _imagePath = "./images/"; // Desktop +// _imagePath = "/home/owner/apps_rw/org.tizen.firstscreen/res/images/"; // Target + + _postersContainer = new List (); + _menuContainer = new ScrollContainer (); + + _hideBottomContainerAnimation = new Animation(0.25f); + _showBottomContainerAnimation = new Animation(0.25f); + + // Create a Top Container for poster items + _topContainer = new View(); + _topContainer.Size = new Vector3(_stageSize.width, _stageSize.height * Constants.TopContainerHeightFactor, 0.0f); + _topContainer.Position = new Vector3(0.0f, _stageSize.y * Constants.TopContainerPositionFactor, 0.0f); + _topContainer.ParentOrigin = NDalic.ParentOriginTopLeft; + _topContainer.AnchorPoint = NDalic.AnchorPointTopLeft; + + // Add a background to Top container + Property.Map visual = new Property.Map(); + visual.Insert(NDalic.VISUAL_PROPERTY_TYPE, new Property.Value((int)VisualType.IMAGE)); + visual.Insert(NDalic.IMAGE_VISUAL_URL, new Property.Value(_imagePath + "/background.png")); + _topContainer.Background = visual; + _topContainer.Name = "TopControl"; + + // Create a Bottom Container + _bottomContainer = new View(); + _bottomContainer.Size = new Vector3(_stageSize.width, _stageSize.height * Constants.BottomContainerHeightFactor, 0.0f); + _bottomContainer.Position = new Vector3(0.0f, _stageSize.height * Constants.BottomContainerHidePositionFactor, 0.0f); + _bottomContainer.ParentOrigin = NDalic.ParentOriginTopLeft; + _bottomContainer.AnchorPoint = NDalic.AnchorPointTopLeft; + + // Add a background to Bottom Container + visual = new Property.Map(); + visual.Insert(NDalic.VISUAL_PROPERTY_TYPE, new Property.Value((int)VisualType.IMAGE)); + visual.Insert(NDalic.IMAGE_VISUAL_URL, new Property.Value(_imagePath + "/background.png")); + _bottomContainer.Background = visual; + _bottomContainer.Name = "BottomControl"; + + // Add both Top and Bottom Containers to Stage + _stage.Add(_topContainer); + _stage.Add(_bottomContainer); + + // Add a clip layer to Top Container + _topClipLayer = new Layer(); + _topClipLayer.AnchorPoint = NDalic.AnchorPointBottomCenter; + _topClipLayer.ParentOrigin = NDalic.ParentOriginBottomCenter; + _topClipLayer.ClippingEnable = true; + _topClipLayer.ClippingBox = new RectInteger(0, + Convert.ToInt32(_stageSize.height * Constants.TopContainerPositionFactor), + Convert.ToInt32((_stageSize.width)), + Convert.ToInt32((_stageSize.height * Constants.TopClipLayerHeightFactor))); // X, Y, Width, Height + _topContainer.Add(_topClipLayer); + + // Create a SpotLight for items / images of both Poster and Menu ScrollContainers + ImageView spotLight = new ImageView(_imagePath + "/highlight_spot.png"); + spotLight.WidthResizePolicy = "USE_NATURAL_SIZE"; + spotLight.HeightResizePolicy = "USE_NATURAL_SIZE"; + spotLight.ParentOrigin = NDalic.ParentOriginCenter; + spotLight.AnchorPoint = NDalic.AnchorPointCenter; + spotLight.Name = "spotLight"; + + // Create a shadowBorder for items / images of Poster ScrollContainers + ImageView shadowBorder = new ImageView(_imagePath + "/thumbnail_shadow.9.png"); + shadowBorder.ParentOrigin = NDalic.ParentOriginCenter; + shadowBorder.AnchorPoint = NDalic.AnchorPointCenter; + shadowBorder.WidthResizePolicy = "SIZE_FIXED_OFFSET_FROM_PARENT"; + shadowBorder.HeightResizePolicy = "SIZE_FIXED_OFFSET_FROM_PARENT"; + shadowBorder.SetSizeModeFactor(new Vector3(32.0f, 41.0f, 0.0f)); + shadowBorder.Name = "poster shadowBorder"; + + // Create Poster Containers and add them to Top Clip layer + for (int i = 0; i < _totalPostersContainers; i++) + { + _postersContainer.Add(new ScrollContainer()); + _postersContainer[i].Container.Name = "poster" + i; + if (i == 0) + { + _postersContainer[i].ItemSize = new Vector3((_stageSize.width * Constants.Poster0ItemWidthFactor) - Constants.PostersContainerPadding, + _stageSize.height * Constants.PostersItemHeightFactor, 0.0f); + } + else + { + _postersContainer[i].ItemSize = new Vector3(_stageSize.width * Constants.Poster1ItemWidthFactor, + _stageSize.height * Constants.PostersItemHeightFactor, 0.0f); + } + _postersContainer[i].Padding = Constants.PostersContainerPadding; + _postersContainer[i].MarginX = Constants.PostersContainerMargin; + _postersContainer[i].OffsetY = Constants.PostersContainerOffsetYFactor; + _postersContainer[i].Width = _stageSize.width; + _postersContainer[i].Height = _stageSize.height * Constants.PostersContainerHeightFactor; + _postersContainer[i].ShadowBorder = shadowBorder; + _postersContainer[i].ShadowBorder.Position = new Vector3(0.0f, 4.0f, 0.0f); + _postersContainer[i].SpotLight = spotLight; + _topClipLayer.Add(_postersContainer[i].Container); + } + + // Add a clip layer to Bottom Container + _bottomClipLayer = new Layer(); + _bottomClipLayer.AnchorPoint = NDalic.AnchorPointBottomCenter; + _bottomClipLayer.ParentOrigin = NDalic.ParentOriginBottomCenter; + _bottomClipLayer.ClippingEnable = true; + _bottomClipLayer.ClippingBox = new RectInteger(Convert.ToInt32(Constants.LauncherWidth), + Convert.ToInt32(_stageSize.height * Constants.BottomContainerShowPositionFactor), + Convert.ToInt32((_stageSize.width)), + Convert.ToInt32((_stageSize.height - (_stageSize.height * Constants.BottomClipLayerHeightFactor)))); // X, Y, Width, Height + _bottomContainer.Add(_bottomClipLayer); + + // Add Launcher items to Bottom Container. Launcher is used to display three images on left of Menu ScrollContainer + launcherIcon = new ImageView[Convert.ToInt32(Constants.LauncherItemsCount)]; + for (int launcherIndex = 0; launcherIndex < Constants.LauncherItemsCount; launcherIndex++) + { + launcherIcon[launcherIndex] = new ImageView(_imagePath + "/" + launcherIndex + "-normal.png"); + launcherIcon[launcherIndex].Name = "launcherIcon" + launcherIndex; + launcherIcon[launcherIndex].WidthResizePolicy = "USE_NATURAL_SIZE"; + launcherIcon[launcherIndex].HeightResizePolicy = "USE_NATURAL_SIZE"; + launcherIcon[launcherIndex].ParentOrigin = NDalic.ParentOriginCenterLeft; + launcherIcon[launcherIndex].AnchorPoint = NDalic.AnchorPointCenterLeft; + launcherIcon[launcherIndex].Position = new Vector3(Constants.LauncherIconWidth * launcherIndex + Constants.LauncherLeftMargin, 0.0f, 0.0f); + _bottomContainer.Add(launcherIcon[launcherIndex]); + } + + // Add a shadow seperator image between last Launcher icon and Menu ScrollContainer + _launcherSeparator = new ImageView(_imagePath + "/eden_launcher_shadow_n.png"); + _launcherSeparator.Name = "launcherSeparator"; + _launcherSeparator.WidthResizePolicy = "USE_NATURAL_SIZE"; + _launcherSeparator.HeightResizePolicy = "FILL_TO_PARENT"; + _launcherSeparator.ParentOrigin = NDalic.ParentOriginCenterLeft; + _launcherSeparator.AnchorPoint = NDalic.AnchorPointCenterLeft; + _launcherSeparator.Position = new Vector3(Constants.LauncherIconWidth * Constants.LauncherItemsCount + Constants.LauncherLeftMargin, 0.0f, 0.0f); + _bottomContainer.Add(_launcherSeparator); + + // Create Menu Container and add it to Bottom Clip Layer + _menuItemSize = new Vector3((_stageSize.width * Constants.MenuItemWidthFactor) - Constants.MenuContainerPadding, + _stageSize.height * Constants.MenuItemHeightFactor, 0.0f); + _menuContainer.Container.Name = "menu"; + _menuContainer.ItemSize = _menuItemSize; + _menuContainer.Padding = Constants.MenuContainerPadding; + _menuContainer.MarginX = Constants.MenuContainerMargin; + _menuContainer.OffsetY = Constants.MenuContainerOffsetYFactor; + _menuContainer.OffsetX = Constants.LauncherWidth; + _menuContainer.Width = _stageSize.width - Constants.LauncherWidth; + _menuContainer.Height = _stageSize.height * Constants.MenuContainerHeightFactor; + _menuContainer.ShadowBorder = new ImageView(_imagePath + "/eden_launcher_shadow.9.png"); + _menuContainer.ShadowBorder.Name = "_menuContainer.ShadowBorder"; + _menuContainer.ShadowBorder.Size = new Vector3(_menuContainer.ItemSize.width + 40.0f, _menuContainer.ItemSize.height + 50.0f, 0.0f); + _menuContainer.ShadowBorder.Position = new Vector3(0.0f, 5.0f, 0.0f); + _menuContainer.ShadowBorder.ParentOrigin = NDalic.ParentOriginCenter; + _menuContainer.ShadowBorder.AnchorPoint = NDalic.AnchorPointCenter; + _menuContainer.SpotLight = spotLight; + _bottomClipLayer.Add(_menuContainer.Container); + + CreatePosters(); // Create Items for Poster ScrollContainer + CreateMenu(); // Create Items for Menu ScrollContainer + + // Initialize PreFocusChange event of KeyboardFocusManager + KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.Get(); + keyboardFocusManager.PreFocusChange += OnKeyboardPreFocusChangeSignal; + + _keyboardFocusIndicator = new ImageView(_imagePath + "/highlight_stroke.9.png"); + _keyboardFocusIndicator.ParentOrigin = NDalic.ParentOriginCenter; + _keyboardFocusIndicator.AnchorPoint = NDalic.AnchorPointCenter; + _keyboardFocusIndicator.WidthResizePolicy = "FILL_TO_PARENT"; + _keyboardFocusIndicator.HeightResizePolicy = "FILL_TO_PARENT"; + + keyboardFocusManager.SetFocusIndicatorActor(_keyboardFocusIndicator); + + _edenEffect = new EdenEffect(); + + // Move Fcous to Bottom Container (Menu ScrollContainer) + ShowBottomContainer(); + _menuContainer.SetFocused(true); + } + } +} + diff --git a/plugins/dali-swig/examples/firstscreen/Constants.cs b/plugins/dali-swig/examples/firstscreen/Constants.cs new file mode 100644 index 0000000..7ada417 --- /dev/null +++ b/plugins/dali-swig/examples/firstscreen/Constants.cs @@ -0,0 +1,43 @@ +using System; + +namespace FirstScreen +{ + public class Constants + { + public const int TotalPostersContainers = 2; // Number of Poster ScrollContainers to be added on Top Container + + public const float TopContainerHeightFactor = 0.38f; // Height Factor of stage height used for Top Container total height + public const float TopContainerPositionFactor = 0.50f; // Position Factor of stage height used for Top Container position + public const float TopClipLayerHeightFactor = 0.34f; // Height Factor of stage height used for Top Clip layer height + public const float TopClipLayerExpandHeightFactor = 0.36f; // Expanded Height Factor of stage height used for Top Clip layer height (used when Bottom container is hidden) + public const float PostersContainerHeightFactor = 0.32f; // Height Factor of stage height used for Poster ScrollContainers + public const float PostersContainerPadding = 2.0f; // Padding size used between items / images in Poster ScrollContainer + public const float PostersContainerMargin = 60.0f; // Extra margin Padding size used between items / images in Poster ScrollContainer when item / image is focused + public const float PostersContainerOffsetYFactor = 0.17f; // Position Factor of Poster item height used for Poster items / images position + + public const float BottomContainerHeightFactor = 0.16f; // Height Factor of stage height used for Bottom Container total height + public const float BottomContainerHidePositionFactor = 0.88f; // Position Factor of stage height used for Bottom Container position when bottom container is hidden (not focused) + public const float BottomContainerShowPositionFactor = 0.84f; // Position Factor of stage height used for Bottom Container position when bottom container is not hidden (focused) + public const float MenuContainerHeightFactor = 0.16f; // Height Factor of stage height used for Bottom ScrollContainers + public const float BottomClipLayerHeightFactor = 0.84f; // Height Factor of stage height used for Bottom Clip layer height + public const float MenuContainerPadding = 10.0f; // Padding size used between items / images in Menu ScrollContainer + public const float MenuContainerMargin = 25.0f; // Extra margin Padding size used between items / images in Menu ScrollContainer when item / image is focused + public const float MenuContainerOffsetYFactor = 0.35f; // Position Factor of Poster item height used for Menu items / images position + + public const float MenuItemWidthFactor = 0.125f; // Width Factor (1/8) of stage Width used for Menu items / images Width + public const float MenuItemHeightFactor = 0.10f; // Height Factor of stage height used for Menu items / images Height + public const float MenuItemsCount = 14; // Number of Menu items / images used in a Menu ScrollContainer + + public const float Poster0ItemWidthFactor = 0.25f; // Width Factor (1/4) of stage Width used for Poster items / images Width in a Poster ScrollContainer 0 + public const float Poster1ItemWidthFactor = 0.24f; // Width Factor of stage Width used for Poster items / images Width in a Poster ScrollContainer 1 + public const float PostersItemHeightFactor = 0.24f; // Height Factor of stage height used for Poster items / images Height + public const float PostersItemsCount = 24; // Number of Menu items / images used in a Poster ScrollContainer + + public const float LauncherWidth = 280.0f; // Width of Launcher. Launcher is used to display three images on left of Menu ScrollContainer + public const float LauncherLeftMargin = 40.0f; // Extra Spaces to the left of first Launcher item / image + public const float LauncherSeparatorWidth = 20.0f; // Extra area / space to the left of Menu ScrollContainer used for a speration shadow image + public const float LauncherItemsCount = 3.0f; // Total number of Launcher items / images + public const float LauncherIconWidth = (LauncherWidth - LauncherLeftMargin - LauncherSeparatorWidth) / LauncherItemsCount; // Width of each Launcher item / image + } +} + diff --git a/plugins/dali-swig/examples/firstscreen/EdenData.cs b/plugins/dali-swig/examples/firstscreen/EdenData.cs new file mode 100644 index 0000000..63e9dfd --- /dev/null +++ b/plugins/dali-swig/examples/firstscreen/EdenData.cs @@ -0,0 +1,106 @@ +using Dali; +using System; + +namespace FirstScreen +{ + public class EdenData + { + private string _name; // Name used for EdenData object (mainly to differentiate key frame animation ) + private string _imageName; // Image File Name (to be loaded from disk) used for ImageView used in key frame animation + private Vector3 _parentOrigin; // ParentOrigin applied to ImageView + private Vector3 _initSize; // InitSize used for key frame animation + private Vector3 _targetSize; // TargetSize used for key frame animation + private float _keyFrameStart; // KeyFrameStart used for key frame animation + private float _keyFrameEnd; // KeyFrameEnd used for key frame animation + private Direction _direction; // Direction used for key frame animation + private ImageView _imageFocus; // ImageView used in key frame animation + + // Initialize EdenData used for key frame animation + public EdenData(string name, string imageName, Direction direction, Vector3 parentOrigin, Vector3 initSize, + Vector3 targetSize, float keyFrameStart, float keyFrameEnd) + { + _name = name; + _imageName = imageName; + _parentOrigin = parentOrigin; + _initSize = initSize; + _targetSize = targetSize; + _keyFrameStart = keyFrameStart; + _keyFrameEnd = keyFrameEnd; + _direction = direction; + + _imageFocus = new ImageView("./images/edeneffect/" + _imageName); // Desktop +// _imageFocus = new ImageView("/home/owner/apps_rw/org.tizen.firstscreen/res/images/edeneffect/" + _imageName); // Target + + _imageFocus.ParentOrigin = _parentOrigin; + _imageFocus.AnchorPoint = NDalic.AnchorPointCenter; + _imageFocus.Name = _name; + } + + public enum Direction + { + Horizontal, + Vertical + }; + + public Direction EdenDirection + { + get {return _direction;} + set {_direction = value;} + } + + public string Name + { + get {return _name;} + set {_name = value;} + } + + public string ImageName + { + get {return _imageName;} + set {_imageName = value;} + } + + public Vector3 ParentOrigin + { + get + { + return _parentOrigin; + } + set + { + _parentOrigin = value; + _imageFocus.ParentOrigin = _parentOrigin; + } + } + + public Vector3 InitSize + { + get {return _initSize;} + set {_initSize = value;} + } + + public Vector3 TargetSize + { + get {return _targetSize;} + set {_targetSize = value;} + } + + public float KeyFrameStart + { + get {return _keyFrameStart;} + set {_keyFrameStart = value;} + } + + public float KeyFrameEnd + { + get {return _keyFrameEnd;} + set {_keyFrameEnd = value;} + } + + public ImageView ImageItem + { + get {return _imageFocus;} + } + } +} + diff --git a/plugins/dali-swig/examples/firstscreen/EdenEffect.cs b/plugins/dali-swig/examples/firstscreen/EdenEffect.cs new file mode 100644 index 0000000..6a84a09 --- /dev/null +++ b/plugins/dali-swig/examples/firstscreen/EdenEffect.cs @@ -0,0 +1,203 @@ +using Dali; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace FirstScreen +{ + public class EdenEffect : IEdenEffect + { + private float _frameThickness; + private EdenData[] _edenFocusData; // Each EdenData is used for one key frame animation (total 6 key frame animations needed for EddenEffect) + private Animation _animation; // Animation used to apply all six key frame animations + + public EdenEffect() + { + _frameThickness = 10.0f; + float _bottomFrameTime = 0.6f; // complete the halo/bottom animation 60% of the way through + float _sideFrameTime = 0.8f; // Start the side frame animation after the bottom animation and complete at 80% of the way through + float _topFrameTime = 1.0f; // start the top frame animation after the side frame animation and complete at 100% way through + + // Six key frame animations (EdenData objects) needed for EddenEffect + // Two key frame animations for top horizontal effect + // Two key frame animations for bottom horizontal effect + // Two key frame animations for vertical horizontal effect + _edenFocusData = new EdenData[6]; + + EdenData edenData = new EdenData("halo", "halo.png", EdenData.Direction.Horizontal, NDalic.ParentOriginTopCenter, + new Vector3(50,20,0), new Vector3(0.0f, 100.0f , 0.0f), 0.0f, _bottomFrameTime); + _edenFocusData[0] = edenData; + + edenData = new EdenData("bottom", "horizontalFrame.png", EdenData.Direction.Horizontal, NDalic.ParentOriginTopCenter, + new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, _frameThickness, 0.0f), 0.0f, _bottomFrameTime); + _edenFocusData[1] = edenData; + + edenData = new EdenData("left", "verticalFrame.png", EdenData.Direction.Vertical, NDalic.ParentOriginBottomLeft, + new Vector3(0.0f, 0.0f, 0.0f), new Vector3(_frameThickness, 0.0f, 0.0f), _bottomFrameTime, _sideFrameTime); + _edenFocusData[2] = edenData; + + edenData = new EdenData("right", "verticalFrame.png", EdenData.Direction.Vertical, NDalic.ParentOriginBottomRight, + new Vector3(0.0f, 0.0f, 0.0f), new Vector3(_frameThickness, 0.0f, 0.0f), _bottomFrameTime, _sideFrameTime); + _edenFocusData[3] = edenData; + + edenData = new EdenData("top-left", "horizontalFrame.png", EdenData.Direction.Horizontal, NDalic.ParentOriginBottomLeft, + new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f ,_frameThickness, 0.0f), _sideFrameTime, _topFrameTime); + _edenFocusData[4] = edenData; + + edenData = new EdenData("top-right", "horizontalFrame.png", EdenData.Direction.Horizontal, NDalic.ParentOriginBottomRight, + new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, _frameThickness, 0.0f), _sideFrameTime, _topFrameTime); + _edenFocusData[5] = edenData; + } + + public void FocusAnimation(View parentItem, Vector3 itemSize, float duration, EdenEffectDirection direction) + { + var itemWidth = itemSize.x + _frameThickness / 2; + var itemHeight = itemSize.y + _frameThickness / 3; + + if (_animation) + { + _animation.Clear(); + _animation.Reset(); + } + _animation = new Animation(duration); + + if (direction == EdenEffectDirection.BottomToTop) + { + _edenFocusData[0].ParentOrigin = NDalic.ParentOriginBottomCenter; + _edenFocusData[1].ParentOrigin = NDalic.ParentOriginBottomCenter; + _edenFocusData[2].ParentOrigin = NDalic.ParentOriginBottomLeft; + _edenFocusData[3].ParentOrigin = NDalic.ParentOriginBottomRight; + _edenFocusData[4].ParentOrigin = NDalic.ParentOriginTopLeft; + _edenFocusData[5].ParentOrigin = NDalic.ParentOriginTopRight; + } + else + { + _edenFocusData[0].ParentOrigin = NDalic.ParentOriginTopCenter; + _edenFocusData[1].ParentOrigin = NDalic.ParentOriginTopCenter; + _edenFocusData[2].ParentOrigin = NDalic.ParentOriginBottomLeft; + _edenFocusData[3].ParentOrigin = NDalic.ParentOriginBottomRight; + _edenFocusData[4].ParentOrigin = NDalic.ParentOriginBottomLeft; + _edenFocusData[5].ParentOrigin = NDalic.ParentOriginBottomRight; + } + + foreach (EdenData edenData in _edenFocusData) + { + var currentParent = edenData.ImageItem.GetParent(); + + // first parent the controls + if (parentItem != currentParent) + { + parentItem.Add(edenData.ImageItem); + } + + edenData.ImageItem.Size = new Vector3(100.0f,100.0f, 0.0f); + parentItem.Add(edenData.ImageItem); + + Vector3 targetSize = edenData.TargetSize; + Vector3 initSize = edenData.InitSize; + + if (edenData.EdenDirection == EdenData.Direction.Horizontal) + { + // adjust the width to match the parent + targetSize.x = itemWidth; + } + else // vertical frame + { + // adjust the height to match the parent + targetSize.y = itemHeight; + } + + // half the size for the top frame as we come out from both left / right sides + if (edenData.Name == "top-right" || edenData.Name == "top-left") + { + targetSize.x = itemWidth - _frameThickness; + } + + KeyFrames keyFrames = new KeyFrames(); + + keyFrames.Add(0.0f, new Property.Value(initSize)); + keyFrames.Add(edenData.KeyFrameStart, new Property.Value(initSize)); + keyFrames.Add(edenData.KeyFrameEnd, new Property.Value(targetSize)); + + // for halo add an extra keyframe to shrink it ( in 20% of time after it has finished) + if (edenData.Name =="halo") + { + keyFrames.Add(edenData.KeyFrameEnd + 0.2f, new Property.Value(initSize)); + } + + _animation.AnimateBetween(new Property(edenData.ImageItem, Actor.Property.SIZE), keyFrames, + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + + // Simulate the vertical frame growing from the top. + // Vertical items are anchored to the bottom of the parent... so when they grow + // we need to move them to the middle of the parent ( otherwise they stick out the bottom) + if (edenData.EdenDirection == EdenData.Direction.Vertical) + { + //animate position as well so it looks like animation is coming from bottom + KeyFrames keyFramesV = new KeyFrames(); + + if (direction == EdenEffectDirection.BottomToTop) + { + keyFramesV.Add(0.0f, new Property.Value(0.0f)); + keyFramesV.Add(edenData.KeyFrameStart, new Property.Value(0.0f)); + } + else + { + keyFramesV.Add(0.0f, new Property.Value(-itemHeight)); + keyFramesV.Add(edenData.KeyFrameStart, new Property.Value(-itemHeight)); + } + + keyFramesV.Add(edenData.KeyFrameEnd, new Property.Value(-itemHeight / 2)); // animate to halfway up the control + + _animation.AnimateBetween(new Property(edenData.ImageItem, Actor.Property.POSITION_Y), keyFramesV, + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + } + + // Simulate the top frame growing from the sides. + if (edenData.Name == "top-left") + { + KeyFrames keyFramesTL = new KeyFrames(); + + keyFramesTL.Add(0.0f, new Property.Value(0.0f)); + keyFramesTL.Add(edenData.KeyFrameStart, new Property.Value(0.0f)); + keyFramesTL.Add(edenData.KeyFrameEnd, new Property.Value(itemWidth / 2)); // animate to halfway up the control + + // grow these from the left or right + _animation.AnimateBetween(new Property(edenData.ImageItem, Actor.Property.POSITION_X), keyFramesTL, + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + } + + if (edenData.Name == "top-right") + { + KeyFrames keyFramesTR = new KeyFrames(); + + keyFramesTR.Add(0.0f, new Property.Value(0.0f)); + keyFramesTR.Add(edenData.KeyFrameStart, new Property.Value(0.0f)); + keyFramesTR.Add(edenData.KeyFrameEnd, new Property.Value(-itemWidth / 2)); // animate to halfway up the control + + // grow these from the left or right + _animation.AnimateBetween(new Property(edenData.ImageItem, Actor.Property.POSITION_X), keyFramesTR, + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + } + + _animation.Finished += OnAnimationFinished; + + _animation.Play(); + } + } + + private void OnAnimationFinished(object source, Animation.FinishedEventArgs e) + { + foreach (EdenData edenData in _edenFocusData) + { + var currentParent = edenData.ImageItem.GetParent(); + + if (currentParent) + { + currentParent.Remove(edenData.ImageItem); + } + } + } + } +} + diff --git a/plugins/dali-swig/examples/firstscreen/IEdenEffect.cs b/plugins/dali-swig/examples/firstscreen/IEdenEffect.cs new file mode 100644 index 0000000..88ca3b8 --- /dev/null +++ b/plugins/dali-swig/examples/firstscreen/IEdenEffect.cs @@ -0,0 +1,17 @@ +using Dali; +using System; + +namespace FirstScreen +{ + public enum EdenEffectDirection + { + TopToBottom, + BottomToTop + }; + + public interface IEdenEffect + { + void FocusAnimation(View parentItem, Vector3 itemSize, float duration, EdenEffectDirection direction); + } +} + diff --git a/plugins/dali-swig/examples/firstscreen/Program.cs b/plugins/dali-swig/examples/firstscreen/Program.cs new file mode 100644 index 0000000..d33c1f6 --- /dev/null +++ b/plugins/dali-swig/examples/firstscreen/Program.cs @@ -0,0 +1,14 @@ +using System; + +namespace FirstScreen +{ + public class MainClass + { + [STAThread] + static void Main(string[] args) + { + FirstScreenApp.Run(); + } + } +} + diff --git a/plugins/dali-swig/examples/firstscreen/ScrollContainer.cs b/plugins/dali-swig/examples/firstscreen/ScrollContainer.cs new file mode 100644 index 0000000..c22c712 --- /dev/null +++ b/plugins/dali-swig/examples/firstscreen/ScrollContainer.cs @@ -0,0 +1,744 @@ +using Dali; +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; + + +namespace FirstScreen +{ + public class ScrollContainer + { + private View _container; + private Actor _itemRoot; + private Vector3 _itemSize; + private List _itemList; + private int _itemCount; + private int _focusedItem; + private PanGestureDetector _panGestureDetector; + private float _scrollDisplacement; + private float _currentScrollPosition; + private float _padding; + private float _width; + private float _height; + private bool _isFocused; + private float _marginX; + private float _marginY; + private float _offsetY; + private float _offsetX; + private Stage _stage; + private Vector2 _stageSize; + private ImageView _shadowBorder; + private ImageView _spotLight; + private Animation _spotLightAnimation; + private Animation _showAnimation; + private Animation _hideAnimation; + private Animation _focusAnimation; + private Animation _scrollAnimation; + private Animation _focusTransitionAnimation; + private Path _circularPath; + private bool _shouldHide; + + public ScrollContainer() + { + _itemSize = new Vector3(0.0f, 0.0f, 0.0f); + _padding = 0.0f; + _width = 0.0f; + _height = 0.0f; + _currentScrollPosition = 0.0f; + _itemCount = 0; + _focusedItem = -1; + _isFocused = false; + _marginX = 50.0f; + _marginY = 0.0f; + _offsetY = 0.0f; + _offsetX = 0.0f; + + _shouldHide = true; + + _container = new View(); + _itemRoot = new Actor(); + _container.Add(_itemRoot); + + _itemList = new List(); + + if (_panGestureDetector == null) + { + _panGestureDetector = new PanGestureDetector(); + _panGestureDetector.Attach(_container); + + _panGestureDetector.Detected += OnPan; + } + + _container.ParentOrigin = NDalic.ParentOriginTopLeft; + _container.AnchorPoint = NDalic.AnchorPointTopLeft; + _itemRoot.ParentOrigin = NDalic.ParentOriginTopLeft; + _itemRoot.AnchorPoint = NDalic.AnchorPointTopLeft; + + _container.WidthResizePolicy = "FILL_TO_PARENT"; + _container.HeightResizePolicy = "FILL_TO_PARENT"; + _itemRoot.WidthResizePolicy = "FILL_TO_PARENT"; + _itemRoot.HeightResizePolicy = "FILL_TO_PARENT"; + + _stage = Stage.GetCurrent(); + _stageSize = _stage.GetSize(); + + _spotLightAnimation = new Animation(5.0f); + _focusTransitionAnimation = new Animation (0.35f); + _focusAnimation = new Animation (0.35f); + _focusAnimation.SetEndAction(Animation.EndAction.BakeFinal); + _scrollAnimation = new Animation (0.35f); + _scrollAnimation.SetEndAction(Animation.EndAction.BakeFinal); + } + + public bool IsFocused + { + get + { + return _isFocused; + } + } + + public Dali.View Container + { + get + { + return _container; + } + } + + public int ItemCount + { + get + { + return _itemCount; + } + } + + public Actor ItemRoot + { + get + { + return _itemRoot; + } + } + + public Vector3 ItemSize + { + get + { + return _itemSize; + } + + set + { + _itemSize = value; + + Vector3 topLeft = new Vector3(-0.25f * _itemSize.width, -0.25f * _itemSize.height, 0.0f); + Vector3 topRight = new Vector3(0.25f * _itemSize.width, -0.25f * _itemSize.height, 0.0f); + Vector3 bottomRight = new Vector3(0.25f * _itemSize.width, 0.25f * _itemSize.height, 0.0f); + Vector3 bottomLeft = new Vector3(-0.25f * _itemSize.width, 0.25f * _itemSize.height, 0.0f); + + _circularPath = new Path(); + _circularPath.AddPoint(topLeft); + _circularPath.AddPoint(topRight); + _circularPath.AddPoint(bottomRight); + _circularPath.AddPoint(bottomLeft); + _circularPath.AddPoint(topLeft); + _circularPath.GenerateControlPoints(0.5f); + } + } + + public float Padding + { + get + { + return _padding; + } + + set + { + _padding = value; + } + } + + public float MarginX + { + get + { + return _marginX; + } + + set + { + _marginX = value; + } + } + + public float OffsetY + { + get + { + return _offsetY; + } + + set + { + _offsetY = value; + } + } + + public float OffsetX + { + get + { + return _offsetX; + } + + set + { + _offsetX = value; + } + } + + public float MarginY + { + get + { + return _marginY; + } + + set + { + _marginY = value; + } + } + + public float Width + { + get + { + return _width; + } + + set + { + _width = value; + } + } + + public float Height + { + get + { + return _height; + } + + set + { + _height = value; + } + } + + public ImageView ShadowBorder + { + get + { + return _shadowBorder; + } + + set + { + _shadowBorder = value; + } + } + + public ImageView SpotLight + { + get + { + return _spotLight; + } + + set + { + _spotLight = value; + } + } + + public int FocusedItemID + { + get + { + if (_focusedItem < 0) + { + _focusedItem = 0; + } + + return _focusedItem; + } + } + + public Actor GetCurrentFocusedActor() + { + if (_focusedItem < 0) + { + _focusedItem = 0; + } + + return _itemList[_focusedItem]; + } + + public void AddItem(View item) + { + item.AnchorPoint = NDalic.AnchorPointBottomCenter; + item.ParentOrigin = NDalic.ParentOriginBottomCenter; + + item.Size = _itemSize; + item.SetKeyboardFocusable(true); + item.Position = GetItemPosition(_itemCount, _currentScrollPosition); + + item.Name = _itemCount.ToString(); + +// item.ClippingMode = "CLIP_CHILDREN"; + + _itemRoot.Add(item); + _itemList.Add(item); + _panGestureDetector.Attach(item); + _itemCount++; + } + + // Perform Show animation on ScrollContainer (used only for Poster Container) + public void Show() + { + Container.Add(ItemRoot); + + _shouldHide = false; + _showAnimation = new Animation (0.35f); + + _showAnimation.AnimateTo(new Property(_container, Actor.Property.COLOR_ALPHA), new Property.Value(1.0f)); + + _container.PositionY = _container.Position.y + 200.0f; + float targetPositionY = _container.Position.y - 200.0f; + _showAnimation.AnimateTo(new Property(_container, Actor.Property.POSITION_Y), new Property.Value(targetPositionY), + new AlphaFunction(AlphaFunction.BuiltinFunction.LINEAR)); + + _showAnimation.Play(); + } + + // Perform Hide animation on ScrollContainer (used only for Poster Container) + public void Hide() + { + if (_hideAnimation) + { + _hideAnimation.Clear(); + _hideAnimation.Reset(); + } + + float duration = 0.35f; + _hideAnimation = new Animation(duration); + + _hideAnimation.AnimateTo(new Property(_container, Actor.Property.COLOR_ALPHA), new Property.Value(0.0f), + new AlphaFunction(AlphaFunction.BuiltinFunction.LINEAR), new TimePeriod(0.0f, duration * 0.75f)); + + _hideAnimation.Finished += OnHideAnimationFinished; + + _shouldHide = true; + _hideAnimation.Play(); + } + + public View Focus(int itemId) + { + if (itemId < 0) + { + itemId = 0; + } + else if (itemId >= _itemList.Count) + { + itemId = _itemList.Count - 1; + } + + _itemList[itemId].Add(_shadowBorder); + _itemList[itemId].Add(_spotLight); + + // Perform Spot Light animation + if(_focusedItem != itemId && _spotLight != null) + { + _spotLightAnimation.Clear(); + _spotLightAnimation.Animate( _spotLight, _circularPath, new Vector3(0.0f, 0.0f, 0.0f) ); + _spotLightAnimation.SetLooping(true); + _spotLightAnimation.Play(); + } + + _focusedItem = itemId; + + Vector3 itemPosition = GetItemPosition(_focusedItem, _currentScrollPosition); + + _focusAnimation.Clear(); + + float relativeItemPositionX = itemPosition.x - _itemSize.width * 0.5f + (_stageSize.width * 0.5f) + _offsetX; + if (relativeItemPositionX < _marginX + _offsetX + _padding) + { + float amount = _marginX + _offsetX + _padding - relativeItemPositionX; + Scroll(amount, itemId + 1); // Perform Scroll animation + } + else if (relativeItemPositionX + _itemSize.width + _padding + _marginX > _stageSize.width) + { + float amount = relativeItemPositionX + _marginX + _padding + _itemSize.width - _stageSize.width; + Scroll(-amount, itemId - 1); // Perform Scroll animation + } + else + { + for (int i = 0; i < _itemList.Count; ++i) + { + Vector3 targetPosition = GetItemPosition(i, _currentScrollPosition); + _focusAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.POSITION), + new Property.Value(targetPosition), + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + } + } + + for (int i = 0; i < _itemList.Count; ++i) + { + SetupItemRenderer(_itemList[i], false); + + // Perform Focus animation + if (i == _focusedItem) + { + _focusAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.SCALE), + new Property.Value(new Vector3(1.2f, 1.2f, 1.2f)), + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + } + else + { + _focusAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.SCALE), + new Property.Value(new Vector3(1.0f, 1.0f, 1.0f)), + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + } + } + + _focusAnimation.Play(); + + if (_isFocused && _focusedItem >= 0) + { + SetupItemRenderer(_itemList[_focusedItem], true); + SetupSpotLightRenderer(); + } + + return _itemList[_focusedItem]; + } + + // Perform EddenEffect animation on Focused Item specified + public void FocusAnimation(EdenEffect edenEffect, EdenEffectDirection direction) + { + edenEffect.FocusAnimation(_itemList[_focusedItem], _itemSize, 1.0f, direction); + } + + public void SetFocused(bool focused) + { + _isFocused = focused; + + // Perform Focus animation if the ScrollContainer is not focused already + if (!_isFocused) + { + Actor parent = _shadowBorder.GetParent(); + if (parent) + { + parent.Remove(_shadowBorder); + } + + parent = _spotLight.GetParent(); + if (parent) + { + parent.Remove(_spotLight); + } + + _focusTransitionAnimation.Clear(); + + for (int i = 0; i < _itemList.Count; ++i) + { + SetupItemRenderer(_itemList[i], false); + + Vector3 targetPosition = GetItemPosition(i, _currentScrollPosition); + _focusTransitionAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.POSITION), + new Property.Value(targetPosition), + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + + _focusTransitionAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.SCALE), + new Property.Value(new Vector3(1.0f, 1.0f, 1.0f)), + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + } + + _focusTransitionAnimation.Play(); + } + else + { + Focus(_focusedItem); + } + } + + // Obtain ID of first visible item/image on the screen of the ScrollContainer + public int GetFirstVisibleItemId() + { + int firstItemId = -1; + + if (_isFocused) + { + firstItemId = (int)Math.Floor((-1.0 * _currentScrollPosition + _marginX * 2.0f) / (_itemSize.x + _padding)); + } + else + { + firstItemId = (int)Math.Floor(-1.0 * _currentScrollPosition / (_itemSize.x + _padding)); + } + + if (firstItemId < 0) + { + firstItemId = 0; + } + + return firstItemId; + } + + // Obtain ID of last visible item/image on the screen of the ScrollContainer + public int GetLastVisibleItemId() + { + int lastItemId = -1; + + if (_isFocused) + { + lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition - _marginX * 2.0f) / _itemSize.x) - 1); + } + else + { + lastItemId = (int)Math.Ceiling(((_width - _currentScrollPosition) / _itemSize.x) - 1); + } + + if (lastItemId >= _itemList.Count) + { + + lastItemId = _itemList.Count - 1; + } + + return lastItemId; + } + + // Obtain Next item/image (Right of the currently focused item) of the ScrollContainer + public Actor FocusNext() + { + int nextItem = -1; + + if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId()) + { + nextItem = GetFirstVisibleItemId(); + } + else + { + nextItem = _focusedItem + 1; + } + + return Focus(nextItem); + } + + // Obtain Previous item/image (left of the currently focused item) of the ScrollContainer + public Actor FocusPrevious() + { + int previousItem = -1; + + if (_focusedItem < GetFirstVisibleItemId() || _focusedItem > GetLastVisibleItemId()) + { + previousItem = GetFirstVisibleItemId(); + } + else + { + previousItem = _focusedItem - 1; + } + + return Focus(previousItem); + } + + private void OnHideAnimationFinished(object source, Animation.FinishedEventArgs e) + { + var currentParent = ItemRoot.GetParent(); + if (_shouldHide && currentParent != null) + { + Container.Remove(ItemRoot); + } + } + + private void OnPan(object source, PanGestureDetector.DetectedEventArgs e) + { + switch (e.PanGesture.state) + { + case Gesture.State.Started: + _scrollDisplacement = 0.0f; + break; + + case Gesture.State.Continuing: + _scrollDisplacement = e.PanGesture.displacement.x; + break; + + case Gesture.State.Finished: + case Gesture.State.Cancelled: + float absScrollDistance = _scrollDisplacement; + if (absScrollDistance < 0.0f) + absScrollDistance = 0.0f - absScrollDistance; + + float scrollSpeed = e.PanGesture.velocity.x * e.PanGesture.velocity.x + e.PanGesture.velocity.y * e.PanGesture.velocity.y; + float maxScrollSpeed = 40.0f; // TBD + if (scrollSpeed > maxScrollSpeed) + scrollSpeed = maxScrollSpeed; + + if (absScrollDistance > 1.0f && scrollSpeed > 0.05f) // Threshold TBD + { + if (_scrollDisplacement > 0.0f) // scroll constant distance in constant speed. + { + Scroll((_itemSize.x + _padding) * 2, GetFirstVisibleItemId()); + } + else + { + Scroll(-(_itemSize.x + _padding) * 2, GetFirstVisibleItemId()); + } + } + break; + } + } + + // Perform ScrollAnimation on each item + private void Scroll(float amount, int baseItem) + { + float tagetScrollPosition = _currentScrollPosition + amount; + float totalItemSize = _itemList.Count * (_itemSize.width + _padding) + _padding + (_marginX * 2.0f); + + float maxScrollPosition = _width - totalItemSize; + + if (tagetScrollPosition < maxScrollPosition) + { + tagetScrollPosition = maxScrollPosition; + } + if (tagetScrollPosition > 0.0f) + { + tagetScrollPosition = 0.0f; + } + + _scrollAnimation.Clear(); + + for (int i = 0; i < _itemList.Count; ++i) + { + Vector3 targetPosition = GetItemPosition(i, tagetScrollPosition); + _scrollAnimation.AnimateTo(new Property(_itemList[i], Actor.Property.POSITION), + new Property.Value(targetPosition), + new AlphaFunction(AlphaFunction.BuiltinFunction.EASE_OUT_SINE)); + } + + _currentScrollPosition = tagetScrollPosition; + _scrollAnimation.Play(); + } + + // Calculate Position of any item/image of ScrollContainer + private Vector3 GetItemPosition(int itemId, float scrollPosition) + { + if (_isFocused) + { + // used (_itemSize.width * 0.5f) because of AnchorPointCenter + // used (_stageSize.width * 0.5f) because of ParentOriginCenter + if (_focusedItem > itemId) + { + float positionX = (_itemSize.width * itemId) + (_padding * (itemId + 1)) + scrollPosition + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f); + return new Vector3(positionX, -_itemSize.height * _offsetY, 0.0f); + } + else if (_focusedItem == itemId) + { + float positionX = (_itemSize.width * itemId) + (_padding * (itemId + 1)) + scrollPosition + _marginX + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f); + return new Vector3(positionX, -_itemSize.height * _offsetY, 0.0f); + } + else + { + float positionX = (_itemSize.width * itemId) + (_padding * (itemId + 1)) + scrollPosition + _marginX * 2.0f + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f); + return new Vector3(positionX, -_itemSize.height * _offsetY, 0.0f); + } + } + else + { + float positionX = (_itemSize.width * itemId) + (_padding * (itemId + 1)) + scrollPosition + (_itemSize.width * 0.5f) - (_stageSize.width * 0.5f); + return new Vector3(positionX, -_itemSize.height * _offsetY, 0.0f); + } + } + + // Used for SpotLight animation with clipping + private void SetupItemRenderer(Actor actor, bool stencilOn) + { + if (actor) + { + Renderer renderer = actor.GetRendererAt(0); + + if (renderer) + { + // Setup the renderer properties: + // The stencil plane is only for stencilling, so disable writing to color buffer. + + // Enable stencil. Draw to the stencil buffer (only). + if (stencilOn) + { + renderer.RenderMode = (int)RenderModeType.COLOR_STENCIL; + } + else + { + renderer.RenderMode = (int)RenderModeType.COLOR; + } + renderer.StencilFunction = (int)StencilFunctionType.ALWAYS; + renderer.StencilFunctionReference = 1; + renderer.StencilFunctionMask = 0xFF; + renderer.StencilOperationOnFail = (int)StencilOperationType.KEEP; + renderer.StencilOperationOnZFail = (int)StencilOperationType.KEEP; + renderer.StencilOperationOnZPass = (int)StencilOperationType.REPLACE; + renderer.StencilMask = 0xFF; + + // We don't want to write to the depth buffer. + renderer.DepthWriteMode = (int)DepthWriteModeType.OFF; + // We don't beed to test the depth buffer. + renderer.DepthTestMode = (int)DepthTestModeType.OFF; + + // This object must be rendered 1st. + renderer.DepthIndex = 10; + } + } + } + + // Used for SpotLight animation with clipping + private void SetupSpotLightRenderer() + { + if (_spotLight) + { + Renderer renderer = _spotLight.GetRendererAt(0); + + if (renderer) + { + // Setup the renderer properties: + // Write to color buffer so soptlight is visible + + // We use blending to blend the spotlight with the poster image. + renderer.BlendMode = (int)BlendModeType.ON; + renderer.BlendEquationRgb = (int)BlendEquationType.ADD; + renderer.BlendEquationAlpha = (int)BlendEquationType.ADD; + renderer.BlendFactorDestRgb = (int)BlendFactorType.ONE; + + // Enable stencil. Here we only draw to areas within the stencil. + renderer.RenderMode = (int)RenderModeType.COLOR_STENCIL; + renderer.StencilFunction = (int)StencilFunctionType.EQUAL; + renderer.StencilFunctionReference = 1; + renderer.StencilFunctionMask = 0xFF; + // Don't write to the stencil. + renderer.StencilMask = 0x00; + + // We don't need to write to the depth buffer. + renderer.DepthWriteMode = (int)DepthWriteModeType.OFF; + // We don't need to test the depth buffer. + renderer.DepthTestMode = (int)DepthTestModeType.OFF; + + // This object must be rendered last. + renderer.DepthIndex = 20; + } + } + } + } +} + diff --git a/plugins/dali-swig/examples/firstscreen/images/0-normal.png b/plugins/dali-swig/examples/firstscreen/images/0-normal.png new file mode 100644 index 0000000..ee755c3 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/0-normal.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/1-normal.png b/plugins/dali-swig/examples/firstscreen/images/1-normal.png new file mode 100644 index 0000000..432bf7f Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/1-normal.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/2-normal.png b/plugins/dali-swig/examples/firstscreen/images/2-normal.png new file mode 100644 index 0000000..c921918 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/2-normal.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/background.png b/plugins/dali-swig/examples/firstscreen/images/background.png new file mode 100644 index 0000000..7e4caad Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/background.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/eden_launcher_shadow.9.png b/plugins/dali-swig/examples/firstscreen/images/eden_launcher_shadow.9.png new file mode 100644 index 0000000..f989071 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/eden_launcher_shadow.9.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/eden_launcher_shadow_n.png b/plugins/dali-swig/examples/firstscreen/images/eden_launcher_shadow_n.png new file mode 100644 index 0000000..0805e9e Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/eden_launcher_shadow_n.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/edeneffect/halo.png b/plugins/dali-swig/examples/firstscreen/images/edeneffect/halo.png new file mode 100644 index 0000000..307f67e Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/edeneffect/halo.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/edeneffect/horizontalFrame.png b/plugins/dali-swig/examples/firstscreen/images/edeneffect/horizontalFrame.png new file mode 100644 index 0000000..abff4ec Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/edeneffect/horizontalFrame.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/edeneffect/verticalFrame.png b/plugins/dali-swig/examples/firstscreen/images/edeneffect/verticalFrame.png new file mode 100644 index 0000000..bdd372d Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/edeneffect/verticalFrame.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/focus_grid.9.png b/plugins/dali-swig/examples/firstscreen/images/focus_grid.9.png new file mode 100644 index 0000000..04ccb1f Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/focus_grid.9.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/highlight_spot.png b/plugins/dali-swig/examples/firstscreen/images/highlight_spot.png new file mode 100644 index 0000000..8caa716 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/highlight_spot.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/highlight_stroke.9.png b/plugins/dali-swig/examples/firstscreen/images/highlight_stroke.9.png new file mode 100644 index 0000000..493b206 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/highlight_stroke.9.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/menu/0.png b/plugins/dali-swig/examples/firstscreen/images/menu/0.png new file mode 100644 index 0000000..cf1135c Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/menu/0.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/menu/1.png b/plugins/dali-swig/examples/firstscreen/images/menu/1.png new file mode 100644 index 0000000..16d48e7 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/menu/1.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/menu/2.png b/plugins/dali-swig/examples/firstscreen/images/menu/2.png new file mode 100644 index 0000000..bf7f1e8 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/menu/2.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/menu/3.png b/plugins/dali-swig/examples/firstscreen/images/menu/3.png new file mode 100644 index 0000000..ba40892 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/menu/3.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/menu/4.png b/plugins/dali-swig/examples/firstscreen/images/menu/4.png new file mode 100644 index 0000000..ad580d8 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/menu/4.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/menu/5.png b/plugins/dali-swig/examples/firstscreen/images/menu/5.png new file mode 100644 index 0000000..599147c Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/menu/5.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/menu/6.png b/plugins/dali-swig/examples/firstscreen/images/menu/6.png new file mode 100644 index 0000000..5f215f6 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/menu/6.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/0.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/0.jpg new file mode 100644 index 0000000..5b234db Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/0.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/1.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/1.jpg new file mode 100644 index 0000000..f999f55 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/1.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/10.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/10.jpg new file mode 100644 index 0000000..e8be482 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/10.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/11.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/11.jpg new file mode 100644 index 0000000..2b97815 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/11.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/12.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/12.jpg new file mode 100644 index 0000000..8b7bda9 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/12.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/13.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/13.jpg new file mode 100644 index 0000000..ba8d61a Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/13.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/2.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/2.jpg new file mode 100644 index 0000000..dba62e1 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/2.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/3.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/3.jpg new file mode 100644 index 0000000..bd74752 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/3.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/4.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/4.jpg new file mode 100644 index 0000000..13581f8 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/4.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/5.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/5.jpg new file mode 100644 index 0000000..7526f22 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/5.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/6.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/6.jpg new file mode 100644 index 0000000..3882771 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/6.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/7.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/7.jpg new file mode 100644 index 0000000..7a0844b Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/7.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/8.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/8.jpg new file mode 100644 index 0000000..4798052 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/8.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster0/9.jpg b/plugins/dali-swig/examples/firstscreen/images/poster0/9.jpg new file mode 100644 index 0000000..5f160b3 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster0/9.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster1/0.jpg b/plugins/dali-swig/examples/firstscreen/images/poster1/0.jpg new file mode 100644 index 0000000..1d4b86b Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster1/0.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster1/1.jpg b/plugins/dali-swig/examples/firstscreen/images/poster1/1.jpg new file mode 100644 index 0000000..f95670d Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster1/1.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster1/2.jpg b/plugins/dali-swig/examples/firstscreen/images/poster1/2.jpg new file mode 100644 index 0000000..f4c0246 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster1/2.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster1/3.jpg b/plugins/dali-swig/examples/firstscreen/images/poster1/3.jpg new file mode 100644 index 0000000..49acd6a Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster1/3.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster1/4.jpg b/plugins/dali-swig/examples/firstscreen/images/poster1/4.jpg new file mode 100644 index 0000000..cb11761 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster1/4.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/poster1/5.jpg b/plugins/dali-swig/examples/firstscreen/images/poster1/5.jpg new file mode 100644 index 0000000..eba0c14 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/poster1/5.jpg differ diff --git a/plugins/dali-swig/examples/firstscreen/images/star-dim.png b/plugins/dali-swig/examples/firstscreen/images/star-dim.png new file mode 100644 index 0000000..38cc674 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/star-dim.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/star-highlight.png b/plugins/dali-swig/examples/firstscreen/images/star-highlight.png new file mode 100644 index 0000000..f99ee25 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/star-highlight.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/thumbnail_shadow.9.png b/plugins/dali-swig/examples/firstscreen/images/thumbnail_shadow.9.png new file mode 100644 index 0000000..61f5a99 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/thumbnail_shadow.9.png differ diff --git a/plugins/dali-swig/examples/firstscreen/images/white-pixel.png b/plugins/dali-swig/examples/firstscreen/images/white-pixel.png new file mode 100644 index 0000000..c63f333 Binary files /dev/null and b/plugins/dali-swig/examples/firstscreen/images/white-pixel.png differ