2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "style-manager-impl.h"
21 #include <dali/devel-api/adaptor-framework/singleton-service.h>
22 #include <dali/public-api/object/type-registry.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/adaptor-framework/application.h>
28 #include <dali-toolkit/internal/builder/builder-impl.h>
29 #include <dali-toolkit/public-api/controls/control.h>
30 #include <dali-toolkit/public-api/controls/control-impl.h>
31 #include <dali-toolkit/public-api/styling/style-manager.h>
32 #include <dali-toolkit/internal/feedback/feedback-style.h>
37 const char* LANDSCAPE_QUALIFIER = "landscape";
38 const char* PORTRAIT_QUALIFIER = "portrait";
39 const char* FONT_SIZE_QUALIFIER = "fontsize";
41 const char* DEFAULT_THEME = DALI_STYLE_DIR "dali-toolkit-default-theme.json";
43 const char* PACKAGE_PATH_KEY = "PACKAGE_PATH";
44 const char* APPLICATION_RESOURCE_PATH_KEY = "APPLICATION_RESOURCE_PATH";
46 const char* DEFAULT_PACKAGE_PATH = DALI_DATA_READ_ONLY_DIR "/toolkit/";
64 BaseHandle handle = StyleManager::Get();
68 SingletonService singletonService( SingletonService::Get() );
69 if ( singletonService )
71 Toolkit::StyleManager manager = Toolkit::StyleManager( new Internal::StyleManager() );
72 singletonService.Register( typeid( manager ), manager );
80 DALI_TYPE_REGISTRATION_BEGIN_CREATE( Toolkit::StyleManager, Dali::BaseHandle, Create, true )
81 DALI_TYPE_REGISTRATION_END()
85 Toolkit::StyleManager StyleManager::Get()
87 Toolkit::StyleManager manager;
89 SingletonService singletonService( SingletonService::Get() );
90 if ( singletonService )
92 // Check whether the style manager is already created
93 Dali::BaseHandle handle = singletonService.GetSingleton( typeid( Toolkit::StyleManager ) );
96 // If so, downcast the handle of singleton
97 manager = Toolkit::StyleManager( dynamic_cast< StyleManager* >( handle.GetObjectPtr() ) );
104 StyleManager::StyleManager()
105 : mDefaultFontSize( -1 ),
106 mDefaultFontFamily(""),
107 mFeedbackStyle( NULL )
109 // Add theme builder constants
110 mThemeBuilderConstants[ PACKAGE_PATH_KEY ] = DEFAULT_PACKAGE_PATH;
111 mThemeBuilderConstants[ APPLICATION_RESOURCE_PATH_KEY ] = Application::GetResourcePath();
113 mStyleMonitor = StyleMonitor::Get();
116 mStyleMonitor.StyleChangeSignal().Connect( this, &StyleManager::StyleMonitorChange );
117 mDefaultFontSize = mStyleMonitor.GetDefaultFontSize();
120 // Sound & haptic style
121 mFeedbackStyle = new FeedbackStyle();
124 StyleManager::~StyleManager()
126 delete mFeedbackStyle;
129 void StyleManager::ApplyTheme( const std::string& themeFile )
131 SetTheme( themeFile );
134 void StyleManager::ApplyDefaultTheme()
140 const std::string& StyleManager::GetDefaultFontFamily() const
142 return mDefaultFontFamily;
145 void StyleManager::SetStyleConstant( const std::string& key, const Property::Value& value )
147 mStyleBuilderConstants[ key ] = value;
150 bool StyleManager::GetStyleConstant( const std::string& key, Property::Value& valueOut )
152 Property::Value* value = mStyleBuilderConstants.Find( key );
162 void StyleManager::ApplyThemeStyle( Toolkit::Control control )
171 ApplyStyle( mThemeBuilder, control );
175 void StyleManager::ApplyThemeStyleAtInit( Toolkit::Control control )
177 ApplyThemeStyle( control );
181 mFeedbackStyle->ObjectCreated( control );
185 void StyleManager::ApplyStyle( Toolkit::Control control, const std::string& jsonFileName, const std::string& styleName )
187 bool builderReady = false;
189 // First look in the cache
190 Toolkit::Builder builder = FindCachedBuilder( jsonFileName );
197 // Merge theme and style constants
198 Property::Map constants( mThemeBuilderConstants );
199 constants.Merge( mStyleBuilderConstants );
202 builder = CreateBuilder( constants );
204 if( LoadJSON( builder, jsonFileName ) )
206 CacheBuilder( builder, jsonFileName );
211 // Apply the style to the control
214 builder.ApplyStyle( styleName, control );
218 Toolkit::StyleManager::StyleChangedSignalType& StyleManager::StyleChangedSignal()
220 return mStyleChangedSignal;
223 Toolkit::StyleManager::StyleChangedSignalType& StyleManager::ControlStyleChangeSignal()
225 return mControlStyleChangeSignal;
228 void StyleManager::SetTheme( const std::string& themeFile )
230 bool themeLoaded = false;
232 mThemeBuilder = CreateBuilder( mThemeBuilderConstants );
234 // Always load the default theme first, then merge in the custom theme if present
235 themeLoaded = LoadJSON( mThemeBuilder, DEFAULT_THEME );
237 if( ! themeFile.empty() )
239 mThemeFile = themeFile;
240 themeLoaded = LoadJSON( mThemeBuilder, mThemeFile );
247 mFeedbackStyle->StyleChanged( mThemeFile, StyleChange::THEME_CHANGE );
250 EmitStyleChangeSignals(StyleChange::THEME_CHANGE);
254 mThemeBuilder.Reset();
258 bool StyleManager::LoadFile( const std::string& filename, std::string& stringOut )
260 DALI_ASSERT_DEBUG( 0 != filename.length());
262 // as toolkit is platform agnostic, it cannot load files from filesystem
263 // ask style monitor to load the style sheet
266 return mStyleMonitor.LoadThemeFile( filename, stringOut );
272 Toolkit::Builder StyleManager::CreateBuilder( const Property::Map& constants )
274 Toolkit::Builder builder = Toolkit::Builder::New();
275 builder.AddConstants( constants );
280 bool StyleManager::LoadJSON( Toolkit::Builder builder, const std::string& jsonFilePath )
282 std::string fileString;
283 if( LoadFile( jsonFilePath, fileString ) )
285 builder.LoadFromString( fileString );
290 DALI_LOG_WARNING("Error loading file '%s'\n", jsonFilePath.c_str());
295 static void CollectQualifiers( std::vector<std::string>& qualifiersOut )
297 // Append the relevant qualifier for orientation
298 int orientation = 0; // Get the orientation from the system
299 switch( orientation )
304 qualifiersOut.push_back( std::string( LANDSCAPE_QUALIFIER ) );
308 case 0: // fall through
311 qualifiersOut.push_back( std::string( PORTRAIT_QUALIFIER ) );
318 * @brief Construct a qualified style name out of qualifiers
320 * A qualifed style name will be in the format: style-qualifier0-qualifier1-qualifierN
322 * @param[in] styleName The root name of the style
323 * @param[in] qualifiers List of qualifier names
324 * @param[out] qualifiedStyleOut The qualified style name
326 static void BuildQualifiedStyleName(
327 const std::string& styleName,
328 const std::vector<std::string>& qualifiers,
329 std::string& qualifiedStyleOut )
331 qualifiedStyleOut.append( styleName );
333 for( std::vector<std::string>::const_iterator it = qualifiers.begin(),
334 itEnd = qualifiers.end(); it != itEnd; ++it )
336 const std::string& str = *it;
338 qualifiedStyleOut.append( "-" );
339 qualifiedStyleOut.append( str );
343 static bool GetStyleNameForControl( Toolkit::Builder builder, Toolkit::Control control, std::string& styleName)
345 styleName = control.GetStyleName();
347 if( styleName.empty() )
349 styleName = control.GetTypeName();
352 // Apply the style after choosing the correct actual style (e.g. landscape or portrait)
353 std::vector<std::string> qualifiers;
354 CollectQualifiers( qualifiers );
357 std::string qualifiedStyleName;
360 qualifiedStyleName.clear();
361 BuildQualifiedStyleName( styleName, qualifiers, qualifiedStyleName );
363 // Break if style found or we have tried the root style name (qualifiers is empty)
364 if( GetImpl(builder).LookupStyleName( qualifiedStyleName ) )
369 if( qualifiers.size() == 0 )
373 // Remove the last qualifier in an attempt to find a style that is valid
374 qualifiers.pop_back();
379 styleName = qualifiedStyleName;
384 void StyleManager::ApplyStyle( Toolkit::Builder builder, Toolkit::Control control )
386 std::string styleName = control.GetStyleName();
387 if( GetStyleNameForControl( builder, control, styleName ) )
389 builder.ApplyStyle( styleName, control );
392 if( mDefaultFontSize >= 0 )
394 // Apply the style for logical font size
395 std::stringstream fontSizeQualifier;
396 fontSizeQualifier << styleName << FONT_SIZE_QUALIFIER << mDefaultFontSize;
397 builder.ApplyStyle( fontSizeQualifier.str(), control );
401 const StylePtr StyleManager::GetRecordedStyle( Toolkit::Control control )
405 std::string styleName = control.GetStyleName();
407 if( GetStyleNameForControl( mThemeBuilder, control, styleName ) )
409 const StylePtr style = GetImpl(mThemeBuilder).GetStyle( styleName );
413 return StylePtr(NULL);
416 Toolkit::Builder StyleManager::FindCachedBuilder( const std::string& key )
418 BuilderMap::iterator builderIt = mBuilderCache.find( key );
419 if( builderIt != mBuilderCache.end() )
421 return builderIt->second;
424 return Toolkit::Builder();
427 void StyleManager::CacheBuilder( Toolkit::Builder builder, const std::string& key )
429 mBuilderCache[ key ] = builder;
432 void StyleManager::StyleMonitorChange( StyleMonitor styleMonitor, StyleChange::Type styleChange )
434 switch ( styleChange )
436 case StyleChange::DEFAULT_FONT_CHANGE:
438 mDefaultFontFamily = styleMonitor.GetDefaultFontFamily();
442 case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
444 mDefaultFontSize = styleMonitor.GetDefaultFontSize();
448 case StyleChange::THEME_CHANGE:
450 SetTheme( styleMonitor.GetTheme() );
454 EmitStyleChangeSignals( styleChange );
457 void StyleManager::EmitStyleChangeSignals( StyleChange::Type styleChange )
459 Toolkit::StyleManager styleManager = StyleManager::Get();
461 // Update Controls first
462 mControlStyleChangeSignal.Emit( styleManager, styleChange );
464 // Inform application last
465 mStyleChangedSignal.Emit( styleManager, styleChange );
469 } // namespace Internal
471 } // namespace Toolkit