From e2fbffea1d7c5d3df04b025247c1a77377a3f0c3 Mon Sep 17 00:00:00 2001 From: David Steele Date: Thu, 23 Feb 2017 21:31:41 +0000 Subject: [PATCH] On state change, visuals now keep instance data If a visual such as a text visual has instance data (i.e. the text string) ensure that this is applied following a state change where the visual is removed and re-added. Added new method CreateInstancePropertyMap to Visual::Base::Impl, and methods DoCreateInstancePropertyMap to derived visuals for writing instance data into. So far, this is for text visual's text property and image visual's desired image size properties. TODO: Prevent the visual being re-added if no properties change (or only animatable properties change) (Whilst taking into account string vs index keys; Property Array vs Vector... [ Note: this is problematic for gradient visual, which generates a bunch of property arrays whilst Builder has generated Vectors from the equivalent JSON ] Change-Id: I742c47067fc19fbaeee2f01195f6f00501b16c85 Signed-off-by: David Steele --- .../src/dali-toolkit-styling/default-theme.json | 88 +++++- .../dali-toolkit-styling/utc-Dali-StyleManager.cpp | 315 ++++++++++++++++++--- .../dali-toolkit-test-utils/dummy-control.cpp | 13 +- .../dali-toolkit-test-utils/dummy-control.h | 5 +- dali-toolkit/internal/builder/builder-impl.cpp | 3 +- dali-toolkit/internal/builder/dictionary.h | 79 +++++- dali-toolkit/internal/builder/style.cpp | 74 ++++- dali-toolkit/internal/builder/style.h | 29 +- .../animated-image/animated-image-visual.cpp | 5 + .../visuals/animated-image/animated-image-visual.h | 5 + .../internal/visuals/border/border-visual.cpp | 5 + .../internal/visuals/border/border-visual.h | 5 + .../internal/visuals/color/color-visual.cpp | 6 + dali-toolkit/internal/visuals/color/color-visual.h | 5 + .../internal/visuals/gradient/gradient-visual.cpp | 5 + .../internal/visuals/gradient/gradient-visual.h | 5 + .../internal/visuals/image/image-visual.cpp | 16 ++ dali-toolkit/internal/visuals/image/image-visual.h | 5 + dali-toolkit/internal/visuals/mesh/mesh-visual.cpp | 5 + dali-toolkit/internal/visuals/mesh/mesh-visual.h | 5 + .../internal/visuals/npatch/npatch-visual.cpp | 5 + .../internal/visuals/npatch/npatch-visual.h | 5 + .../visuals/primitive/primitive-visual.cpp | 5 + .../internal/visuals/primitive/primitive-visual.h | 5 + dali-toolkit/internal/visuals/svg/svg-visual.cpp | 5 + dali-toolkit/internal/visuals/svg/svg-visual.h | 5 + dali-toolkit/internal/visuals/text/text-visual.cpp | 10 + dali-toolkit/internal/visuals/text/text-visual.h | 5 + dali-toolkit/internal/visuals/visual-base-impl.cpp | 14 + dali-toolkit/internal/visuals/visual-base-impl.h | 19 ++ .../visuals/wireframe/wireframe-visual.cpp | 5 + .../internal/visuals/wireframe/wireframe-visual.h | 5 + dali-toolkit/public-api/controls/control-impl.cpp | 270 ++++++++++++++++-- 33 files changed, 940 insertions(+), 96 deletions(-) diff --git a/automated-tests/src/dali-toolkit-styling/default-theme.json b/automated-tests/src/dali-toolkit-styling/default-theme.json index aea0422..4f9fb77 100644 --- a/automated-tests/src/dali-toolkit-styling/default-theme.json +++ b/automated-tests/src/dali-toolkit-styling/default-theme.json @@ -129,7 +129,12 @@ { "visuals": { - "foregroundVisual": + "testVisual": + { + "visualType":"IMAGE", + "url":"0001.png" + }, + "testVisual2": { "visualType":"GRADIENT", "startPosition": [-1, -1], @@ -137,6 +142,17 @@ "spreadMethod": "REPEAT", "stopOffset": [0.2, 0.8], "stopColor": [ [ 1,0,0,1], [0,1,0,1] ] + }, + "foregroundVisual": + { + "visualType":"IMAGE", + "url":"theSameImage.png" + }, + "labelVisual": + { + "visualType":"TEXT", + "pointSize":8, + "text":"Some text" } } }, @@ -144,10 +160,26 @@ { "visuals": { - "foregroundVisual": + "testVisual": + { + "visualType":"IMAGE", + "url":"0002.png" + }, + "testVisual2": { "visualType":"COLOR", "mixColor": [ 1,0,0,1] + }, + "foregroundVisual": + { + "visualType":"IMAGE", + "url":"theSameImage.png" + }, + "labelVisual": + { + "visualType":"TEXT", + "pointSize":8, + "text":"Some different text" } } } @@ -178,8 +210,8 @@ }, "focusVisual": { - "visualType":"IMAGE", - "url": "focus.png" + "visualType":"NPATCH", + "url": "focus.9.png" } }, "entryTransition": @@ -217,6 +249,29 @@ }, "DISABLED": { + "states": + { + "SELECTED": + { + "visuals": + { + "testVisual": + { + "visualType":"IMAGE", + "url":"0001.png" + }, + "testVisual2": + { + "visualType":"GRADIENT", + "startPosition": [-1, -1], + "endPosition": [1, 1], + "spreadMethod": "REPEAT", + "stopOffset": [0.2, 0.8], + "stopColor": [ [ 1,0,0,1], [0,1,0,1] ] + } + } + } + }, "visuals": { "foregroundVisual": @@ -255,6 +310,12 @@ "spreadMethod": "REPEAT", "stopOffset": [0.2, 0.8], "stopColor": [ [ 1,0,0,1], [0,1,0,1] ] + }, + "labelVisual": + { + "visualType":"TEXT", + "pointSize":8, + "textColor":[1,0,1,1] } } }, @@ -271,6 +332,11 @@ "stopOffset": [0.3, 0.9], "stopColor": [ [ 0,0,1,1], [0,1,1,1] ] }, + "labelVisual": + { + "visualType":"TEXT", + "pointSize":10 + }, "focusVisual": { "visualType":"IMAGE", @@ -318,6 +384,12 @@ { "visualType":"COLOR", "mixColor": [1,0,0,1] + }, + "labelVisual": + { + "visualType":"TEXT", + "pointSize":9, + "textColor":[1,1,1,1] } } } @@ -333,6 +405,14 @@ } } ] + }, + "NoStateStyle": + { + "testVisual2": + { + "visualType":"COLOR", + "mixColor":[1,1,1,1] + } } } } diff --git a/automated-tests/src/dali-toolkit-styling/utc-Dali-StyleManager.cpp b/automated-tests/src/dali-toolkit-styling/utc-Dali-StyleManager.cpp index 34f604a..6a81e06 100644 --- a/automated-tests/src/dali-toolkit-styling/utc-Dali-StyleManager.cpp +++ b/automated-tests/src/dali-toolkit-styling/utc-Dali-StyleManager.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include using namespace Dali; @@ -56,6 +58,54 @@ void dali_style_manager_cleanup(void) test_return_value = TET_PASS; } + +Visual::Base CheckVisual( Impl::DummyControl& dummyImpl, Property::Index visualId, int type, const char* location ) +{ + DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(visualId), true, location); + Visual::Base visual = dummyImpl.GetVisual(visualId); + DALI_TEST_EQUALS( (bool)visual, true, location ); + Property::Map map; + visual.CreatePropertyMap( map ); + Property::Value* value = map.Find( Visual::Property::TYPE ); + DALI_TEST_EQUALS( value != NULL, true, location ); + + int visualType; + value->Get( visualType ); + DALI_TEST_EQUALS( visualType, type, location ); + return visual; +} + + +Integration::Bitmap* CreateBitmap( unsigned int imageWidth, unsigned int imageHeight, unsigned int initialColor, Pixel::Format pixelFormat ) +{ + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight ); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + memset( pixbuffer, initialColor, imageHeight * imageWidth * bytesPerPixel ); + + return bitmap; +} + +Integration::ResourcePointer CustomizeNinePatch( TestApplication& application, + unsigned int ninePatchImageWidth, + unsigned int ninePatchImageHeight) +{ + TestPlatformAbstraction& platform = application.GetPlatform(); + + Pixel::Format pixelFormat = Pixel::RGBA8888; + + tet_infoline("Create Bitmap"); + platform.SetClosestImageSize(Vector2( ninePatchImageWidth, ninePatchImageHeight)); + Integration::Bitmap* bitmap = CreateBitmap( ninePatchImageWidth, ninePatchImageHeight, 0xFF, pixelFormat ); + + tet_infoline("Getting resource"); + Integration::ResourcePointer resourcePtr(bitmap); + platform.SetSynchronouslyLoadedResource( resourcePtr); + + return resourcePtr; +} + int UtcDaliStyleManagerConstructorP(void) { ToolkitTestApplication application; @@ -884,17 +934,38 @@ int UtcDaliStyleManagerSetState01(void) Stage::GetCurrent().Add(actor); Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + Integration::ResourcePointer ninePatch = CustomizeNinePatch( application, 30, 30 ); DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOREGROUND_VISUAL), true, TEST_LOCATION); Visual::Base visual1 = dummyImpl.GetVisual(DummyControl::Property::FOREGROUND_VISUAL); + Visual::Base labelVisual1 = dummyImpl.GetVisual(DummyControl::Property::LABEL_VISUAL); + Property::Map labelMap; + labelVisual1.CreatePropertyMap( labelMap ); + labelMap[TextVisual::Property::TEXT] = "New text"; + VisualFactory factory = VisualFactory::Get(); + labelVisual1 = factory.CreateVisual(labelMap); + dummyImpl.UnregisterVisual(DummyControl::Property::LABEL_VISUAL ); + dummyImpl.RegisterVisual(DummyControl::Property::LABEL_VISUAL, labelVisual1 ); actor.SetProperty( DevelControl::Property::STATE, DevelControl::FOCUSED ); DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOREGROUND_VISUAL), true, TEST_LOCATION); DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOCUS_VISUAL), true, TEST_LOCATION); + DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::LABEL_VISUAL), true, TEST_LOCATION); Visual::Base visual2 = dummyImpl.GetVisual(DummyControl::Property::FOREGROUND_VISUAL); + Visual::Base labelVisual2 = dummyImpl.GetVisual(DummyControl::Property::LABEL_VISUAL); DALI_TEST_CHECK( visual1 != visual2 ); + DALI_TEST_CHECK( labelVisual1 != labelVisual2 ); + labelMap.Clear(); + labelVisual2.CreatePropertyMap( labelMap ); + Property::Value* textValue = labelMap.Find( Toolkit::TextVisual::Property::TEXT, "text"); + DALI_TEST_CHECK( textValue ); + Property::Value* pointSizeValue = labelMap.Find( Toolkit::TextVisual::Property::POINT_SIZE, "pointSize"); + tet_infoline( "Check that the instance data has been copied to the new text visual\n"); + DALI_TEST_EQUALS( textValue->Get(), "New text", TEST_LOCATION ); + DALI_TEST_EQUALS( pointSizeValue->Get(), 10, TEST_LOCATION ); + actor.SetProperty( DevelControl::Property::STATE, DevelControl::DISABLED ); @@ -908,6 +979,17 @@ int UtcDaliStyleManagerSetState01(void) DALI_TEST_CHECK( visual1 != visual3 ); DALI_TEST_CHECK( visual2 != visual3 ); + Visual::Base labelVisual3 = dummyImpl.GetVisual(DummyControl::Property::LABEL_VISUAL); + DALI_TEST_CHECK( labelVisual2 != labelVisual3 ); + + labelVisual2.CreatePropertyMap( labelMap ); + textValue = labelMap.Find(Toolkit::TextVisual::Property::TEXT, "text"); + DALI_TEST_CHECK( textValue ); + pointSizeValue = labelMap.Find(Toolkit::TextVisual::Property::POINT_SIZE, "pointSize"); + tet_infoline( "Check that the instance data has been copied to the new text visual\n"); + DALI_TEST_EQUALS( textValue->Get(), "New text", TEST_LOCATION ); + DALI_TEST_EQUALS( pointSizeValue->Get(), 10, TEST_LOCATION ); + END_TEST; } @@ -928,6 +1010,7 @@ int UtcDaliStyleManagerSetState02(void) Stage::GetCurrent().Add(actor); Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + Integration::ResourcePointer ninePatch = CustomizeNinePatch( application, 30, 30 ); int state = actor.GetProperty( DevelControl::Property::STATE ); DALI_TEST_EQUALS( state, (int) DevelControl::NORMAL, TEST_LOCATION ); @@ -956,9 +1039,16 @@ int UtcDaliStyleManagerSetState02(void) DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOREGROUND_VISUAL), true, TEST_LOCATION); Visual::Base visual3 = dummyImpl.GetVisual(DummyControl::Property::FOREGROUND_VISUAL); - Visual::Base focusVisual = dummyImpl.GetVisual(DummyControl::Property::FOCUS_VISUAL); - DALI_TEST_CHECK( !focusVisual ); - DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOCUS_VISUAL), false, TEST_LOCATION); + + Visual::Base testVisual = dummyImpl.GetVisual(DummyControl::Property::FOCUS_VISUAL); + DALI_TEST_CHECK( !testVisual ); + testVisual = dummyImpl.GetVisual(DummyControl::Property::TEST_VISUAL); + DALI_TEST_CHECK( !testVisual ); + testVisual = dummyImpl.GetVisual(DummyControl::Property::TEST_VISUAL2); + DALI_TEST_CHECK( !testVisual ); + testVisual = dummyImpl.GetVisual(DummyControl::Property::LABEL_VISUAL); + DALI_TEST_CHECK( testVisual ); + DALI_TEST_CHECK( visual1 != visual3 ); DALI_TEST_CHECK( visual2 != visual3 ); @@ -974,7 +1064,7 @@ int UtcDaliStyleManagerSetState02(void) visual1 = dummyImpl.GetVisual(DummyControl::Property::FOREGROUND_VISUAL); DALI_TEST_CHECK( visual1 ); - focusVisual = dummyImpl.GetVisual(DummyControl::Property::FOCUS_VISUAL); + Visual::Base focusVisual = dummyImpl.GetVisual(DummyControl::Property::FOCUS_VISUAL); DALI_TEST_CHECK( !focusVisual ); DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOCUS_VISUAL), false, TEST_LOCATION); @@ -983,7 +1073,104 @@ int UtcDaliStyleManagerSetState02(void) } -int UtcDaliStyleManagerSetSubState(void) +int UtcDaliStyleManagerSetState03N(void) +{ + tet_infoline("Instantiate dummy control and test state transition without state style" ); + Test::StyleMonitor::SetThemeFileOutput( DALI_STYLE_DIR "dali-toolkit-default-theme.json", + defaultTheme ); + + ToolkitTestApplication application; + + StyleChangedSignalChecker styleChangedSignalHandler; + Dali::StyleMonitor styleMonitor = Dali::StyleMonitor::Get(); + StyleManager styleManager = StyleManager::Get(); + + DummyControl actor = DummyControl::New(true); + actor.SetStyleName("NoStyles"); + Stage::GetCurrent().Add(actor); + + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + Property::Map propertyMap; + propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR); + propertyMap.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE); + VisualFactory factory = VisualFactory::Get(); + Visual::Base visual = factory.CreateVisual( propertyMap ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + int state = actor.GetProperty( DevelControl::Property::STATE ); + DALI_TEST_EQUALS( state, (int) DevelControl::NORMAL, TEST_LOCATION ); + + actor.SetProperty( DevelControl::Property::STATE, + Property::Map().Add( "state", "FOCUSED" ).Add("withTransitions", false)); + + Visual::Base testVisual = dummyImpl.GetVisual(DummyControl::Property::TEST_VISUAL); + DALI_TEST_CHECK( testVisual = visual ); + + state = actor.GetProperty( DevelControl::Property::STATE ); + DALI_TEST_EQUALS( state, (int) DevelControl::FOCUSED, TEST_LOCATION ); + + actor.SetProperty( DevelControl::Property::STATE, + Property::Map().Add( "state", "DISABLED" ).Add("withTransitions", false)); + + testVisual = dummyImpl.GetVisual(DummyControl::Property::TEST_VISUAL); + DALI_TEST_CHECK( testVisual = visual ); + + state = actor.GetProperty( DevelControl::Property::STATE ); + DALI_TEST_EQUALS( state, (int) DevelControl::DISABLED, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliStyleManagerSetState04N(void) +{ + tet_infoline("Instantiate dummy control and test state transition with style without state" ); + Test::StyleMonitor::SetThemeFileOutput( DALI_STYLE_DIR "dali-toolkit-default-theme.json", + defaultTheme ); + + ToolkitTestApplication application; + + StyleChangedSignalChecker styleChangedSignalHandler; + Dali::StyleMonitor styleMonitor = Dali::StyleMonitor::Get(); + StyleManager styleManager = StyleManager::Get(); + + DummyControl actor = DummyControl::New(true); + actor.SetStyleName("NoStateStyle"); + Stage::GetCurrent().Add(actor); + + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + Property::Map propertyMap; + propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR); + propertyMap.Insert(ColorVisual::Property::MIX_COLOR, Color::BLUE); + VisualFactory factory = VisualFactory::Get(); + Visual::Base visual = factory.CreateVisual( propertyMap ); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + + int state = actor.GetProperty( DevelControl::Property::STATE ); + DALI_TEST_EQUALS( state, (int) DevelControl::NORMAL, TEST_LOCATION ); + + actor.SetProperty( DevelControl::Property::STATE, + Property::Map().Add( "state", "FOCUSED" ).Add("withTransitions", false)); + + Visual::Base testVisual = dummyImpl.GetVisual(DummyControl::Property::TEST_VISUAL); + DALI_TEST_CHECK( testVisual = visual ); + + state = actor.GetProperty( DevelControl::Property::STATE ); + DALI_TEST_EQUALS( state, (int) DevelControl::FOCUSED, TEST_LOCATION ); + + actor.SetProperty( DevelControl::Property::STATE, + Property::Map().Add( "state", "DISABLED" ).Add("withTransitions", false)); + + testVisual = dummyImpl.GetVisual(DummyControl::Property::TEST_VISUAL); + DALI_TEST_CHECK( testVisual = visual ); + + state = actor.GetProperty( DevelControl::Property::STATE ); + DALI_TEST_EQUALS( state, (int) DevelControl::DISABLED, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliStyleManagerSetSubState01(void) { tet_infoline("Instantiate dummy control and test state/visual/transition capture" ); Test::StyleMonitor::SetThemeFileOutput( DALI_STYLE_DIR "dali-toolkit-default-theme.json", @@ -1001,53 +1188,97 @@ int UtcDaliStyleManagerSetSubState(void) actor.SetStyleName("ComplexControl"); Stage::GetCurrent().Add(actor); + Integration::ResourcePointer ninePatch = CustomizeNinePatch( application, 30, 30 ); + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); - { - DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOREGROUND_VISUAL), true, TEST_LOCATION); - Visual::Base visual = dummyImpl.GetVisual(DummyControl::Property::FOREGROUND_VISUAL); - DALI_TEST_CHECK( visual ); - Property::Map map; - visual.CreatePropertyMap( map ); - Property::Value* value = map.Find( Visual::Property::TYPE ); - DALI_TEST_CHECK( value ); + CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL2, Toolkit::Visual::GRADIENT, TEST_LOCATION); - int visualType; - value->Get( visualType ); - DALI_TEST_EQUALS( visualType, (int)Toolkit::Visual::GRADIENT, TEST_LOCATION ); - } + actor.SetProperty(DevelControl::Property::SUB_STATE, "UNSELECTED"); + + CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL2, Toolkit::Visual::COLOR, TEST_LOCATION); + + actor.SetProperty(DevelControl::Property::SUB_STATE, "SELECTED"); + + CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL2, Toolkit::Visual::GRADIENT, TEST_LOCATION); + + END_TEST; +} + + +int UtcDaliStyleManagerSetSubState02(void) +{ + tet_infoline("Instantiate complex control and test state/substate change" ); + Test::StyleMonitor::SetThemeFileOutput( DALI_STYLE_DIR "dali-toolkit-default-theme.json", + defaultTheme ); + + ToolkitTestApplication application; + + StyleChangedSignalChecker styleChangedSignalHandler; + Dali::StyleMonitor styleMonitor = Dali::StyleMonitor::Get(); + StyleManager styleManager = StyleManager::Get(); + + DummyControl actor = DummyControl::New(true); + actor.SetProperty(DevelControl::Property::STATE, "NORMAL"); + actor.SetProperty(DevelControl::Property::SUB_STATE, "SELECTED"); + tet_infoline( "Setting state to NORMAL/SELECTED before re-styling\n"); + + actor.SetStyleName("ComplexControl"); + Stage::GetCurrent().Add(actor); + + Integration::ResourcePointer ninePatch = CustomizeNinePatch( application, 30, 30 ); + + Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); + + CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL2, Toolkit::Visual::GRADIENT, TEST_LOCATION); actor.SetProperty(DevelControl::Property::SUB_STATE, "UNSELECTED"); + tet_infoline( "Changing substate to UNSELECTED - check visual changes\n"); - { - DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOREGROUND_VISUAL), true, TEST_LOCATION); - Visual::Base visual = dummyImpl.GetVisual(DummyControl::Property::FOREGROUND_VISUAL); - DALI_TEST_CHECK( visual ); - Property::Map map; - visual.CreatePropertyMap( map ); - Property::Value* value = map.Find( Visual::Property::TYPE ); - DALI_TEST_CHECK( value ); + CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL2, Toolkit::Visual::COLOR, TEST_LOCATION); - int visualType; - value->Get( visualType ); - DALI_TEST_EQUALS( visualType, (int)Toolkit::Visual::COLOR, TEST_LOCATION ); - } + actor.SetProperty(DevelControl::Property::STATE, "FOCUSED"); + tet_infoline( "Changing state to FOCUSED - check visual changes\n"); + + Visual::Base fgVisual1 = CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::GRADIENT, TEST_LOCATION); + Visual::Base focusVisual1 = CheckVisual( dummyImpl, DummyControl::Property::FOCUS_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); actor.SetProperty(DevelControl::Property::SUB_STATE, "SELECTED"); + tet_infoline( "Changing substate to SELECTED - Expect no change\n"); - { - Impl::DummyControl& dummyImpl = static_cast(actor.GetImplementation()); - DALI_TEST_EQUALS(dummyImpl.IsVisualEnabled(DummyControl::Property::FOREGROUND_VISUAL), true, TEST_LOCATION); - Visual::Base visual = dummyImpl.GetVisual(DummyControl::Property::FOREGROUND_VISUAL); - DALI_TEST_CHECK( visual ); - Property::Map map; - visual.CreatePropertyMap( map ); - Property::Value* value = map.Find( Visual::Property::TYPE ); - DALI_TEST_CHECK( value ); + Visual::Base fgVisual2 = CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::GRADIENT, TEST_LOCATION); + Visual::Base focusVisual2 = CheckVisual( dummyImpl, DummyControl::Property::FOCUS_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + + DALI_TEST_CHECK( fgVisual1 == fgVisual2 ); + DALI_TEST_CHECK( focusVisual1 == focusVisual2 ); + + actor.SetProperty(DevelControl::Property::STATE, "NORMAL"); + tet_infoline( "Changing state to NORMAL - Expect to change to NORMAL/SELECTED \n"); + + CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL2, Toolkit::Visual::GRADIENT, TEST_LOCATION); + + Visual::Base focusVisual = dummyImpl.GetVisual(DummyControl::Property::FOCUS_VISUAL); + DALI_TEST_CHECK( ! focusVisual ); + + actor.SetProperty(DevelControl::Property::STATE, "DISABLED"); + tet_infoline( "Changing state to DISABLED - Expect to change to DISABLED/SELECTED \n"); + + CheckVisual( dummyImpl, DummyControl::Property::FOREGROUND_VISUAL, Toolkit::Visual::COLOR, TEST_LOCATION); + CheckVisual( dummyImpl, DummyControl::Property::TEST_VISUAL, Toolkit::Visual::IMAGE, TEST_LOCATION); + + Visual::Base testVisual = dummyImpl.GetVisual(DummyControl::Property::FOCUS_VISUAL); + DALI_TEST_CHECK( ! testVisual ); + testVisual = dummyImpl.GetVisual(DummyControl::Property::LABEL_VISUAL); + DALI_TEST_CHECK( ! testVisual ); - int visualType; - value->Get( visualType ); - DALI_TEST_EQUALS( visualType, (int)Toolkit::Visual::GRADIENT, TEST_LOCATION ); - } END_TEST; } diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp index 979e56a..8f70228 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp @@ -72,7 +72,7 @@ Dali::PropertyRegistration dummyControlVisualProperty01( typeRegistration, "testVisual", Dali::Toolkit::DummyControl::Property::TEST_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty ); Dali::PropertyRegistration dummyControlVisualProperty02( - typeRegistration, "testVisual", Dali::Toolkit::DummyControl::Property::TEST_VISUAL2, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty ); + typeRegistration, "testVisual2", Dali::Toolkit::DummyControl::Property::TEST_VISUAL2, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty ); Dali::PropertyRegistration dummyControlVisualProperty03( typeRegistration, "foregroundVisual", Dali::Toolkit::DummyControl::Property::FOREGROUND_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty ); @@ -80,6 +80,9 @@ Dali::PropertyRegistration dummyControlVisualProperty03( Dali::PropertyRegistration dummyControlVisualProperty04( typeRegistration, "focusVisual", Dali::Toolkit::DummyControl::Property::FOCUS_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty ); +Dali::PropertyRegistration dummyControlVisualProperty05( + typeRegistration, "labelVisual", Dali::Toolkit::DummyControl::Property::LABEL_VISUAL, Dali::Property::MAP, &Dali::Toolkit::DummyControlImpl::SetProperty, &Dali::Toolkit::DummyControlImpl::GetProperty ); + } DummyControl DummyControlImpl::New() @@ -125,6 +128,12 @@ void DummyControlImpl::RegisterVisual( Property::Index index, Toolkit::Visual::B void DummyControlImpl::UnregisterVisual( Property::Index index ) { Control::UnregisterVisual( index ); + + VisualIndices::iterator iter = std::find( mRegisteredVisualIndices.begin(), mRegisteredVisualIndices.end(), index ); + if( iter != mRegisteredVisualIndices.end() ) + { + mRegisteredVisualIndices.erase(iter); + } } Toolkit::Visual::Base DummyControlImpl::GetVisual( Property::Index index ) @@ -142,7 +151,6 @@ bool DummyControlImpl::IsVisualEnabled( Property::Index index ) return Control::IsVisualEnabled( index ); } - Animation DummyControlImpl::CreateTransition( const Toolkit::TransitionData& transition ) { return Control::CreateTransition( transition ); @@ -159,6 +167,7 @@ void DummyControlImpl::SetProperty( BaseObject* object, Dali::Property::Index in case Toolkit::DummyControl::Property::TEST_VISUAL2: case Toolkit::DummyControl::Property::FOREGROUND_VISUAL: case Toolkit::DummyControl::Property::FOCUS_VISUAL: + case Toolkit::DummyControl::Property::LABEL_VISUAL: { Property::Map* map = value.GetMap(); if( map != NULL ) diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h index 75d3efe..d4b8b18 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h @@ -48,7 +48,8 @@ public: TEST_VISUAL = PROPERTY_START_INDEX, TEST_VISUAL2, FOREGROUND_VISUAL, - FOCUS_VISUAL + FOCUS_VISUAL, + LABEL_VISUAL }; }; @@ -92,7 +93,7 @@ public: void UnregisterVisual( Property::Index index ); void EnableVisual( Property::Index index, bool enabled ); bool IsVisualEnabled( Property::Index index ); - + int GetVisualCount(); Toolkit::Visual::Base GetVisual( Property::Index index ); Animation CreateTransition( const Toolkit::TransitionData& transition ); diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index 48d2e2b..e4ef639 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -1139,7 +1139,8 @@ void Builder::ApplyAllStyleProperties( const TreeNode& root, const TreeNode& nod if( matchedStyle ) { StylePtr style( *matchedStyle ); - style->ApplyVisualsAndPropertiesRecursively( handle ); // (recurses through states) + Dictionary instancedProperties; + style->ApplyVisualsAndPropertiesRecursively( handle, instancedProperties ); } else // If there were no styles, instead set properties { diff --git a/dali-toolkit/internal/builder/dictionary.h b/dali-toolkit/internal/builder/dictionary.h index ccccf2c..88095eb 100644 --- a/dali-toolkit/internal/builder/dictionary.h +++ b/dali-toolkit/internal/builder/dictionary.h @@ -36,6 +36,23 @@ namespace Internal * * It enables lookup of keys via case-insensitive match. */ + + +typedef std::vector DictionaryKeys; +inline void Merge( DictionaryKeys& toDict, const DictionaryKeys& fromDict ) +{ + for( DictionaryKeys::const_iterator fromIter = fromDict.begin(); fromIter != fromDict.end(); ++fromIter ) + { + const std::string& fromKey = (*fromIter); + DictionaryKeys::iterator toIter = std::find( toDict.begin(), toDict.end(), fromKey ); + if( toIter == toDict.end() ) + { + toDict.push_back( fromKey ); + } + } +} + + template class Dictionary { @@ -62,7 +79,6 @@ public: */ typedef typename Elements::const_iterator iterator; - /** * Constructor */ @@ -105,6 +121,53 @@ public: } /** + * Remove a key value pair from the dictionary. + */ + void Remove( const std::string& name ) + { + for( typename Elements::iterator iter = container.begin(); iter != container.end(); ++iter ) + { + if( iter->key == name ) + { + container.erase( iter ); + break; + } + } + } + + /** + * Remove a key value pair from the dictionary. + */ + void Remove( const char* name ) + { + if( name != NULL ) + { + std::string theName(name); + Remove(theName); + } + } + + void Merge( const Dictionary& dictionary ) + { + for( typename Elements::const_iterator fromIter = dictionary.container.begin(); fromIter != dictionary.container.end(); ++fromIter ) + { + bool found=false; + for( typename Elements::iterator toIter = container.begin(); toIter != container.end(); ++toIter ) + { + if( fromIter->key == toIter->key ) + { + found=true; + toIter->entry = fromIter->entry; + } + } + if( !found ) + { + container.push_back( Element(fromIter->key, fromIter->entry) ); + } + } + } + + /** * Find the element in the dictionary pointed at by key, and * insensitive search, and return a const pointer to it, or NULL */ @@ -187,6 +250,20 @@ public: { return container.end(); } + + void GetKeys( DictionaryKeys& keys ) const + { + keys.clear(); + for( typename Elements::const_iterator iter = container.begin(); iter != container.end(); ++iter ) + { + keys.push_back( (*iter).key ); + } + } + + void Clear() + { + container.clear(); + } }; diff --git a/dali-toolkit/internal/builder/style.cpp b/dali-toolkit/internal/builder/style.cpp index 515ddd9..988bd61 100644 --- a/dali-toolkit/internal/builder/style.cpp +++ b/dali-toolkit/internal/builder/style.cpp @@ -18,7 +18,9 @@ #include #include #include +#include #include +#include namespace Dali { @@ -37,9 +39,11 @@ StylePtr Style::New() return stylePtr; } -void Style::ApplyVisualsAndPropertiesRecursively( Handle handle ) const +void Style::ApplyVisualsAndPropertiesRecursively( + Handle handle, + const Dictionary& instancedProperties ) const { - ApplyVisuals( handle ); + ApplyVisuals( handle, instancedProperties ); ApplyProperties( handle ); Toolkit::Control control = Toolkit::Control::DownCast(handle); @@ -59,7 +63,7 @@ void Style::ApplyVisualsAndPropertiesRecursively( Handle handle ) const const StylePtr statePtr(*stylePtr); // We have a state match. - statePtr->ApplyVisuals( handle ); + statePtr->ApplyVisuals( handle, instancedProperties ); statePtr->ApplyProperties( handle ); // Apply substate visuals @@ -72,7 +76,7 @@ void Style::ApplyVisualsAndPropertiesRecursively( Handle handle ) const { const StylePtr subStatePtr(*stylePtr); // We have a sub-state match. - subStatePtr->ApplyVisuals( handle ); + subStatePtr->ApplyVisuals( handle, instancedProperties ); subStatePtr->ApplyProperties( handle ); } } @@ -81,18 +85,66 @@ void Style::ApplyVisualsAndPropertiesRecursively( Handle handle ) const } } -void Style::ApplyVisuals( Handle handle ) const +void Style::ApplyVisuals( + Handle handle, + const Dictionary& instancedProperties ) const { - for( Dictionary::iterator iter = visuals.Begin(); iter != visuals.End() ; ++iter ) + ApplyVisuals( handle, visuals, instancedProperties ); +} + +void Style::ApplyVisuals( + Handle handle, + const Dictionary& visualMaps, + const Dictionary& instancedProperties ) +{ + for( Dictionary::iterator iter = visualMaps.Begin(); iter != visualMaps.End() ; ++iter ) { const std::string& visualName = (*iter).key; - const Property::Map& map = (*iter).entry; - Dali::Property::Index index = handle.GetPropertyIndex( visualName ); - if( index != Property::INVALID_INDEX ) + Property::Map map = (*iter).entry; + Property::Map* instancedMap = instancedProperties.Find( visualName ); + ApplyVisual( handle, visualName, map, instancedMap ); + } +} + +void Style::ApplyVisual( + Handle handle, + const std::string& visualName, + const Property::Map& visualMap, + const Property::Map* instancedProperties ) +{ + // Check if this visual name is a valid property of handle + Dali::Property::Index index = handle.GetPropertyIndex( visualName ); + if( index != Property::INVALID_INDEX ) + { + const Property::Map* applyMap = &visualMap; + Property::Map mergedMap; + + // If there are instanced properties, and the visual types match, + // merge them into the visual map + if( instancedProperties ) { - const Property::Value value(const_cast(map)); - handle.SetProperty( index, value ); + Property::Value* instanceTypeValue = instancedProperties->Find( Toolkit::DevelVisual::Property::TYPE); + Property::Value* newTypeValue = visualMap.Find( Toolkit::DevelVisual::Property::TYPE, VISUAL_TYPE ); + if( instanceTypeValue && newTypeValue ) + { + int instanceVisualType=-1; + int newVisualType=-1; + Scripting::GetEnumerationProperty( *instanceTypeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, instanceVisualType ); + Scripting::GetEnumerationProperty( *newTypeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, newVisualType ); + + if( instanceVisualType == newVisualType ) + { + // Same type - merge remaining instance data + mergedMap.Merge( visualMap ); + mergedMap.Merge( *instancedProperties ); + applyMap = &mergedMap; + } + } } + + // Apply the visual property map to the handle + const Property::Value value(const_cast(*applyMap)); + handle.SetProperty( index, value ); } } diff --git a/dali-toolkit/internal/builder/style.h b/dali-toolkit/internal/builder/style.h index bd26a6d..441f568 100644 --- a/dali-toolkit/internal/builder/style.h +++ b/dali-toolkit/internal/builder/style.h @@ -55,16 +55,41 @@ public: * through sub-states. * * @param[in] handle The handle to apply the visuals to + * @param[in] instancedProperties The maps from which to get instanced properties */ - void ApplyVisualsAndPropertiesRecursively( Handle handle ) const; + void ApplyVisualsAndPropertiesRecursively( Handle handle, + const Dictionary& instancedProperties ) const; /** * Apply the visuals of the style to the control pointed at by * handle. * * @param[in] handle The handle to apply the visuals to + * @param[in] instancedProperties The maps from which to get instanced properties */ - void ApplyVisuals( Handle handle ) const; + void ApplyVisuals( Handle handle, + const Dictionary& instancedProperties ) const; + + /** + * Apply the properties from the visualMaps and the instancedProperties + * to the control pointed at by handle. + * + * @param[in] handle The handle to apply the properties to + * @param[in] visualMaps The visual maps from which to get the styled properties + * @param[in] instancedProperties The maps from which to get instanced properties + */ + static void ApplyVisuals( Handle handle, + const Dictionary& visualMaps, + const Dictionary& instancedProperties ); + + /** + * Apply the properties from the visualMap and optional instancedProperties + * to the control pointed at by handle. + */ + static void ApplyVisual( Handle handle, + const std::string& visualName, + const Property::Map& visualMap, + const Property::Map* instancedProperties ); /** * Apply the properties of the style to the control pointed at by diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp index 2b58ce9..0031bc3 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -113,6 +113,11 @@ void AnimatedImageVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV ); } +void AnimatedImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + void AnimatedImageVisual::DoSetProperties( const Property::Map& propertyMap ) { // url already passed in from constructor diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h index d19fd09..e89fec6 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h @@ -99,6 +99,11 @@ public: // from Visual */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/border/border-visual.cpp b/dali-toolkit/internal/visuals/border/border-visual.cpp index 13b8633..2329167 100644 --- a/dali-toolkit/internal/visuals/border/border-visual.cpp +++ b/dali-toolkit/internal/visuals/border/border-visual.cpp @@ -226,6 +226,11 @@ void BorderVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::BorderVisual::Property::ANTI_ALIASING, mAntiAliasing ); } +void BorderVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + void BorderVisual::OnSetTransform() { if( mImpl->mRenderer ) diff --git a/dali-toolkit/internal/visuals/border/border-visual.h b/dali-toolkit/internal/visuals/border/border-visual.h index 7efb142..473080b 100644 --- a/dali-toolkit/internal/visuals/border/border-visual.h +++ b/dali-toolkit/internal/visuals/border/border-visual.h @@ -91,6 +91,11 @@ protected: virtual void DoCreatePropertyMap( Property::Map& map ) const; /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + + /** * @copydoc Visual::Base::OnSetTransform */ virtual void OnSetTransform(); diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index 0ac80d6..1691888 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -138,6 +138,12 @@ void ColorVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::ColorVisual::Property::MIX_COLOR, mImpl->mMixColor ); } +void ColorVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + + void ColorVisual::OnSetTransform() { if( mImpl->mRenderer ) diff --git a/dali-toolkit/internal/visuals/color/color-visual.h b/dali-toolkit/internal/visuals/color/color-visual.h index e5f6df1..939d40e 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.h +++ b/dali-toolkit/internal/visuals/color/color-visual.h @@ -65,6 +65,11 @@ public: // from Visual */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp index 4ea6a28..fbce369 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp @@ -323,6 +323,11 @@ void GradientVisual::DoCreatePropertyMap( Property::Map& map ) const } } +void GradientVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + void GradientVisual::InitializeRenderer() { Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.h b/dali-toolkit/internal/visuals/gradient/gradient-visual.h index c64b588..9c84cf2 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.h +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.h @@ -100,6 +100,11 @@ public: // from Visual */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index f6e2a9f..aa3c118 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -789,6 +789,22 @@ void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV ); } +void ImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + map.Clear(); + map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::Visual::IMAGE ); + if( !mImageUrl.empty() ) + { + map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, mDesiredSize.GetWidth() ); + map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, mDesiredSize.GetHeight() ); + } + else if( mImage ) + { + map.Insert( Toolkit::ImageVisual::Property::DESIRED_WIDTH, static_cast(mImage.GetWidth()) ); + map.Insert( Toolkit::ImageVisual::Property::DESIRED_HEIGHT, static_cast(mImage.GetHeight()) ); + } +} + void ImageVisual::OnSetTransform() { if( mImpl->mRenderer ) diff --git a/dali-toolkit/internal/visuals/image/image-visual.h b/dali-toolkit/internal/visuals/image/image-visual.h index 52312ea..b0cc262 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.h +++ b/dali-toolkit/internal/visuals/image/image-visual.h @@ -152,6 +152,11 @@ public: // from Visual */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/mesh/mesh-visual.cpp b/dali-toolkit/internal/visuals/mesh/mesh-visual.cpp index 051dfa3..190c457 100644 --- a/dali-toolkit/internal/visuals/mesh/mesh-visual.cpp +++ b/dali-toolkit/internal/visuals/mesh/mesh-visual.cpp @@ -533,6 +533,11 @@ void MeshVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::MeshVisual::Property::LIGHT_POSITION, mLightPosition ); } +void MeshVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + void MeshVisual::InitializeRenderer() { //Try to load the geometry from the file. diff --git a/dali-toolkit/internal/visuals/mesh/mesh-visual.h b/dali-toolkit/internal/visuals/mesh/mesh-visual.h index 2c227a3..511ce49 100644 --- a/dali-toolkit/internal/visuals/mesh/mesh-visual.h +++ b/dali-toolkit/internal/visuals/mesh/mesh-visual.h @@ -75,6 +75,11 @@ public: // from Visual */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp index 6ecb818..31e6344 100644 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp @@ -324,6 +324,11 @@ void NPatchVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly ); } +void NPatchVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + NPatchVisual::NPatchVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), mLoader( factoryCache.GetNPatchLoader() ), diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.h b/dali-toolkit/internal/visuals/npatch/npatch-visual.h index 0a0465f..22b60d5 100644 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.h +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.h @@ -100,6 +100,11 @@ public: // from Visual */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/primitive/primitive-visual.cpp b/dali-toolkit/internal/visuals/primitive/primitive-visual.cpp index 748564e..9d306be 100644 --- a/dali-toolkit/internal/visuals/primitive/primitive-visual.cpp +++ b/dali-toolkit/internal/visuals/primitive/primitive-visual.cpp @@ -438,6 +438,11 @@ void PrimitiveVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::PrimitiveVisual::Property::LIGHT_POSITION, mLightPosition ); } +void PrimitiveVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + void PrimitiveVisual::OnSetTransform() { if( mImpl->mRenderer ) diff --git a/dali-toolkit/internal/visuals/primitive/primitive-visual.h b/dali-toolkit/internal/visuals/primitive/primitive-visual.h index 6b210bd..677df9d 100644 --- a/dali-toolkit/internal/visuals/primitive/primitive-visual.h +++ b/dali-toolkit/internal/visuals/primitive/primitive-visual.h @@ -122,6 +122,11 @@ public: // from Visual */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index ad352af..73d29e0 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -144,6 +144,11 @@ void SvgVisual::DoCreatePropertyMap( Property::Map& map ) const } } +void SvgVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + void SvgVisual::ParseFromUrl( const std::string& imageUrl ) { mImageUrl = imageUrl; diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.h b/dali-toolkit/internal/visuals/svg/svg-visual.h index 26e7208..3369901 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.h +++ b/dali-toolkit/internal/visuals/svg/svg-visual.h @@ -90,6 +90,11 @@ public: // from Visual */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index 55b1478..77a680f 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -261,6 +261,16 @@ void TextVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::TextVisual::Property::ENABLE_MARKUP, mController->IsMarkupProcessorEnabled() ); } +void TextVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + map.Clear(); + map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::DevelVisual::TEXT ); + std::string text; + mController->GetText( text ); + map.Insert( Toolkit::TextVisual::Property::TEXT, text ); +} + + TextVisual::TextVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), mController( Text::Controller::New() ), diff --git a/dali-toolkit/internal/visuals/text/text-visual.h b/dali-toolkit/internal/visuals/text/text-visual.h index b0bf8c3..b11f548 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.h +++ b/dali-toolkit/internal/visuals/text/text-visual.h @@ -98,6 +98,11 @@ public: // from Visual::Base */ virtual void DoCreatePropertyMap( Property::Map& map ) const; + /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + protected: /** diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 0d2b050..bfd5293 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -287,6 +287,20 @@ void Visual::Base::CreatePropertyMap( Property::Map& map ) const map.Insert( DevelVisual::Property::OPACITY, mImpl->mMixColor.a ); } +void Visual::Base::CreateInstancePropertyMap( Property::Map& map ) const +{ + DoCreateInstancePropertyMap( map ); + + if( mImpl->mCustomShader ) + { + mImpl->mCustomShader->CreatePropertyMap( map ); + } + + //map.Insert( DevelVisual::Property::DEPTH_INDEX, mImpl->mDepthIndex ); + //map.Insert( DevelVisual::Property::ENABLED, (bool) mImpl->mRenderer ); +} + + void Visual::Base::EnablePreMultipliedAlpha( bool preMultipled ) { if( preMultipled ) diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index e7d8ddd..15b2539 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -131,6 +131,16 @@ public: void CreatePropertyMap( Property::Map& map ) const; /** + * @brief Create a property map containing per-instance visual properties. + * + * This will enable creation of new visuals on control state change with + * any alternative style properties and the relevant instance properties + * (e.g. for image visual, the desired size, and for text visual, the actual text). + * @param[in] map The property map into which to write + */ + void CreateInstancePropertyMap( Property::Map& map ) const; + + /** * @brief Set whether the Pre-multiplied Alpha Blending is required * * @param[in] preMultipled whether alpha is pre-multiplied. @@ -222,6 +232,15 @@ protected: virtual void DoCreatePropertyMap( Property::Map& map ) const = 0; /** + * @brief Called by CreateInstancePropertyMap() allowing derived + * classes to store instanced data (separate to styled data) that + * needs copying between visuals on state change. + * + * @param[out] map The visual property map + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const = 0; + + /** * @brief Called by SetProperties() allowing sub classes to set their properties * * @param[in] propertyMap The properties for the requested Visual object. diff --git a/dali-toolkit/internal/visuals/wireframe/wireframe-visual.cpp b/dali-toolkit/internal/visuals/wireframe/wireframe-visual.cpp index 764ba27..990b25f 100644 --- a/dali-toolkit/internal/visuals/wireframe/wireframe-visual.cpp +++ b/dali-toolkit/internal/visuals/wireframe/wireframe-visual.cpp @@ -153,6 +153,11 @@ void WireframeVisual::DoCreatePropertyMap( Property::Map& map ) const } } +void WireframeVisual::DoCreateInstancePropertyMap( Property::Map& map ) const +{ + // Do nothing +} + void WireframeVisual::DoSetProperties( const Property::Map& propertyMap ) { Property::Value* mixValue = propertyMap.Find( Toolkit::DevelVisual::Property::MIX_COLOR, MIX_COLOR ); diff --git a/dali-toolkit/internal/visuals/wireframe/wireframe-visual.h b/dali-toolkit/internal/visuals/wireframe/wireframe-visual.h index f446806..9edeca8 100644 --- a/dali-toolkit/internal/visuals/wireframe/wireframe-visual.h +++ b/dali-toolkit/internal/visuals/wireframe/wireframe-visual.h @@ -109,6 +109,11 @@ protected: // from Visual::Base virtual void DoCreatePropertyMap( Property::Map& map ) const; /** + * @copydoc Visual::Base::CreateInstancePropertyMap + */ + virtual void DoCreateInstancePropertyMap( Property::Map& map ) const; + + /** * @copydoc Visual::Base::DoSetProperties() */ virtual void DoSetProperties( const Property::Map& propertyMap ); diff --git a/dali-toolkit/public-api/controls/control-impl.cpp b/dali-toolkit/public-api/controls/control-impl.cpp index e77c28b..c89ae0c 100644 --- a/dali-toolkit/public-api/controls/control-impl.cpp +++ b/dali-toolkit/public-api/controls/control-impl.cpp @@ -40,8 +40,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -535,13 +537,233 @@ public: return value; } - void SetState( DevelControl::State state, bool withTransitions=true ) + + void CopyInstancedProperties( RegisteredVisualContainer& visuals, Dictionary& instancedProperties ) + { + for(RegisteredVisualContainer::Iterator iter = visuals.Begin(); iter!= visuals.End(); iter++) + { + if( (*iter)->visual ) + { + Property::Map instanceMap; + Toolkit::GetImplementation((*iter)->visual).CreateInstancePropertyMap(instanceMap); + instancedProperties.Add( (*iter)->visual.GetName(), instanceMap ); + } + } + } + + template + void Remove( Dictionary& keyValues, const std::string& name ) + { + keyValues.Remove(name); + } + + void Remove( DictionaryKeys& keys, const std::string& name ) + { + DictionaryKeys::iterator iter = std::find( keys.begin(), keys.end(), name ); + if( iter != keys.end()) + { + keys.erase(iter); + } + } + + void FindChangableVisuals( Dictionary& stateVisualsToAdd, + Dictionary& stateVisualsToChange, + DictionaryKeys& stateVisualsToRemove) + { + DictionaryKeys copyOfStateVisualsToRemove = stateVisualsToRemove; + + for( DictionaryKeys::iterator iter = copyOfStateVisualsToRemove.begin(); + iter != copyOfStateVisualsToRemove.end(); ++iter ) + { + const std::string& visualName = (*iter); + Property::Map* toMap = stateVisualsToAdd.Find( visualName ); + if( toMap ) + { + stateVisualsToChange.Add( visualName, *toMap ); + stateVisualsToAdd.Remove( visualName ); + Remove( stateVisualsToRemove, visualName ); + } + } + } + + void RemoveVisual( RegisteredVisualContainer& visuals, const std::string& visualName ) + { + Actor self( mControlImpl.Self() ); + + for ( RegisteredVisualContainer::Iterator visualIter = visuals.Begin(); + visualIter != visuals.End(); ++visualIter ) + { + Toolkit::Visual::Base visual = (*visualIter)->visual; + if( visual && visual.GetName() == visualName ) + { + Toolkit::GetImplementation(visual).SetOffStage( self ); + (*visualIter)->visual.Reset(); + visuals.Erase( visualIter ); + break; + } + } + } + + void RemoveVisuals( RegisteredVisualContainer& visuals, DictionaryKeys& removeVisuals ) + { + Actor self( mControlImpl.Self() ); + for( DictionaryKeys::iterator iter = removeVisuals.begin(); iter != removeVisuals.end(); ++iter ) + { + const std::string visualName = *iter; + RemoveVisual( visuals, visualName ); + } + } + + Toolkit::Visual::Type GetVisualTypeFromMap( const Property::Map& map ) + { + Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE ); + Toolkit::Visual::Type type = Toolkit::Visual::IMAGE; + if( typeValue ) + { + Scripting::GetEnumerationProperty( *typeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, type ); + } + return type; + } + + /** + * Go through the list of visuals that are common to both states. + * If they are different types, or are both image types with different + * URLs, then the existing visual needs moving and the new visual creating + */ + void RecreateChangedVisuals( Dictionary& stateVisualsToChange, + Dictionary& instancedProperties ) + { + Dali::CustomActor handle( mControlImpl.GetOwner() ); + for( Dictionary::iterator iter = stateVisualsToChange.Begin(); + iter != stateVisualsToChange.End(); ++iter ) + { + const std::string& visualName = (*iter).key; + const Property::Map& toMap = (*iter).entry; + + // is it a candidate for re-creation? + bool recreate = false; + + Toolkit::Visual::Base visual = GetVisualByName( mVisuals, visualName ); + if( visual ) + { + Property::Map fromMap; + visual.CreatePropertyMap( fromMap ); + + Toolkit::Visual::Type fromType = GetVisualTypeFromMap( fromMap ); + Toolkit::Visual::Type toType = GetVisualTypeFromMap( toMap ); + + if( fromType != toType ) + { + recreate = true; + } + else + { + if( fromType == Toolkit::Visual::IMAGE ) + { + Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME ); + Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME ); + + if( fromUrl && toUrl ) + { + std::string fromUrlString; + std::string toUrlString; + fromUrl->Get(fromUrlString); + toUrl->Get(toUrlString); + + if( fromUrlString != toUrlString ) + { + recreate = true; + } + } + } + } + + const Property::Map* instancedMap = instancedProperties.FindConst( visualName ); + if( recreate || instancedMap ) + { + RemoveVisual( mVisuals, visualName ); + Style::ApplyVisual( handle, visualName, toMap, instancedMap ); + } + else + { + // @todo check to see if we can apply toMap without recreating the visual + // e.g. by setting only animatable properties + // For now, recreate all visuals, but merge in instance data. + RemoveVisual( mVisuals, visualName ); + Style::ApplyVisual( handle, visualName, toMap, instancedMap ); + } + } + } + } + + void ReplaceStateVisualsAndProperties( const StylePtr oldState, const StylePtr newState, const std::string& subState ) + { + // Collect all old visual names + DictionaryKeys stateVisualsToRemove; + if( oldState ) + { + oldState->visuals.GetKeys( stateVisualsToRemove ); + if( ! subState.empty() ) + { + const StylePtr* oldSubState = oldState->subStates.FindConst(subState); + if( oldSubState ) + { + DictionaryKeys subStateVisualsToRemove; + (*oldSubState)->visuals.GetKeys( subStateVisualsToRemove ); + Merge( stateVisualsToRemove, subStateVisualsToRemove ); + } + } + } + + // Collect all new visual properties + Dictionary stateVisualsToAdd; + if( newState ) + { + stateVisualsToAdd = newState->visuals; + if( ! subState.empty() ) + { + const StylePtr* newSubState = newState->subStates.FindConst(subState); + if( newSubState ) + { + stateVisualsToAdd.Merge( (*newSubState)->visuals ); + } + } + } + + // If a name is in both add/remove, move it to change list. + Dictionary stateVisualsToChange; + FindChangableVisuals( stateVisualsToAdd, stateVisualsToChange, stateVisualsToRemove); + + // Copy instanced properties (e.g. text label) of current visuals + Dictionary instancedProperties; + CopyInstancedProperties( mVisuals, instancedProperties ); + + // For each visual in remove list, remove from mVisuals + RemoveVisuals( mVisuals, stateVisualsToRemove ); + + // For each visual in add list, create and add to mVisuals + Dali::CustomActor handle( mControlImpl.GetOwner() ); + Style::ApplyVisuals( handle, stateVisualsToAdd, instancedProperties ); + + // For each visual in change list, if it requires a new visual, + // remove old visual, create and add to mVisuals + RecreateChangedVisuals( stateVisualsToChange, instancedProperties ); + } + + void SetState( DevelControl::State newState, bool withTransitions=true ) { - if( mState != state ) + DevelControl::State oldState = mState; + Dali::CustomActor handle( mControlImpl.GetOwner() ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "Control::Impl::SetState: %s\n", + (mState == DevelControl::NORMAL ? "NORMAL" :( + mState == DevelControl::FOCUSED ?"FOCUSED" : ( + mState == DevelControl::DISABLED?"DISABLED":"NONE" )))); + + if( mState != newState ) { // If mState was Disabled, and new state is Focused, should probably // store that fact, e.g. in another property that FocusManager can access. - mState = state; + mState = newState; // Trigger state change and transitions // Apply new style, if stylemanager is available @@ -549,15 +771,19 @@ public: if( styleManager ) { const StylePtr stylePtr = GetImpl( styleManager ).GetRecordedStyle( Toolkit::Control( mControlImpl.GetOwner() ) ); + if( stylePtr ) { - for( int i=mVisuals.Count()-1; i >= 0; i-- ) + std::string oldStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( oldState, ControlStateTable, ControlStateTableCount ); + std::string newStateName = Scripting::GetEnumerationName< Toolkit::DevelControl::State >( newState, ControlStateTable, ControlStateTableCount ); + + const StylePtr* newStateStyle = stylePtr->subStates.Find( newStateName ); + const StylePtr* oldStateStyle = stylePtr->subStates.Find( oldStateName ); + if( oldStateStyle && newStateStyle ) { - mControlImpl.UnregisterVisual( mVisuals[i]->index ); + // Only change if both state styles exist + ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, mSubStateName ); } - - Dali::CustomActor handle( mControlImpl.GetOwner() ); - stylePtr->ApplyVisualsAndPropertiesRecursively( handle ); } } } @@ -584,30 +810,12 @@ public: { StylePtr stateStyle(*state); - // Unregister existing visuals of this substate - const StylePtr* subState = stateStyle->subStates.Find( mSubStateName ); - if( subState ) - { - StylePtr subStateStyle(*subState); - - for( Dictionary::iterator iter = subStateStyle->visuals.Begin(); iter != subStateStyle->visuals.End(); ++iter ) - { - const std::string& visualName = (*iter).key; - Dali::Property::Index index = handle.GetPropertyIndex( visualName ); - if( index != Property::INVALID_INDEX ) - { - mControlImpl.UnregisterVisual( index ); - } - } - } - - // Register visuals of the new substate - const StylePtr* newSubState = stateStyle->subStates.Find( subStateName ); - if( newSubState ) + const StylePtr* newStateStyle = stateStyle->subStates.Find( subStateName ); + const StylePtr* oldStateStyle = stateStyle->subStates.Find( mSubStateName ); + if( oldStateStyle && newStateStyle ) { - StylePtr newSubStateStyle(*newSubState); - newSubStateStyle->ApplyVisuals( handle ); - newSubStateStyle->ApplyProperties( handle ); + std::string empty; + ReplaceStateVisualsAndProperties( *oldStateStyle, *newStateStyle, empty ); } } } -- 2.7.4