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)
#include <stdlib.h>
#include <limits>
+#include <unistd.h>
#include <dali-toolkit-test-suite-utils.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
+#include <dali-toolkit/internal/text/text-scroller-data.h>
using namespace Dali;
using namespace Toolkit;
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()
ToolkitTestApplication application;
// Creates a text controller.
- ControlImpl controlImpl;
- ControllerPtr controller = Controller::New( controlImpl );
+ ControllerPtr controller = Controller::New();
DALI_TEST_CHECK( controller );
ToolkitTestApplication application;
// Creates a text controller.
- ControlImpl controlImpl;
- ControllerPtr controller = Controller::New( controlImpl );
+ ControllerPtr controller = Controller::New();
DALI_TEST_CHECK( controller );
ToolkitTestApplication application;
// Creates a text controller.
- ControlImpl controlImpl;
- ControllerPtr controller = Controller::New( controlImpl );
+ ControllerPtr controller = Controller::New();
std::string text;
ImfManager::ImfEventData imfEvent;
ToolkitTestApplication application;
// Creates a text controller.
- ControlImpl controlImpl;
- ControllerPtr controller = Controller::New( controlImpl );
+ ControllerPtr controller = Controller::New();
DALI_TEST_CHECK( controller );
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( "<font family='TizenSans' size='12'>Hello world</font>" );
+ 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;
+}
--- /dev/null
+/*
+ * 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 <iostream>
+
+#include <stdlib.h>
+#include <limits>
+
+#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <toolkit-text-model.h>
+#include <dali-toolkit/internal/text/markup-processor.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/text-definitions.h>
+#include <dali-toolkit/internal/text/text-io.h>
+
+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;
+}
Control::RegisterVisual( index, placementActor, visual );
}
+void DummyControlImpl::RegisterVisual( Property::Index index, Actor placementActor, Toolkit::Visual::Base visual, bool enabled )
+{
+ Control::RegisterVisual( index, placementActor, visual, enabled );
+}
+
void DummyControlImpl::UnregisterVisual( Property::Index index )
{
Control::UnregisterVisual( index );
return Control::GetVisual( index );
}
+void DummyControlImpl::EnableVisual( Property::Index index, bool enabled )
+{
+ Control::EnableVisual( index, enabled );
+}
+
+bool DummyControlImpl::IsVisualEnabled( Property::Index index )
+{
+ return Control::IsVisualEnabled( index );
+}
+
Actor DummyControlImpl::GetPlacementActor( Property::Index index )
{
return Control::GetPlacementActor( index );
inline LongPressGestureDetector GetLongPressGestureDetector() const { return Internal::Control::GetLongPressGestureDetector(); }
void RegisterVisual( Property::Index index, Actor placementActor, Toolkit::Visual::Base visual);
+ void RegisterVisual( Property::Index index, Actor placementActor, Toolkit::Visual::Base visual, bool enabled );
void UnregisterVisual( Property::Index index );
+ void EnableVisual( Property::Index index, bool enabled );
+ bool IsVisualEnabled( Property::Index index );
+
Toolkit::Visual::Base GetVisual( Property::Index index );
Actor GetPlacementActor( Property::Index index );
// Register to self
dummyImpl.RegisterVisual( index, dummy, visual );
+
DALI_TEST_EQUALS( objectDestructionTracker.IsDestroyed(), false, TEST_LOCATION ); // Control not destroyed yet
DALI_TEST_CHECK( dummyImpl.GetVisual( index ) == visual );
DALI_TEST_CHECK( dummyImpl.GetPlacementActor( index ) == dummy );
END_TEST;
}
+
+int UtcDaliControlImplRegisterDisabledVisual(void)
+{
+ ToolkitTestApplication application;
+
+ DummyControl dummy = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(dummy.GetImplementation());
+
+ Property::Index TEST_PROPERTY =1;
+
+ Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
+ Toolkit::Visual::Base visual;
+
+ Property::Map map;
+ map[Visual::Property::TYPE] = Visual::COLOR;
+ map[ColorVisual::Property::MIX_COLOR] = Color::RED;
+
+ visual = visualFactory.CreateVisual( map );
+ DALI_TEST_CHECK(visual);
+
+ // Register index with a color visual
+ dummyImpl.RegisterVisual( TEST_PROPERTY, dummy, visual, false );
+
+ DALI_TEST_CHECK( dummyImpl.GetVisual( TEST_PROPERTY ) == visual );
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY ) == false );
+
+ Stage::GetCurrent().Add(dummy);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY ) == false );
+
+ DALI_TEST_CHECK( dummy.OnStage() == true );
+
+ dummyImpl.EnableVisual( TEST_PROPERTY, true );
+
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY ) == true );
+
+ END_TEST;
+}
+
+int UtcDaliControlImplDisableRegisteredVisual(void)
+{
+ ToolkitTestApplication application;
+
+ DummyControl dummy = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(dummy.GetImplementation());
+
+ Property::Index TEST_PROPERTY =1;
+
+ Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
+ Toolkit::Visual::Base visual;
+
+ Property::Map map;
+ map[Visual::Property::TYPE] = Visual::COLOR;
+ map[ColorVisual::Property::MIX_COLOR] = Color::RED;
+
+ visual = visualFactory.CreateVisual( map );
+ DALI_TEST_CHECK(visual);
+
+ // Register index with a color visual
+ dummyImpl.RegisterVisual( TEST_PROPERTY, dummy, visual );
+
+ Stage::GetCurrent().Add(dummy);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY ) == true);
+
+ DALI_TEST_CHECK( dummy.OnStage() == true );
+
+ dummyImpl.EnableVisual( TEST_PROPERTY, false );
+
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY ) == false );
+
+ END_TEST;
+}
+
+int UtcDaliControlImplEnabledVisualParentRemovedFromStage(void)
+{
+ // Visual enabled but then parent removed from stage, test ensures visual/renderer are also removed from stage.
+ // Then adding parent back to stage should automatically put visual/renderer back
+
+ ToolkitTestApplication application;
+
+ DummyControl dummy = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(dummy.GetImplementation());
+
+ Property::Index TEST_PROPERTY =1;
+
+ Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
+ Toolkit::Visual::Base visual;
+
+ Property::Map map;
+ map[Visual::Property::TYPE] = Visual::COLOR;
+ map[ColorVisual::Property::MIX_COLOR] = Color::RED;
+
+ visual = visualFactory.CreateVisual( map );
+ DALI_TEST_CHECK(visual);
+
+ // Register index with a color visual
+ dummyImpl.RegisterVisual( TEST_PROPERTY, dummy, visual, false );
+
+ Stage::GetCurrent().Add(dummy);
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY ) == false );
+ DALI_TEST_CHECK( dummy.OnStage() == true );
+ dummyImpl.EnableVisual( TEST_PROPERTY, true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_CHECK( dummy.GetRendererCount() == 1u );
+
+ // Remove control from stage, visual should be removed from stage too
+ Stage::GetCurrent().Remove(dummy);
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_CHECK( dummy.GetRendererCount() == 0u );
+
+ Stage::GetCurrent().Add(dummy);
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_CHECK( dummy.GetRendererCount() == 1u );
+
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY ) == true );
+
+ END_TEST;
+}
+
+int UtcDaliControlImplRegisterTwoVisualsAndEnableOnlyOne(void)
+{
+ // Register 2 visuals and enable by default
+ // Disable 1 visual
+ // Remove control from stage then put it back
+ // Check that only 1 visual/renderer is staged.
+
+ ToolkitTestApplication application;
+
+ DummyControl dummy = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(dummy.GetImplementation());
+
+ Property::Index TEST_PROPERTY1 =1;
+ Property::Index TEST_PROPERTY2 =2;
+
+ Toolkit::VisualFactory visualFactory = Toolkit::VisualFactory::Get();
+ Toolkit::Visual::Base visual1;
+ Toolkit::Visual::Base visual2;
+
+ Property::Map map;
+ map[Visual::Property::TYPE] = Visual::COLOR;
+ map[ColorVisual::Property::MIX_COLOR] = Color::RED;
+
+ Property::Map map2;
+ map[Visual::Property::TYPE] = Visual::COLOR;
+ map[ColorVisual::Property::MIX_COLOR] = Color::BLUE;
+
+ visual1 = visualFactory.CreateVisual( map );
+ DALI_TEST_CHECK(visual1);
+
+ visual2 = visualFactory.CreateVisual( map );
+ DALI_TEST_CHECK(visual2);
+
+ // Register index with a color visual
+ dummyImpl.RegisterVisual( TEST_PROPERTY1, dummy, visual1 );
+ // Register second index with a color visual
+ dummyImpl.RegisterVisual( TEST_PROPERTY2, dummy, visual2 );
+
+ Stage::GetCurrent().Add(dummy);
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK( dummy.GetRendererCount() == 2u );
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY1 ) == true );
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY1 ) == true);
+ DALI_TEST_CHECK( dummy.OnStage() == true );
+ dummyImpl.EnableVisual( TEST_PROPERTY2, false );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_CHECK( dummy.GetRendererCount() == 1u );
+
+ // Remove control from stage, visual should be removed from stage too
+ Stage::GetCurrent().Remove(dummy);
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_CHECK( dummy.GetRendererCount() == 0u );
+
+ Stage::GetCurrent().Add(dummy);
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+ DALI_TEST_CHECK( dummy.GetRendererCount() == 1u );
+
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY1 ) == true );
+ DALI_TEST_CHECK( dummyImpl.IsVisualEnabled( TEST_PROPERTY2 ) == false );
+
+ END_TEST;
+}
+
DALI_TEST_EQUALS( editor.GetProperty<float>( 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<std::string>( 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<std::string>( 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<std::string>( 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<std::string>( TextEditor::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION );
+ editor.SetProperty( TextEditor::Property::SHADOW, "{\"color\":\"green\",\"offset\":\"2 2\"}" );
+ DALI_TEST_EQUALS( editor.GetProperty<std::string>( 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" );
DALI_TEST_EQUALS( field.GetProperty<std::string>( 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<std::string>( 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<std::string>( 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<std::string>( 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<std::string>( TextField::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION );
+ field.SetProperty( TextField::Property::SHADOW, "{\"color\":\"green\",\"offset\":\"2 2\"}" );
+ DALI_TEST_EQUALS( field.GetProperty<std::string>( 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" );
// The underline color is changed as well.
DALI_TEST_EQUALS( label.GetProperty<Vector4>( TextLabel::Property::UNDERLINE_COLOR ), Color::BLUE, TEST_LOCATION );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( 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<Vector2>( TextLabel::Property::SHADOW_OFFSET ), Vector2( 3.0f, 3.0f ), TEST_LOCATION );
DALI_TEST_EQUALS( label.GetProperty<float>( 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<std::string>( 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<std::string>( TextLabel::Property::UNDERLINE ), std::string("{\"enable\":\"true\",\"color\":\"red\",\"height\":\"1\"}"), TEST_LOCATION );
+
+ label.SetProperty( TextLabel::Property::UNDERLINE, "" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( 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<std::string>( TextLabel::Property::SHADOW ), std::string("Shadow properties"), TEST_LOCATION );
+ label.SetProperty( TextLabel::Property::SHADOW, "{\"color\":\"green\",\"offset\":\"2 2\"}" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::SHADOW ), std::string("{\"color\":\"green\",\"offset\":\"2 2\"}"), TEST_LOCATION );
+
+ label.SetProperty( TextLabel::Property::SHADOW, "" );
+ DALI_TEST_EQUALS( label.GetProperty<std::string>( TextLabel::Property::SHADOW ), std::string("{\"color\":\"green\",\"offset\":\"0 0\"}"), TEST_LOCATION );
// Check the emboss property
label.SetProperty( TextLabel::Property::EMBOSS, "Emboss properties" );
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();
}
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<bool>();
+ DALI_TEST_CHECK( !enabled );
+
+ END_TEST;
+}
+
int UtcDaliToolkitTextlabelEllipsis(void)
{
ToolkitTestApplication application;
#include <iostream>
#include <stdlib.h>
+#include <unistd.h>
+
#include <dali-toolkit-test-suite-utils.h>
#include <dali/public-api/rendering/renderer.h>
#include <dali/public-api/rendering/texture-set.h>
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)
// </svg>
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 );
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, "<font family='TizenSans' size='12'>Hello world</font>" );
+ 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;
}
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<int>( 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>(), (int)Visual::TEXT, TEST_LOCATION );
+
+ value = resultMap.Find( TextVisual::Property::RENDERING_BACKEND, Property::INTEGER );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<int>(), Toolkit::Text::DEFAULT_RENDERING_BACKEND, TEST_LOCATION );
+
+ value = resultMap.Find( TextVisual::Property::TEXT, Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<std::string>(), "Hello world", TEST_LOCATION );
+
+ value = resultMap.Find( TextVisual::Property::FONT_FAMILY, Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<std::string>(), "TizenSans", TEST_LOCATION );
+
+ value = resultMap.Find( TextVisual::Property::FONT_STYLE, Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<std::string>(), "{\"weight\":\"bold\"}", TEST_LOCATION );
+
+ value = resultMap.Find( TextVisual::Property::POINT_SIZE, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 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<bool>() );
+
+ value = resultMap.Find( TextVisual::Property::HORIZONTAL_ALIGNMENT, Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<std::string>(), "CENTER", TEST_LOCATION );
+
+ value = resultMap.Find( TextVisual::Property::VERTICAL_ALIGNMENT, Property::STRING );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<std::string>(), "CENTER", TEST_LOCATION );
+
+ value = resultMap.Find( TextVisual::Property::TEXT_COLOR, Property::VECTOR4 );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<Vector4>(), Color::RED, TEST_LOCATION );
+
+ value = resultMap.Find( TextVisual::Property::ENABLE_MARKUP, Property::BOOLEAN );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_CHECK( !value->Get<bool>() );
+
+ value = resultMap.Find( TextVisual::Property::ENABLE_AUTO_SCROLL, Property::BOOLEAN );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_CHECK( !value->Get<bool>() );
+
+ value = resultMap.Find( TextVisual::Property::LINE_SPACING, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 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<bool>() );
+
+ END_TEST;
+}
+
int UtcDaliVisualGetPropertyMapBatchImageVisualNoAtlas(void)
{
ToolkitTestApplication application;
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 )
#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
#include <dali-toolkit/public-api/visuals/mesh-visual-properties.h>
#include <dali-toolkit/public-api/visuals/primitive-visual-properties.h>
+#include <dali-toolkit/public-api/visuals/text-visual-properties.h>
#include <dali-toolkit/public-api/visuals/visual-properties.h>
#include <dali-toolkit/public-api/dali-toolkit-version.h>
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 );
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.
{
Actor self = Self();
- mController = Text::Controller::New( *this );
+ mController = Text::Controller::New( this, this );
mDecorator = Text::Decorator::New( *mController,
*mController );
// Disables the horizontal scrolling.
mController->SetHorizontalScrollEnabled( false );
+ // Sets the maximum number of characters.
mController->SetMaximumNumberOfCharacters( std::numeric_limits<Length>::max() );
// Enable the smooth handle panning.
mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
}
- EnableClipping( true, size );
+ EnableClipping( size );
RenderText( updateTextType );
}
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();
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() );
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 )
}
}
-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();
}
}
-#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.
*
*/
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
+
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/text-controls/text-editor.h>
#include <dali-toolkit/internal/text/clipping/text-clipper.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
#include <dali-toolkit/internal/text/text-controller.h>
#include <dali-toolkit/internal/text/rendering/text-renderer.h>
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
-
namespace Dali
{
/**
* @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:
// 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()
*/
*/
virtual void InputStyleChanged( Text::InputStyle::Mask inputStyleMask );
+ /**
+ * @copydoc Text::ControlInterface::AddDecoration()
+ */
+ virtual void AddDecoration( Actor& actor, bool needsClipping );
+
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.
} // namespace Dali
-#endif // __DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H__
+#endif // DALI_TOOLKIT_INTERNAL_TEXT_EDITOR_H
{
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;
mRenderer = Backend::Get().NewRenderer( mRenderingBackend );
}
- EnableClipping( ( Dali::Toolkit::TextField::EXCEED_POLICY_CLIP == mExceedPolicy ), size );
+ EnableClipping( size );
RenderText( updateTextType );
}
}
}
- void TextField::RenderText( Text::Controller::UpdateTextType updateTextType )
+void TextField::RenderText( Text::Controller::UpdateTextType updateTextType )
{
Actor self = Self();
Actor renderableActor;
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();
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() );
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 )
}
}
-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 );
}
}
-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 )
-#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.
*
*/
+// EXTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
+
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/text-controls/text-field.h>
#include <dali-toolkit/internal/text/clipping/text-clipper.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
#include <dali-toolkit/internal/text/text-controller.h>
#include <dali-toolkit/internal/text/rendering/text-renderer.h>
-// EXTERNAL INCLUDES
-#include <dali/devel-api/adaptor-framework/clipboard-event-notifier.h>
-
namespace Dali
{
/**
* @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:
// 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()
*/
*/
virtual void InputStyleChanged( Text::InputStyle::Mask inputStyleMask );
+ /**
+ * @copydoc Text::ControlInterface::AddDecoration()
+ */
+ virtual void AddDecoration( Actor& actor, bool needsClipping );
+
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.
} // namespace Dali
-#endif // __DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H__
+#endif // DALI_TOOLKIT_INTERNAL_TEXT_FIELD_H
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/text/rendering-backend.h>
-#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
-#include <dali-toolkit/internal/text/property-string-parser.h>
-#include <dali-toolkit/internal/text/rendering/text-backend.h>
+#include <dali-toolkit/public-api/visuals/text-visual-properties.h>
#include <dali-toolkit/internal/text/text-effects-style.h>
-#include <dali-toolkit/internal/text/text-font-style.h>
-#include <dali-toolkit/internal/text/text-view.h>
-#include <dali-toolkit/internal/text/text-definitions.h>
#include <dali-toolkit/internal/styling/style-manager-impl.h>
using Dali::Toolkit::Text::LayoutEngine;
-using Dali::Toolkit::Text::Backend;
namespace Dali
{
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()
{
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
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<bool>();
- impl.mController->SetMarkupProcessorEnabled( enableMarkup );
- }
- break;
- }
- case Toolkit::TextLabel::Property::ENABLE_AUTO_SCROLL:
- {
- if( impl.mController )
- {
- const bool enableAutoScroll = value.Get<bool>();
- // 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<int>() );
- break;
- }
- case Toolkit::TextLabel::Property::AUTO_SCROLL_LOOP_COUNT:
- {
- if( !impl.mTextScroller )
- {
- impl.mTextScroller = Text::TextScroller::New( impl );
- }
- impl.mTextScroller->SetLoopCount( value.Get<int>() );
- break;
- }
- case Toolkit::TextLabel::Property::AUTO_SCROLL_GAP:
- {
- if( !impl.mTextScroller )
- {
- impl.mTextScroller = Text::TextScroller::New( impl );
- }
- impl.mTextScroller->SetGap( value.Get<float>() );
- break;
- }
- case Toolkit::TextLabel::Property::LINE_SPACING:
- {
- if( impl.mController )
- {
- const float lineSpacing = value.Get<float>();
- 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 );
}
}
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<std::string>(),
+ 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<std::string>(),
+ 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<std::string>(),
+ 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<std::string>(),
+ 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<std::string>(),
+ 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;
{
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<int>( 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<TextVisual*>( &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 )
// 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() ) );
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()
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 ) )
{
}
-#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.
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/text-controls/text-label.h>
-#include <dali-toolkit/internal/text/text-controller.h>
-#include <dali-toolkit/internal/text/text-scroller-interface.h>
-#include <dali-toolkit/internal/text/rendering/text-renderer.h>
-#include <dali-toolkit/internal/text/text-scroller.h>
+#include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/visuals/text/text-visual.h>
namespace Dali
{
/**
* @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:
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
/**
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
} // namespace Dali
-#endif // __DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H__
+#endif // DALI_TOOLKIT_INTERNAL_TEXT_LABEL_H
$(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)/controls/alignment/alignment-impl.cpp \
$(toolkit_src_dir)/controls/bloom-view/bloom-view-impl.cpp \
$(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 \
// EXTERNAL INCLUDES
#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/vector2.h>
#include <stdlib.h>
+#include <sstream>
+#include <iomanip>
namespace Dali
{
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" );
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;
}
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 )
return static_cast<float>( 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<float>( ( color & 0xFF000000 ) >> 24u ) / 255.f;
}
}
+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<unsigned int>( 255.f * value.a );
+ const unsigned int red = static_cast<unsigned int>( 255.f * value.r );
+ const unsigned int green = static_cast<unsigned int>( 255.f * value.g );
+ const unsigned int blue = static_cast<unsigned int>( 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
namespace Dali
{
+struct Vector2;
struct Vector4;
namespace Toolkit
/**
* @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.
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.
* @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.
*/
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
}
}
-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
*/
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
-#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.
*
*/
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/input-style.h>
-
namespace Dali
{
-class Actor;
-
namespace Toolkit
{
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
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H__
+#endif // DALI_TOOLKIT_TEXT_CONTROL_INTERFACE_H
#include <dali-toolkit/internal/text/multi-language-support.h>
#include <dali-toolkit/internal/text/segmentation.h>
#include <dali-toolkit/internal/text/shaper.h>
+#include <dali-toolkit/internal/text/text-control-interface.h>
#include <dali-toolkit/internal/text/text-run-container.h>
namespace
void Controller::Impl::RequestRelayout()
{
- mControlInterface.RequestTextRelayout();
+ if( NULL != mControlInterface )
+ {
+ mControlInterface->RequestTextRelayout();
+ }
}
} // namespace Text
-#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.
#include <dali-toolkit/internal/text/input-style.h>
#include <dali-toolkit/internal/text/layouts/layout-engine.h>
#include <dali-toolkit/internal/text/logical-model-impl.h>
+#include <dali-toolkit/internal/text/text-scroller-data.h>
#include <dali-toolkit/internal/text/text-controller.h>
#include <dali-toolkit/internal/text/text-view.h>
#include <dali-toolkit/internal/text/visual-model-impl.h>
struct Controller::Impl
{
- Impl( ControlInterface& controlInterface )
+ Impl( ControlInterface* controlInterface,
+ EditableControlInterface* editableControlInterface )
: mControlInterface( controlInterface ),
+ mEditableControlInterface( editableControlInterface ),
mLogicalModel(),
mVisualModel(),
mFontDefaults( NULL ),
mEmbossDefaults( NULL ),
mOutlineDefaults( NULL ),
mEventData( NULL ),
+ mAutoScrollData( NULL ),
mFontClient(),
mClipboard(),
mView(),
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();
delete mEmbossDefaults;
delete mOutlineDefaults;
delete mEventData;
+ delete mAutoScrollData;
}
+ // Text Controller Implementation.
+
/**
- * @brief Request a relayout using the ControlInterface.
+ * @copydoc Text::Controller::RequestRelayout()
*/
void RequestRelayout();
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.
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.
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
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_CONTROLLER_H__
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H
#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
#include <dali-toolkit/internal/text/markup-processor.h>
#include <dali-toolkit/internal/text/text-controller-impl.h>
+#include <dali-toolkit/internal/text/text-editable-control-interface.h>
namespace
{
// 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 )
{
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<OperationsMask>( mImpl->mOperationsPending |
UPDATE_DIRECTION |
REORDER );
+ if( NULL == mImpl->mAutoScrollData )
+ {
+ mImpl->mAutoScrollData = new ScrollerData();
+ }
}
else
{
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 )
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
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 );
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 )
return mImpl->mEventData->mInputStyle.shadowProperties;
}
- return GetDefaultShadowProperties();
+ return EMPTY_STRING;
}
void Controller::SetInputUnderlineProperties( const std::string& underlineProperties )
return mImpl->mEventData->mInputStyle.underlineProperties;
}
- return GetDefaultUnderlineProperties();
+ return EMPTY_STRING;
}
void Controller::SetInputEmbossProperties( const std::string& embossProperties )
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;
return updateTextType;
}
+void Controller::RequestRelayout()
+{
+ mImpl->RequestRelayout();
+}
+
// public : Input style change signals.
bool Controller::IsInputStyleChangedSignalsQueueEmpty()
{
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();
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;
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;
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 )
mImpl->mEventData->mScrollAfterDelete = true;
mImpl->RequestRelayout();
- mImpl->mControlInterface.TextChanged();
+
+ if( NULL != mImpl->mEditableControlInterface )
+ {
+ mImpl->mEditableControlInterface->TextChanged();
+ }
break;
}
case Toolkit::TextSelectionPopup::COPY:
}
}
+// 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 )
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();
+ }
}
}
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,
if ( NO_OPERATION != ( UPDATE_DIRECTION & operations ) )
{
- mImpl->mAutoScrollDirectionRTL = false;
+ if( NULL != mImpl->mAutoScrollData )
+ {
+ mImpl->mAutoScrollData->mAutoScrollDirectionRTL = false;
+ }
}
// Reorder the lines
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;
}
}
}
#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;
// 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.
-#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.
#include <dali-toolkit/devel-api/controls/text-controls/text-selection-popup-callback-interface.h>
#include <dali-toolkit/internal/text/decorator/text-decorator.h>
#include <dali-toolkit/internal/text/layouts/layout-engine.h>
-#include <dali-toolkit/internal/text/text-control-interface.h>
+#include <dali-toolkit/internal/text/text-scroller-interface.h>
namespace Dali
{
{
class Controller;
+class ControlInterface;
+class EditableControlInterface;
class View;
+struct ScrollerData;
typedef IntrusivePtr<Controller> ControllerPtr;
-typedef Dali::Toolkit::Text::ControlInterface ControlInterface;
/**
* @brief A Text Controller is used by UI Controls which display text.
*
* 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.
/**
* @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.
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.
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.
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.
*/
UpdateTextType Relayout( const Size& size );
+ /**
+ * @brief Request a relayout using the ControlInterface.
+ */
+ void RequestRelayout();
+
public: // Input style change signals.
/**
*/
virtual void TextPopupButtonTouched( Dali::Toolkit::TextSelectionPopup::Buttons button );
+private: // Inherit from TextScroller
+
+ /**
+ * @copydoc Text::ScrollerInterface::ScrollingFinished()
+ */
+ virtual void ScrollingFinished();
+
private: // Update.
/**
/**
* @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 );
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_CONTROLLER_H__
+#endif // DALI_TOOLKIT_TEXT_CONTROLLER_H
--- /dev/null
+#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 <dali-toolkit/internal/text/input-style.h>
+
+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
{
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<std::string>();
+
+ 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<std::string>();
- Vector4 color;
- const bool colorDefined = colorValue != NULL;
- if( colorDefined )
- {
- const std::string colorStr = colorValue->Get<std::string>();
+ 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<std::string>();
+ 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<std::string>();
+ 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<std::string>();
+
+ 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<std::string>();
+
+ 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<std::string>();
+
+ 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 ) )
{
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;
}
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;
+ }
}
}
}
{
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:
{
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<std::string>();
-
- 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<std::string>();
-
- StringOffsetToVector2( offsetStr, offset );
- }
-
switch( type )
{
case EffectStyle::DEFAULT:
}
}
}
+ 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;
{
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:
*
*/
-// EXTERNAL INCLUDES
-#include <dali/devel-api/scripting/scripting.h>
-
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/text-controller.h>
-#include <dali-toolkit/internal/text/text-definitions.h>
namespace Dali
{
};
/**
+ * @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.
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/property-string-parser.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
namespace Dali
{
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");
} // namespace
+void SetFontFamilyProperty( ControllerPtr controller, const Property::Value& value )
+{
+ if( controller )
+ {
+ const std::string fontFamilyValue = value.Get<std::string>();
+
+ 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<std::string>();
+ }
+
+ /// Type key
+ Property::Value* typeValue = map.Find( TYPE_KEY );
+
+ std::string typeStr;
+ if( NULL != typeValue )
+ {
+ typeStr = typeValue->Get<std::string>();
+ }
+
+ 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 )
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/text-controller.h>
-#include <dali-toolkit/internal/text/text-definitions.h>
namespace Dali
{
};
/**
+ * @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.
/*
- * 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.
*
*/
-// CLASS HEADER
-#include <dali-toolkit/internal/text/text-control-interface.h>
+// FILE HEADER
+#include <dali-toolkit/internal/text/text-scroller-data.h>
namespace Dali
{
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
--- /dev/null
+#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 <dali/public-api/math/vector2.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+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
+
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/text-scroller-interface.h>
+#include <dali-toolkit/internal/text/text-scroller-data.h>
namespace Dali
{
namespace Toolkit
{
+namespace Text
+{
+extern const int MINIMUM_SCROLL_SPEED;
+} // namespace
+
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
return textScroller;
}
-void TextScroller::SetGap( int gap )
-{
- DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextScroller::SetGap gap[%d]\n", gap );
- mWrapGap = static_cast<float>(gap);
-}
-
-int TextScroller::GetGap() const
-{
- return static_cast<int>(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;
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" );
}
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 )
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() )
class TextScroller;
class ScrollerInterface;
+struct ScrollerData;
typedef IntrusivePtr<TextScroller> 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.
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.
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();
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
);
}
+BorderVisualPtr BorderVisual::New( VisualFactoryCache& factoryCache )
+{
+ return new BorderVisual( factoryCache );
+}
+
BorderVisual::BorderVisual( VisualFactoryCache& factoryCache )
: Visual::Base( factoryCache ),
mBorderColor( Color::TRANSPARENT ),
// EXTERNAL INCLUDES
#include <dali/public-api/rendering/geometry.h>
+#include <dali/public-api/common/intrusive-ptr.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
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.
*
* | 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
*/
virtual ~BorderVisual();
-protected:
-
/**
* @copydoc Visual::Base::DoInitialize
*/
);
}
+ColorVisualPtr ColorVisual::New( VisualFactoryCache& factoryCache )
+{
+ return new ColorVisual( factoryCache );
+}
+
ColorVisual::ColorVisual( VisualFactoryCache& factoryCache )
: Visual::Base( factoryCache ),
mMixColorIndex( Property::INVALID_INDEX )
#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.
*
*/
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+
// INTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
namespace Internal
{
+class ColorVisual;
+typedef IntrusivePtr< ColorVisual > ColorVisualPtr;
+
/**
* The visual which renders a solid color to the control's quad
*
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
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 );
} // unnamed namespace
+GradientVisualPtr GradientVisual::New( VisualFactoryCache& factoryCache )
+{
+ return new GradientVisual( factoryCache );
+}
GradientVisual::GradientVisual( VisualFactoryCache& factoryCache )
: Visual::Base( factoryCache ),
#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.
*
*/
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+
// INTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
#include <dali-toolkit/internal/visuals/gradient/gradient.h>
{
class Gradient;
+class GradientVisual;
+typedef IntrusivePtr< GradientVisual > GradientVisualPtr;
/**
* The visual which renders smooth transition of colors to the control's quad.
};
/**
- * @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
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
*/
}\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()
{
}
*
*/
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+
// INTERNAL HEADER
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
-// EXTERNAL INCLUDES
-#include <dali/public-api/images/resource-image.h>
-
namespace Dali
{
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
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 );
*/
// CLASS HEADER
-#include "image-visual.h"
+#include <dali-toolkit/internal/visuals/image/image-visual.h>
// EXTERNAL HEADER
#include <cstring> // for strncasecmp
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()
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;
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 );
// 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 );
naturalSize = Vector2::ZERO;
}
-Renderer ImageVisual::CreateRenderer() const
+void ImageVisual::CreateRenderer()
{
Geometry geometry;
Shader shader;
// Renderer can't be shared between NativeImage and other image types.
if( !mNativeFragmentShaderCode.empty() )
{
- return CreateNativeImageRenderer();
+ CreateNativeImageRenderer();
+ return;
}
if( !mImpl->mCustomShader )
}
}
- 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;
}
}
- 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 );
}
return mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
}
-void ImageVisual::DoSynchronousResourceLoading()
+void ImageVisual::LoadResourceSynchronously()
{
if( !mImageUrl.empty() )
{
}
}
-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 );
}
}
{
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 )
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
{
{
// 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();
}
}
{
mImpl->mFlags &= ~Impl::IS_FROM_CACHE;
- mImpl->mRenderer = CreateRenderer();
+ // don't reuse CreateTextureSet
+ mTextureSet = TextureSet::New();
+ CreateRenderer();
if( image )
{
mImpl->mRenderer.Reset();
}
mPlacementActor.Reset();
+ mTextureSet.Reset(); // release texture when going offstage
}
void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const
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 );
}
}
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 );
+ }
}
}
#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.
*
*/
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/visual-base-impl.h>
-#include <dali-toolkit/devel-api/image-loader/atlas-upload-observer.h>
-
// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/public-api/images/image.h>
#include <dali/public-api/images/image-operations.h>
#include <dali/public-api/images/resource-image.h>
#include <dali/devel-api/object/weak-handle.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-base-impl.h>
+#include <dali-toolkit/devel-api/image-loader/atlas-upload-observer.h>
+
namespace Dali
{
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
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
*/
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.
/**
* @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
void SetNativeFragmentShaderCode( Dali::NativeImage& nativeImage );
private:
+
Image mImage;
PixelData mPixels;
+ TextureSet mTextureSet;
Vector4 mPixelArea;
WeakHandle<Actor> 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
}\n
);
-} // namespace
+} // unnamed namespace
+
+MeshVisualPtr MeshVisual::New( VisualFactoryCache& factoryCache )
+{
+ return new MeshVisual( factoryCache );
+}
MeshVisual::MeshVisual( VisualFactoryCache& factoryCache )
: Visual::Base( factoryCache ),
// EXTERNAL INCLUDES
#include <fstream>
#include <string.h>
+#include <dali/public-api/common/intrusive-ptr.h>
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/visuals/mesh-visual-properties.h>
namespace Internal
{
+class MeshVisual;
+typedef IntrusivePtr< MeshVisual > MeshVisualPtr;
+
/**
* The visual which renders a 3D object to the control's quad
*
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
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 );
/////////////////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 )
{
}
}
}
-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();
*
*/
-// INTERNAL INCLUDES
-#include <dali-toolkit/internal/visuals/visual-base-impl.h>
-
// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/public-api/images/image.h>
#include <dali/public-api/images/image-operations.h>
#include <dali/devel-api/images/nine-patch-image.h>
#include <dali/public-api/rendering/sampler.h>
#include <dali/public-api/rendering/shader.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-base-impl.h>
+
namespace Dali
{
namespace Internal
{
+class NPatchVisual;
+typedef IntrusivePtr< NPatchVisual > NPatchVisualPtr;
+
/**
* The visual which renders an 9 patch image to the control's quad
*
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
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:
}\n
);
-} // namespace
+} // unnamed namespace
+
+PrimitiveVisualPtr PrimitiveVisual::New( VisualFactoryCache& factoryCache )
+{
+ return new PrimitiveVisual( factoryCache );
+}
PrimitiveVisual::PrimitiveVisual( VisualFactoryCache& factoryCache )
: Visual::Base( factoryCache ),
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/visuals/primitive-visual-properties.h>
namespace Internal
{
+class PrimitiveVisual;
+typedef IntrusivePtr< PrimitiveVisual > PrimitiveVisualPtr;
+
/**
* The visual which renders a simple 3D shape to the control's quad
*
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
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 );
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;
std::string imageUrl;
if( imageURLValue->Get( imageUrl ) )
{
- SetImage( imageUrl );
+ ParseFromUrl( imageUrl );
}
else
{
void SvgVisual::SetSize( const Vector2& size )
{
- if(mImpl->mSize != size && mParsedImage && GetIsOnStage() )
+ if(mImpl->mSize != size && mParsedImage && IsOnStage() )
{
AddRasterizationTask( size );
}
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();
}
}
void SvgVisual::ApplyRasterizedImage( PixelData rasterizedPixelData )
{
- if( GetIsOnStage() )
+ if( IsOnStage() )
{
TextureSet currentTextureSet = mImpl->mRenderer.GetTextures();
if( mAtlasRect != FULL_TEXTURE_RECT )
}
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 )
if( textureSet )
{
- TextureSetImage( textureSet, 0u, texture );
+ textureSet.SetTexture( 0, texture );
}
}
*
*/
-//EXTERNAL INCLUDES
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/devel-api/object/weak-handle.h>
// INTERNAL INCLUDES
namespace Internal
{
+class SvgVisual;
+typedef IntrusivePtr< SvgVisual > SvgVisualPtr;
+
/**
* The visual which renders a svg image
*
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
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 );
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
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.
*
--- /dev/null
+/*
+ * 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 <dali-toolkit/internal/visuals/text/text-visual.h>
+
+// EXTERNAL HEADER
+#include <dali/devel-api/scripting/enum-helper.h>
+// #include <dali/devel-api/scripting/scripting.h>
+
+// INTERNAL HEADER
+#include <dali-toolkit/public-api/text/rendering-backend.h>
+#include <dali-toolkit/public-api/visuals/text-visual-properties.h>
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/internal/text/rendering/text-backend.h>
+#include <dali-toolkit/internal/text/text-view.h>
+#include <dali-toolkit/internal/visuals/visual-base-impl.h>
+#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
+#include <dali-toolkit/internal/text/text-font-style.h>
+#include <dali-toolkit/internal/text/text-effects-style.h>
+
+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<Toolkit::Text::LayoutEngine::HorizontalAlignment>( 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<int>();
+
+#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<std::string>() );
+ 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<float>();
+
+ if( !Equals( mController->GetDefaultPointSize(), pointSize ) )
+ {
+ mController->SetDefaultPointSize( pointSize );
+ }
+ break;
+ }
+ case Toolkit::TextVisual::Property::MULTI_LINE:
+ {
+ mController->SetMultiLineEnabled( propertyValue.Get<bool>() );
+ 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<bool>();
+ mController->SetMarkupProcessorEnabled( enableMarkup );
+ break;
+ }
+ case Toolkit::TextVisual::Property::ENABLE_AUTO_SCROLL:
+ {
+ const bool enableAutoScroll = propertyValue.Get<bool>();
+
+ // 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<int>() );
+ break;
+ }
+ case Toolkit::TextVisual::Property::AUTO_SCROLL_LOOP_COUNT:
+ {
+ const int loopCount = propertyValue.Get<int>();
+ 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<float>() );
+ break;
+ }
+ case Toolkit::TextVisual::Property::LINE_SPACING:
+ {
+ const float lineSpacing = propertyValue.Get<float>();
+ 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<Vector4>();
+ if( mController->GetUnderlineColor() != color )
+ {
+ mController->SetUnderlineColor( color );
+ mRenderer.Reset();
+ }
+ break;
+ }
+ case Property::FLOAT:
+ {
+ float height = propertyValue.Get<float>();
+ if( fabsf( mController->GetUnderlineHeight() - height ) > Math::MACHINE_EPSILON_1000 )
+ {
+ mController->SetUnderlineHeight( height );
+ mRenderer.Reset();
+ }
+ break;
+ }
+ case Property::BOOLEAN:
+ {
+ const bool enabled = propertyValue.Get<bool>();
+ 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<Vector2>();
+ if( mController->GetShadowOffset() != shadowOffset )
+ {
+ mController->SetShadowOffset( shadowOffset );
+ mRenderer.Reset();
+ }
+ break;
+ }
+ case Property::VECTOR4:
+ {
+ const Vector4 shadowColor = propertyValue.Get<Vector4>();
+ 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
--- /dev/null
+#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 <dali/public-api/common/intrusive-ptr.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/visual-base-impl.h>
+#include <dali-toolkit/internal/text/rendering/text-renderer.h>
+#include <dali-toolkit/internal/text/text-controller.h>
+#include <dali-toolkit/internal/text/text-scroller.h>
+
+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 */
return mImpl->mSize;
}
+float Visual::Base::GetHeightForWidth( float width ) const
+{
+ return 0.f;
+}
+
void Visual::Base::GetNaturalSize( Vector2& naturalSize ) const
{
naturalSize = Vector2::ZERO;
void Visual::Base::SetOffStage( Actor& actor )
{
- if( GetIsOnStage() )
+ if( IsOnStage() )
{
DoSetOffStage( 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)
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;
}
*/
// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
#include <dali/public-api/images/image-operations.h>
#include <dali/public-api/object/base-object.h>
#include <dali/public-api/rendering/shader.h>
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;
*
* @param[in] preMultipled whether alpha is pre-multiplied.
*/
- void EnablePreMultipliedAlpha( bool preMultipled );
+ void EnablePreMultipliedAlpha( bool preMultipled );
/**
* @brief Query whether alpha is pre-multiplied.
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:
/**
VisualFactoryCache& mFactoryCache;
};
+typedef IntrusivePtr<Base> BasePtr;
+
} // namspace Visual
} // namespace Internal
#include <dali-toolkit/internal/visuals/npatch/npatch-visual.h>
#include <dali-toolkit/internal/visuals/primitive/primitive-visual.h>
#include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+#include <dali-toolkit/internal/visuals/text/text-visual.h>
#include <dali-toolkit/internal/visuals/wireframe/wireframe-visual.h>
#include <dali-toolkit/internal/visuals/visual-factory-cache.h>
#include <dali-toolkit/internal/visuals/visual-factory-resolve-url.h>
// 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.
{
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;
}
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
{
if( batchingEnabled )
{
- visualPtr = new BatchImageVisual( *( mFactoryCache.Get() ) );
+ visualPtr = BatchImageVisual::New( *( mFactoryCache.Get() ) );
break;
}
else
{
- visualPtr = new ImageVisual( *( mFactoryCache.Get() ) );
+ visualPtr = ImageVisual::New( *( mFactoryCache.Get() ) );
}
}
}
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 )
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 )
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 )
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
*/
Toolkit::Visual::Base CreateVisual( const std::string& image, ImageDimensions size );
-
protected:
/**
}
+WireframeVisualPtr WireframeVisual::New( VisualFactoryCache& factoryCache )
+{
+ return new WireframeVisual( factoryCache );
+}
WireframeVisual::WireframeVisual( VisualFactoryCache& factoryCache )
: Visual::Base( factoryCache )
}
WireframeVisual::~WireframeVisual()
-{}
+{
+}
void WireframeVisual::DoSetOnStage( Actor& actor )
{
*
*/
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+
// INTERNAL INCLUDES
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
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
*/
virtual ~WireframeVisual();
-protected:
-
/**
* @copydoc Visual::Base::DoSetOnStage
*/
Property::Index index;
Toolkit::Visual::Base visual;
Actor placementActor;
+ bool enabled;
- RegisteredVisual( Property::Index aIndex, Toolkit::Visual::Base &aVisual, Actor &aPlacementActor) : index(aIndex), visual(aVisual), placementActor(aPlacementActor) {}
+ RegisteredVisual( Property::Index aIndex, Toolkit::Visual::Base &aVisual, Actor &aPlacementActor, bool aEnabled) :
+ index(aIndex), visual(aVisual), placementActor(aPlacementActor), enabled(aEnabled) {}
};
-typedef Dali::OwnerContainer< RegisteredVisual* > RegisteredVisuals;
+typedef Dali::OwnerContainer< RegisteredVisual* > RegisteredVisualContainer;
/**
* Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
*/
-bool FindVisual( Property::Index targetIndex, RegisteredVisuals& visuals, RegisteredVisuals::Iterator& iter )
+bool FindVisual( Property::Index targetIndex, RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
{
for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
{
// Data
Control& mControlImpl;
- RegisteredVisuals mVisuals; // Stores visuals needed by the control, non trivial type so std::vector used.
+ RegisteredVisualContainer mVisuals; // Stores visuals needed by the control, non trivial type so std::vector used.
std::string mStyleName;
Toolkit::Visual::Base mBackgroundVisual; ///< The visual to render the background
Vector4 mBackgroundColor; ///< The color of the background visual
void Control::RegisterVisual( Property::Index index, Actor& placementActor, Toolkit::Visual::Base& visual )
{
+ RegisterVisual( index, placementActor, visual, true );
+}
+
+void Control::RegisterVisual( Property::Index index, Actor& placementActor, Toolkit::Visual::Base& visual, bool enabled )
+{
bool visualReplaced ( false );
Actor actorToRegister; // Null actor, replaced if placement actor not Self
Actor self = Self();
if ( !mImpl->mVisuals.Empty() )
{
- RegisteredVisuals::Iterator iter;
+ RegisteredVisualContainer::Iterator iter;
// Check if visual (index) is already registered. Replace if so.
if ( FindVisual( index, mImpl->mVisuals, iter ) )
{
if ( !visualReplaced ) // New registration entry
{
- mImpl->mVisuals.PushBack( new RegisteredVisual( index, visual, actorToRegister ) );
+ mImpl->mVisuals.PushBack( new RegisteredVisual( index, visual, actorToRegister, enabled ) );
}
- if( visual && self.OnStage() )
+ if( visual && self.OnStage() && enabled )
{
visual.SetOnStage( placementActor );
}
void Control::UnregisterVisual( Property::Index index )
{
- RegisteredVisuals::Iterator iter;
+ RegisteredVisualContainer::Iterator iter;
if ( FindVisual( index, mImpl->mVisuals, iter ) )
{
mImpl->mVisuals.Erase( iter );
Toolkit::Visual::Base Control::GetVisual( Property::Index index ) const
{
- RegisteredVisuals::Iterator iter;
+ RegisteredVisualContainer::Iterator iter;
if ( FindVisual( index, mImpl->mVisuals, iter ) )
{
return (*iter)->visual;
return Toolkit::Visual::Base();
}
+void Control::EnableVisual( Property::Index index, bool enable )
+{
+ RegisteredVisualContainer::Iterator iter;
+ if ( FindVisual( index, mImpl->mVisuals, iter ) )
+ {
+ if ( (*iter)->enabled == enable )
+ {
+ return;
+ }
+
+ (*iter)->enabled = enable;
+ Actor parentActor = Self();
+ if ( (*iter)->placementActor )
+ {
+ parentActor = (*iter)->placementActor;
+ }
+
+ if ( Self().OnStage() ) // If control not on Stage then Visual will be added when StageConnection is called.
+ {
+ if ( enable )
+ {
+
+ (*iter)->visual.SetOnStage( parentActor );
+ }
+ else
+ {
+ (*iter)->visual.SetOffStage( parentActor ); // No need to call if control not staged.
+ }
+ }
+ }
+}
+
+bool Control::IsVisualEnabled( Property::Index index ) const
+{
+ RegisteredVisualContainer::Iterator iter;
+ if ( FindVisual( index, mImpl->mVisuals, iter ) )
+ {
+ return (*iter)->enabled;
+ }
+ return false;
+}
+
Actor Control::GetPlacementActor( Property::Index index ) const
{
- RegisteredVisuals::Iterator iter;
+ RegisteredVisualContainer::Iterator iter;
if ( FindVisual( index, mImpl->mVisuals, iter ) )
{
if( (*iter)->placementActor )
void Control::OnStageConnection( int depth )
{
- for(RegisteredVisuals::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
+ for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
{
// Check whether the visual is empty, as it is allowed to register a placement actor without visual.
- if( (*iter)->visual )
+ if( (*iter)->visual && (*iter)->enabled )
{
if( (*iter)->placementActor )
{
void Control::OnStageDisconnection()
{
- for(RegisteredVisuals::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
+ for(RegisteredVisualContainer::Iterator iter = mImpl->mVisuals.Begin(); iter!= mImpl->mVisuals.End(); iter++)
{
// Check whether the visual is empty, as it is allowed to register a placement actor without visual.
if( (*iter)->visual )
protected: // For derived classes to call
/**
- * @brief Register a visual by Property Index, linking an Actor to controlRenderer when required.
- * In the case of the visual being an actor or control deeming controlRenderer not required then controlRenderer should be an empty handle.
+ * @brief Register a visual by Property Index, linking an Actor to visual when required.
+ * In the case of the visual being an actor or control deeming visual not required then visual should be an empty handle.
* No parenting is done during registration, this should be done by derived class.
*
* @SINCE_1_2.0
* @param[in] index The Property index of the visual, used to reference visual
* @param[in] placementActor The actor used to by the visual.
* @param[in] visual The visual to register
- * @note Derived class must NOT call visual.SetOnStage(placementActor). It is the responsibility of the base class to connect/disconnect registered visual to stage.
+ * @note Derived class should not call visual.SetOnStage(placementActor). It is the responsibility of the base class to connect/disconnect registered visual to stage.
+ * Use below API with enabled set to false if derived class wishes to control when visual is staged.
*/
void RegisterVisual( Property::Index index, Actor& placementActor, Toolkit::Visual::Base& visual );
/**
+ * @brief Register a visual by Property Index, linking an Actor to visual when required.
+ * In the case of the visual being an actor or control deeming visual not required then visual should be an empty handle.
+ * If enabled is false then the visual is not set on stage until enabled by the derived class.
+ * @see EnableVisual
+ *
+ * @SINCE_1_2.11
+ *
+ * @param[in] index The Property index of the visual, used to reference visual
+ * @param[in] placementActor The actor used to by the visual.
+ * @param[in] visual The visual to register
+ * @param[in] enabled false if derived class wants to control when visual is set on stage.
+ *
+ */
+ void RegisterVisual( Property::Index index, Actor& placementActor, Toolkit::Visual::Base& visual, bool enabled );
+
+ /**
* @brief Erase the entry matching the given index from the list of registered visuals
* @param[in] index The Property index of the visual, used to reference visual
*
Toolkit::Visual::Base GetVisual( Property::Index index ) const;
/**
+ * @brief Sets the given visual to be displayed or not when parent staged.
+ *
+ * @SINCE_1_2.11
+ *
+ * @param[in] index The Property index of the visual
+ * @param[in] enable flag to set enabled or disabled.
+ */
+ void EnableVisual( Property::Index index, bool enable );
+
+ /**
+ * @brief Queries if the given visual is to be displayed when parent staged.
+ *
+ * @SINCE_1_2.11
+ *
+ * @param[in] index The Property index of the visual
+ * @return bool whether visual is enabled or not
+ */
+ bool IsVisualEnabled( Property::Index index ) const;
+
+ /**
* @brief Retrieve the placement actor associated with the given index.
*
* @SINCE_1_2.2
/**
* @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,
/**
* @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,
/**
* @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
*/
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 10;
+const unsigned int TOOLKIT_MICRO_VERSION = 11;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
$(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
--- /dev/null
+#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 <dali-toolkit/public-api/visuals/visual-properties.h>
+
+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
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
Name: dali-addon
Summary: DALi module for Node.JS
-Version: 1.2.10
+Version: 1.2.11
Release: 1
Group: Development/Libraries
License: Apache License, Version 2.0
Name: NDalic
Summary: dali wrapper
-Version: 1.0.0
+Version: 1.2.11
Release: 1
Group: uifw/graphic
License: TO_BE_FILLED_IN
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.2.10
+Version: 1.2.11
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-2-Clause and MIT
--- /dev/null
+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<ScrollContainer> _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<ScrollContainer> ();
+ _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);
+ }
+ }
+}
+
--- /dev/null
+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
+ }
+}
+
--- /dev/null
+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;}
+ }
+ }
+}
+
--- /dev/null
+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);
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+using Dali;
+using System;
+
+namespace FirstScreen
+{
+ public enum EdenEffectDirection
+ {
+ TopToBottom,
+ BottomToTop
+ };
+
+ public interface IEdenEffect
+ {
+ void FocusAnimation(View parentItem, Vector3 itemSize, float duration, EdenEffectDirection direction);
+ }
+}
+
--- /dev/null
+using System;
+
+namespace FirstScreen
+{
+ public class MainClass
+ {
+ [STAThread]
+ static void Main(string[] args)
+ {
+ FirstScreenApp.Run();
+ }
+ }
+}
+
--- /dev/null
+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<View> _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<View>();
+
+ 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;
+ }
+ }
+ }
+ }
+}
+