From 4ff601968ee16e6d401977900d2aed328bdc6707 Mon Sep 17 00:00:00 2001 From: David Steele Date: Tue, 12 Jan 2016 17:37:42 +0000 Subject: [PATCH 1/1] Prevented json array of numbers appending on merge If 2 JSON files are merged into the same JSON parser (by calling Parse(first) then calling Parse(second) ), then currently, nodes in the tree with the same key but with differing types are overridden, but object and array types are merged. This is problematic for styling, where colors are represented as JSON arrays. Changed matching arrays of numbers to override rather than merge. Change-Id: Ia7a37a16919aa8648e7fe34430c5abf04cfaddb4 Signed-off-by: David Steele --- .../src/dali-toolkit/utc-Dali-JsonParser.cpp | 34 ++++++++++++++++++ dali-toolkit/internal/builder/builder-impl.cpp | 8 ++--- .../internal/builder/json-parser-state.cpp | 9 +++-- .../internal/builder/tree-node-manipulator.cpp | 13 +++++++ .../internal/styling/style-manager-impl.cpp | 41 ++++++++++------------ dali-toolkit/internal/styling/style-manager-impl.h | 5 ++- .../styles/480x800/dali-toolkit-default-theme.json | 8 +++++ 7 files changed, 86 insertions(+), 32 deletions(-) diff --git a/automated-tests/src/dali-toolkit/utc-Dali-JsonParser.cpp b/automated-tests/src/dali-toolkit/utc-Dali-JsonParser.cpp index 1f2c667..1fafb16 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-JsonParser.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-JsonParser.cpp @@ -722,3 +722,37 @@ int UtcDaliJsonParserMethod11(void) tet_result(TET_PASS); END_TEST; } + + +int UtcDaliJsonParserMerge1(void) +{ + ToolkitTestApplication application; + tet_infoline("JSON tree merge"); + + std::string s1( ReplaceQuotes(" \ +{ \ + 'styles': \ + { \ + 'button': \ + { \ + 'backgroundColor':[0.8, 0.0, 1.0, 1.0], \ + 'foregroundColor':[1, 1, 1, 1] \ + } \ + } \ +} \ +")); + + JsonParser parser = JsonParser::New(); + JsonParser testParser = JsonParser::New(); + + testParser.Parse( s1 ); + + parser.Parse( s1 ); + parser.Parse( s1 ); // Merge the tree into itself. The value array should not grow. + + DALI_TEST_CHECK(parser.GetRoot()); + + CompareTrees( *parser.GetRoot(), *testParser.GetRoot() ); + + END_TEST; +} diff --git a/dali-toolkit/internal/builder/builder-impl.cpp b/dali-toolkit/internal/builder/builder-impl.cpp index 1535eeb..de40d44 100644 --- a/dali-toolkit/internal/builder/builder-impl.cpp +++ b/dali-toolkit/internal/builder/builder-impl.cpp @@ -1117,7 +1117,6 @@ void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::U parser.GetErrorDescription().c_str() ); DALI_ASSERT_ALWAYS(!"Cannot parse JSON"); - } else { @@ -1155,7 +1154,6 @@ void Builder::LoadFromString( std::string const& data, Dali::Toolkit::Builder::U } DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Cannot parse JSON"); - } void Builder::AddConstants( const Property::Map& map ) @@ -1359,9 +1357,9 @@ Builder::Builder() mParser = Dali::Toolkit::JsonParser::New(); Property::Map defaultDirs; - defaultDirs[ TOKEN_STRING(DALI_IMAGE_DIR) ] = DALI_IMAGE_DIR; - defaultDirs[ TOKEN_STRING(DALI_SOUND_DIR) ] = DALI_SOUND_DIR; - defaultDirs[ TOKEN_STRING(DALI_STYLE_DIR) ] = DALI_STYLE_DIR; + defaultDirs[ TOKEN_STRING(DALI_IMAGE_DIR) ] = DALI_IMAGE_DIR; + defaultDirs[ TOKEN_STRING(DALI_SOUND_DIR) ] = DALI_SOUND_DIR; + defaultDirs[ TOKEN_STRING(DALI_STYLE_DIR) ] = DALI_STYLE_DIR; defaultDirs[ TOKEN_STRING(DALI_STYLE_IMAGE_DIR) ] = DALI_STYLE_IMAGE_DIR; AddConstants( defaultDirs ); diff --git a/dali-toolkit/internal/builder/json-parser-state.cpp b/dali-toolkit/internal/builder/json-parser-state.cpp index afa9e59..3691838 100644 --- a/dali-toolkit/internal/builder/json-parser-state.cpp +++ b/dali-toolkit/internal/builder/json-parser-state.cpp @@ -318,8 +318,13 @@ TreeNode* JsonParserState::NewNode(const char* name, TreeNode::NodeType type) TreeNodeManipulator modify(node); modify.SetName(name); - // Set the type of the existing node, this may remove children where necessary - // (changing from container type to value type) + + // Set the type of the existing node. + // Where the new type is different, then any children of this node will + // be deleted. + // When the type is an array of numbers, then this will also remove any children + // When the type is an object or other array, then the children will not be removed, + // but will instead follow these replace rules. modify.SetType(type); mCurrent = modify; diff --git a/dali-toolkit/internal/builder/tree-node-manipulator.cpp b/dali-toolkit/internal/builder/tree-node-manipulator.cpp index 926842a..4357cb8 100644 --- a/dali-toolkit/internal/builder/tree-node-manipulator.cpp +++ b/dali-toolkit/internal/builder/tree-node-manipulator.cpp @@ -291,6 +291,19 @@ void TreeNodeManipulator::SetType( TreeNode::NodeType type) } } } + else if( TreeNode::ARRAY == mNode->mType ) + { + if( mNode->mFirstChild != NULL ) + { + TreeNode::NodeType type = mNode->mFirstChild->GetType(); + + if( TreeNode::FLOAT == type || TreeNode::INTEGER == type ) + { + // Arrays of numbers should be replaced, not appended to. + RemoveChildren(); + } + } + } } void TreeNodeManipulator::SetName( const char* name ) diff --git a/dali-toolkit/internal/styling/style-manager-impl.cpp b/dali-toolkit/internal/styling/style-manager-impl.cpp index 5178020..85aa069 100644 --- a/dali-toolkit/internal/styling/style-manager-impl.cpp +++ b/dali-toolkit/internal/styling/style-manager-impl.cpp @@ -101,7 +101,6 @@ StyleManager::StyleManager() : mOrientationDegrees( 0 ), // Portrait mDefaultFontSize( -1 ), mDefaultFontFamily(""), - mThemeFile( DEFAULT_THEME ), mFeedbackStyle( NULL ) { // Add theme builder constants @@ -131,7 +130,7 @@ void StyleManager::SetOrientationValue( int orientation ) mOrientationDegrees = orientation; // TODO: if orientation changed, apply the new style to all controls // dont want to really do the whole load from file again if the bundle contains both portrait & landscape - SetTheme(); + SetTheme( mThemeFile ); } } @@ -184,15 +183,13 @@ bool StyleManager::GetStyleConstant( const std::string& key, Property::Value& va void StyleManager::RequestThemeChange( const std::string& themeFile ) { - mThemeFile = themeFile; - - // need to do style change synchronously as app might create a UI control on the next line - SetTheme(); + SetTheme( themeFile ); } void StyleManager::RequestDefaultTheme() { - RequestThemeChange( DEFAULT_THEME ); + std::string empty; + SetTheme( empty ); } void StyleManager::ApplyThemeStyle( Toolkit::Control control ) @@ -256,12 +253,22 @@ Toolkit::StyleManager::StyleChangeSignalType& StyleManager::StyleChangeSignal() return mStyleChangeSignal; } - -void StyleManager::SetTheme() +void StyleManager::SetTheme( const std::string& themeFile ) { + bool themeLoaded = false; + mThemeBuilder = CreateBuilder( mThemeBuilderConstants ); - if( LoadJSON( mThemeBuilder, mThemeFile ) ) + // Always load the default theme first, then merge in the custom theme if present + themeLoaded = LoadJSON( mThemeBuilder, DEFAULT_THEME ); + + if( ! themeFile.empty() ) + { + mThemeFile = themeFile; + themeLoaded = LoadJSON( mThemeBuilder, mThemeFile ); + } + + if( themeLoaded ) { if(mFeedbackStyle) { @@ -398,7 +405,7 @@ void StyleManager::OnOrientationChanged( Orientation orientation ) mOrientation = orientation; // TODO: if orientation changed, apply the new style to all controls // dont want to really do the whole load from file again if the bundle contains both portrait & landscape - SetTheme(); + SetTheme( mThemeFile ); } @@ -436,17 +443,7 @@ void StyleManager::StyleMonitorChange( StyleMonitor styleMonitor, StyleChange::T case StyleChange::THEME_CHANGE: { - const std::string& newTheme = styleMonitor.GetTheme(); - if( ! newTheme.empty() ) - { - mThemeFile = newTheme; - } - else - { - mThemeFile = DEFAULT_THEME; - } - - SetTheme(); + SetTheme( styleMonitor.GetTheme() ); break; } } diff --git a/dali-toolkit/internal/styling/style-manager-impl.h b/dali-toolkit/internal/styling/style-manager-impl.h index 0eec891..294e601 100644 --- a/dali-toolkit/internal/styling/style-manager-impl.h +++ b/dali-toolkit/internal/styling/style-manager-impl.h @@ -144,8 +144,9 @@ private: /** * @brief Set the current theme. Called only once per event processing cycle. + * @param[in] themeFile The name of the theme file to read. */ - void SetTheme(); + void SetTheme( const std::string& themeFile ); /** * @brief Internal helper method to read a file from file system. @@ -248,9 +249,7 @@ private: int mOrientationDegrees; ///< Directly set value of orientation int mDefaultFontSize; ///< Logical size, not a point-size - std::string mDefaultFontFamily; - std::string mThemeFile; ///< The full path of the current theme file Property::Map mThemeBuilderConstants; ///< Contants to give the theme builder diff --git a/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json b/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json index 3717470..ab9c802 100644 --- a/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json +++ b/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json @@ -142,6 +142,14 @@ distributing this software or its derivatives. "grabHandleImage" : "{DALI_STYLE_IMAGE_DIR}cursor_handler_drop_center.png", "selectionHandleImageLeft" : {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_left.png" }, "selectionHandleImageRight": {"filename":"{DALI_STYLE_IMAGE_DIR}selection_handle_drop_right.png" } + }, + "popup": + { + "popupBackgroundImage":"{DALI_IMAGE_DIR}00_popup_bg.9.png" + }, + "confirmationpopup": + { + "popupBackgroundImage":"{DALI_IMAGE_DIR}00_popup_bg.9.png" } } } -- 2.7.4