Release 8.0.0.15177
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI.Components / Utils / StyleManager.cs
1 /*
2  * Copyright(c) 2019 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17 using System;
18 using System.Collections.Generic;
19 using Tizen.NUI.BaseComponents;
20
21 namespace Tizen.NUI.Components
22 {
23     /// <summary>
24     /// StyleManager is a class to manager all style.
25     /// </summary>
26     /// <since_tizen> 8 </since_tizen>
27     public sealed class StyleManager
28     {
29         internal const float PointSizeNormal = 12;
30         internal const float PointSizeTitle = 16;
31
32         private const string defaultThemeName = "default";
33         private const string wearableThemeName = "wearable";
34         
35         private string currentThemeName = defaultThemeName;
36         private Dictionary<string, Dictionary<string, StyleBase>> themeStyleSet = new Dictionary<string, Dictionary<string, StyleBase>>();
37         private Dictionary<string, StyleBase> defaultStyleSet = new Dictionary<string, StyleBase>();
38
39         /// <summary>
40         /// (Theme name, Theme instance)
41         /// </summary>
42         private Dictionary<string, Dictionary<Type, StyleBase>> componentStyleByTheme = new Dictionary<string, Dictionary<Type, StyleBase>>();
43         
44         /// <summary>
45         /// (Theme name, Theme instance)
46         /// </summary>
47         private Dictionary<string, Theme> themeMap = new Dictionary<string, Theme>();
48
49         private EventHandler<ThemeChangeEventArgs> themeChangeHander;
50
51         private Theme currentTheme;
52
53         /// <summary>
54         /// StyleManager construct.
55         /// </summary>
56         private StyleManager()
57         {
58             SetInitialThemeByDeviceProfile();
59         }
60
61         /// <summary>
62         /// An event for the theme changed signal which can be used to subscribe or unsubscribe the event handler provided by the user.<br />
63         /// </summary>
64         /// <since_tizen> 8 </since_tizen>
65         public event EventHandler<ThemeChangeEventArgs> ThemeChangedEvent
66         {
67             add
68             {
69                 themeChangeHander += value;
70             }
71             remove
72             {
73                 themeChangeHander -= value;
74             }
75         }
76
77         /// <summary>
78         /// StyleManager static instance.
79         /// </summary>
80         /// <since_tizen> 8 </since_tizen>
81         public static StyleManager Instance { get; } = new StyleManager();
82
83         /// <summary>
84         /// Style theme.
85         /// </summary>
86         /// <since_tizen> 8 </since_tizen>
87         public string Theme
88         {
89             get
90             {
91                 return currentThemeName;
92             }
93
94             set
95             {
96                 if (currentThemeName != value)
97                 {
98                     currentThemeName = value.ToLower();
99                     themeChangeHander?.Invoke(null, new ThemeChangeEventArgs { CurrentTheme = currentThemeName });
100
101                     UpdateTheme();
102                 }
103             }
104         }
105
106         /// <summary>
107         /// Register style in StyleManager.
108         /// </summary>
109         /// <param name="style">Style name.</param>
110         /// <param name="theme">Theme.</param>
111         /// <param name="styleType">Style type.</param>
112         /// <param name="bDefault">Flag to decide if it is default style.</param>
113         /// <since_tizen> 8 </since_tizen>
114         public void RegisterStyle(string style, string theme, Type styleType, bool bDefault = false)
115         {
116             if (style == null)
117             {
118                 throw new InvalidOperationException($"style can't be null");
119             }
120
121             if (theme == null || bDefault == true)
122             {
123                 if (defaultStyleSet.ContainsKey(style))
124                 {
125                     throw new InvalidOperationException($"{style}] already be used");
126                 }
127                 else
128                 {
129                     defaultStyleSet.Add(style, Activator.CreateInstance(styleType) as StyleBase);
130                 }
131                 return;
132             }
133
134             if (themeStyleSet.ContainsKey(style) && themeStyleSet[style].ContainsKey(theme))
135             {
136                 throw new InvalidOperationException($"{style}] already be used");
137             }
138
139             if (!themeStyleSet.ContainsKey(style))
140             {
141                 themeStyleSet.Add(style, new Dictionary<string, StyleBase>());
142             }
143
144             themeStyleSet[style].Add(theme, Activator.CreateInstance(styleType) as StyleBase);
145         }
146
147         /// <summary>
148         /// Get style.
149         /// </summary>
150         /// <param name="style">Style name.</param>
151         /// <returns>The style corresponding to style name .</returns>
152         /// <since_tizen> 8 </since_tizen>
153         public ViewStyle GetViewStyle(string style)
154         {
155             if (style == null)
156             {
157                 return null;
158             }
159
160             if (themeStyleSet.ContainsKey(style) && themeStyleSet[style].ContainsKey(Theme))
161             {
162                 return (themeStyleSet[style][Theme])?.GetViewStyle();
163             }
164             else if (defaultStyleSet.ContainsKey(style))
165             {
166                 return (defaultStyleSet[style])?.GetViewStyle();
167             }
168
169             return null;
170         }
171
172         /// <summary>
173         /// Register a style for a component to theme.
174         /// </summary>
175         /// <param name="targetTheme">The target theme name to register a component style. It theme should be a known one.</param>
176         /// <param name="component">The type of ComponentStyle</param>
177         /// <param name="style">The derived class of StyleBase</param>
178         /// <since_tizen> 8 </since_tizen>
179         public void RegisterComponentStyle(string targetTheme, Type component, Type style)
180         {
181             if (targetTheme == null)
182             {
183                 throw new ArgumentException("The argument targetTheme must be specified");
184             }
185
186             if (!themeMap.ContainsKey(targetTheme))
187             {
188                 Tizen.Log.Error("NUI", "The theme name should be a known one.");
189                 return;
190             }
191
192             if (!componentStyleByTheme.ContainsKey(targetTheme))
193             {
194                 componentStyleByTheme.Add(targetTheme, new Dictionary<Type, StyleBase>());
195             }
196
197             if (componentStyleByTheme[targetTheme].ContainsKey(component))
198             {
199                 componentStyleByTheme[targetTheme][component] = Activator.CreateInstance(style) as StyleBase;
200             }
201             else
202             {
203                 componentStyleByTheme[targetTheme].Add(component, Activator.CreateInstance(style) as StyleBase);
204             }
205         }
206
207         /// <summary>
208         /// Get components style in the current theme.
209         /// </summary>
210         /// <param name="component">The type of component</param>
211         /// <returns>The style of the component.</returns>
212         /// <since_tizen> 8 </since_tizen>
213         public ViewStyle GetComponentStyle(Type component)
214         {
215             if (componentStyleByTheme.ContainsKey(currentThemeName) && componentStyleByTheme[currentThemeName].ContainsKey(component))
216             {
217                 return componentStyleByTheme[currentThemeName][component].GetViewStyle();
218             }
219
220             return currentTheme.GetComponentStyle(component);
221         }
222
223         /// <summary>
224         /// ThemeChangeEventArgs is a class to record theme change event arguments which will sent to user.
225         /// </summary>
226         /// <since_tizen> 8 </since_tizen>
227         public class ThemeChangeEventArgs : EventArgs
228         {
229             /// <summary>
230             /// CurrentTheme
231             /// </summary>
232             /// <since_tizen> 8 </since_tizen>
233             public string CurrentTheme;
234         }
235
236         internal static string GetFrameworkResourcePath(string resourceFileName)
237         {
238             return "/usr/share/dotnet.tizen/framework/res/" + resourceFileName;
239         }
240
241         private void SetInitialThemeByDeviceProfile()
242         {
243             themeMap.Add(wearableThemeName, WearableTheme.Instance);
244             themeMap.Add(defaultThemeName, DefaultTheme.Instance);
245
246             currentThemeName = defaultThemeName;
247             currentTheme = DefaultTheme.Instance;
248
249             string currentProfile;
250
251             try
252             {
253                 System.Information.TryGetValue<string>("tizen.org/feature/profile", out currentProfile);
254                 Tizen.Log.Info("NUI", "Profile for initial theme found : " + currentProfile);
255             }
256             catch
257             {
258                 Tizen.Log.Error("NUI", "Unknown device profile");
259                 return;
260             }
261
262             if (string.Equals(currentProfile, wearableThemeName))
263             {
264                 currentThemeName = wearableThemeName;
265                 currentTheme = WearableTheme.Instance;
266             }
267         }
268
269         private void UpdateTheme()
270         {
271             if (themeMap.ContainsKey(currentThemeName))
272             {
273                 currentTheme = themeMap[currentThemeName];
274             }
275             else
276             {
277                 currentTheme = DefaultTheme.Instance;
278             }
279         }
280     }
281 }