[NUI] Re-design theme resource structure from the tizen-theme-manager (#2633)
authorJiyun Yang <ji.yang@samsung.com>
Fri, 26 Feb 2021 07:15:40 +0000 (16:15 +0900)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Wed, 3 Mar 2021 07:56:53 +0000 (16:56 +0900)
* [NUI] Fix Selector bug and code by throwing proper exception.

* Fix multiple items bug
* Throw proper exception

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
* [NUI] Add Theme.Version and improve GetStyle API

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
* [NUI] Remove build warning and move IThemeCreator to the new file from the ThemeManager

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
* [NUI] Re-design theme resource structure from the tizen-theme-manager

This patch fixes problem that
the data from the tizen-theme-manager was not able to express mutually exclusive style properties,
such as, BackgroundColor and BackgroundImage.

* IExternalTheme
  * The wrapper interface to express external theme such as Tizen.Applications.ThemeManager.Theme.
  * TizenExternalTheme : Wrapped Tizen.Applications.ThemeManager.Theme.
  * DictionaryExternalTheme : Wrapped Dicrionary<stirng, string>. (for testing)
* ExternalKeyList
  * This class defines a set of keys used in external theme syntax.
  * A set of ExternalKeyList is held by a ThemeCreator in each package.

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
* [NUI] Fix CornerRadius Policy not applied issue

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
21 files changed:
src/Tizen.NUI.Components/Controls/Control.cs
src/Tizen.NUI.Components/Theme/DefaultTheme.cs
src/Tizen.NUI.Components/Theme/DefaultThemeCommon.cs [new file with mode: 0644]
src/Tizen.NUI.Components/Theme/DefaultThemeMobile.cs [deleted file]
src/Tizen.NUI.Components/Theme/DefaultThemeWearable.cs
src/Tizen.NUI.Components/Utils/StyleManager.cs
src/Tizen.NUI.Wearable/src/internal/Theme/DefaultTheme.cs
src/Tizen.NUI/Tizen.NUI.csproj
src/Tizen.NUI/src/public/Application/NUIApplication.cs
src/Tizen.NUI/src/public/BaseComponents/ImageView.cs
src/Tizen.NUI/src/public/BaseComponents/Style/Selector.cs
src/Tizen.NUI/src/public/BaseComponents/ViewBindableProperty.cs
src/Tizen.NUI/src/public/Theme/DefaultTheme.cs
src/Tizen.NUI/src/public/Theme/DictionaryExternalTheme.cs [new file with mode: 0644]
src/Tizen.NUI/src/public/Theme/ExternalThemeKeyList.cs [new file with mode: 0644]
src/Tizen.NUI/src/public/Theme/ExternalThemeManager.cs [new file with mode: 0644]
src/Tizen.NUI/src/public/Theme/IExternalTheme.cs [new file with mode: 0644]
src/Tizen.NUI/src/public/Theme/IThemeCreator.cs [moved from src/Tizen.NUI/src/public/Theme/DefaultThemeWearable.cs with 70% similarity]
src/Tizen.NUI/src/public/Theme/Theme.cs
src/Tizen.NUI/src/public/Theme/ThemeManager.cs
src/Tizen.NUI/src/public/Theme/TizenExternalTheme.cs [new file with mode: 0644]

index 8a96466..1caef24 100755 (executable)
@@ -61,7 +61,7 @@ namespace Tizen.NUI.Components
         [EditorBrowsable(EditorBrowsableState.Never)]
         static public void Preload()
         {
-            ThemeManager.AddPackageTheme(DefaultThemeCreator.Instance);
+            DefaultThemeCreator.Preload();
         }
 
         /// <summary>
index 9910996..4c39c3f 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*
  * Copyright(c) 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * limitations under the License.
  *
  */
-#if !PROFILE_WEARABLE && !PROFILE_MOBILE
 
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using Tizen.NUI.BaseComponents;
-using Tizen.NUI.Binding;
 
 namespace Tizen.NUI.Components
 {
-    // It is a C# version of res/Tizen.NUI.Components_Tizen.NUI.Theme.Common.xaml
-    internal class DefaultThemeCreator : IThemeCreator
+    internal partial class DefaultThemeCreator
     {
+        private HashSet<ExternalThemeKeyList> actionSet;
+
         private DefaultThemeCreator() { }
 
         public static IThemeCreator Instance { get; set; } = new DefaultThemeCreator();
 
-        public ResourceDictionary CreateThemeResource() => new ResourceDictionary()
+        public HashSet<ExternalThemeKeyList> GetExternalThemeKeyListSet()
         {
-            ["ButtonBackgroundColorNormal"] = new Color(0.039f, 0.055f, 0.29f, 1),
-            ["ButtonBackgroundColorFocused"] = new Color(0, 0.2f, 0.545f, 1),
-            ["ButtonBackgroundColorPressed"] = new Color(0.106f, 0.412f, 0.792f, 1),
-            ["ButtonBackgroundColorDisabled"] = new Color(0.765f, 0.792f, 0.824f, 1),
-            ["ButtonTextColorNormal"] = Color.White,
-            ["ButtonTextColorPressed"] = Color.White,
-            ["ButtonTextColorDisabled"] = Color.White,
-            ["CheckBoxIconBackgroundImagePressed"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_p.png",
-            ["CheckBoxIconBackgroundImageSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_p.png",
-            ["CheckBoxIconBackgroundImageOther"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_n.png",
-            ["CheckBoxIconImageResourceUrlPressed"] = "",
-            ["CheckBoxIconImageResourceUrlSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_s.png",
-            ["CheckBoxIconImageResourceUrlOther"] = "",
-            ["CheckBoxTextColorNormal"] = new Color(0.22f, 0.22f, 0.22f, 1),
-            ["CheckBoxTextColorPressed"] = new Color(0.11f, 0.11f, 0.11f, 1),
-            ["CheckBoxTextColorDisabled"] = new Color(0.66f, 0.66f, 0.66f, 1),
-            ["DropDownBackgroundImagePressed"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_p.png",
-            ["DropDownBackgroundImageOther"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_n.png",
-            ["DropDownIconImageResourceUrl"] = FrameworkInformation.ResourcePath + "nui_component_default_dropdown_button_icon.png",
-            ["DropDownListBackgroundImageResourceUrl"] = FrameworkInformation.ResourcePath + "nui_component_default_dropdown_list_bg.png",
-            ["DropDownDataItemBackgroundColorPressed"] = new Color(0.05f, 0.63f, 0.9f, 1),
-            ["DropDownDataItemBackgroundColorSelected"] = new Color(0.8f, 0.8f, 0.8f, 1),
-            ["DropDownDataItemBackgroundColorNormal"] = new Color(1, 1, 1, 1),
-            ["PopupBackgroundColor"] = new Color(0.9f, 0.9f, 0.9f, 1),
-            ["PopupImageShadowUrl"] = FrameworkInformation.ResourcePath + "nui_component_default_popup_shadow.png",
-            ["PopupButtonBackgroundColorNormal"] = new Color(1, 1, 1, 1),
-            ["PopupButtonBackgroundColorPressed"] = new Color(1, 1, 1, 0.5f),
-            ["PopupButtonOverlayBackgroundColorNormal"] = new Color(1, 1, 1, 1),
-            ["PopupButtonOverlayBackgroundColorPressed"] = new Color(0, 0, 0, 0.1f),
-            ["PopupButtonOverlayBackgroundColorSelected"] = new Color(1, 1, 1, 1),
-            ["PopupButtonTextColor"] = new Color(0.05f, 0.63f, 0.9f, 1),
-            ["ProgressTrackBackgroundColor"] = new Color(0, 0, 0, 0.1f),
-            ["ProgressBufferBackgroundColor"] = new Color(0.05f, 0.63f, 0.9f, 0.3f),
-            ["ProgressProgressBackgroundColor"] = new Color(0.05f, 0.63f, 0.9f, 1),
-            ["RadioButtonIconBackgroundImagePressed"] = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_p.png",
-            ["RadioButtonIconBackgroundImageSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_s.png",
-            ["RadioButtonIconBackgroundImageOther"] = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_n.png",
-            ["RadioButtonTextColorNormal"] = new Color(0.22f, 0.22f, 0.22f, 1),
-            ["RadioButtonTextColorPressed"] = new Color(0.11f, 0.11f, 0.11f, 1),
-            ["RadioButtonTextColorDisabled"] = new Color(0.66f, 0.66f, 0.66f, 1),
-            ["SliderTrackColor"] = new Color(0, 0, 0, 0.1f),
-            ["SliderProgressColor"] = new Color(0.5f, 0.63f, 0.9f, 1),
-            ["SliderThumbImageResourceUrl"] = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_n.png",
-            ["SliderThumbBackgroundImageNormal"] = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_bg_p.png",
-            ["SliderThumbBackgroundImagePressed"] = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_bg_p.png",
-            ["SliderValueIndicatorImage"] = FrameworkInformation.ResourcePath + "nui_component_default_slider_value_indicator.png",
-            ["SwitchTrackImageResourceUrlNormal"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_n.png",
-            ["SwitchTrackImageResourceUrlSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_s.png",
-            ["SwitchTrackImageResourceUrlDisabled"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_d.png",
-            ["SwitchTrackImageResourceUrlDisabledSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_ds.png",
-            ["SwitchThumbImageResourceUrlNormal"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_n.png",
-            ["SwitchThumbImageResourceUrlDisabled"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_d.png",
-            ["SwitchThumbImageResourceUrlSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_n.png",
-            ["SwitchTextColorNormal"] = new Color(0.22f, 0.22f, 0.22f, 1),
-            ["SwitchTextColorPressed"] = new Color(0.11f, 0.11f, 0.11f, 1),
-            ["SwitchTextColorDisabled"] = new Color(0.66f, 0.66f, 0.66f, 1),
-            ["TabBackgroundColor"] = Color.Yellow,
-            ["TabUnderLineBackgroundColor"] = new Color(0.05f, 0.63f, 0.9f, 1.0f),
-            ["TabTextColorNormal"] = Color.Black,
-            ["TabTextColorSelected"] = new Color(0.05f, 0.63f, 0.9f, 1),
-            ["ToastBackgroundColor"] = new Color(0, 0, 0, 0.8f),
-            ["PaginationIndicatorImageUrlNormal"] = FrameworkInformation.ResourcePath + "nui_component_default_pagination_normal_dot.png",
-            ["PaginationIndicatorImageUrlSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_pagination_focus_dot.png",
-            ["ScrollbarTrackColor"] = new Color(1, 1, 1, 0.15f),
-            ["ScrollbarThumbColor"] = new Color(0.6f, 0.6f, 0.6f, 1.0f),
-            ["RecyclerViewItemBackgroundColorNormal"] = new Color(1, 1, 1, 1),
-            ["RecyclerViewItemBackgroundColorPressed"] = new Color(0.85f, 0.85f, 0.85f, 1),
-            ["RecyclerViewItemBackgroundColorDisabled"] = new Color(0.70f, 0.70f, 0.70f, 1),
-            ["RecyclerViewItemBackgroundColorSelected"] = new Color(0.701f, 0.898f, 0.937f, 1),
-            ["TitleBackgroundColorNormal"] = new Color(0.78f, 0.78f, 0.78f, 1),
-        };
-
-        public Theme Create() => Create(null);
+            if (actionSet != null)
+            {
+                return actionSet;
+            }
+
+            actionSet = new HashSet<ExternalThemeKeyList>()
+            {
+                // Button
+                (new ExternalThemeKeyList(typeof(Button), typeof(ButtonStyle)))
+                    .AddBackgroundSelector("/Background", SetBackgroundColor, SetBackgroundImage)
+                    .Add<Rectangle>("/BackgroundImageBorder", SetBackgroundBorder)
+                    .AddSelector<Color>("/Text/TextColor", SetButtonTextColor)
+                    .AddSelector<float?>("/Text/PixelSize", SetButtonTextPixelSize),
+
+                // CheckBox
+                (new ExternalThemeKeyList(typeof(CheckBox), typeof(ButtonStyle)))
+                    .AddSelector<string>("/Icon/ResourceUrl", SetButtonIconResourceUrl, ControlState.Selected, ControlState.DisabledSelected)
+                    .Add<Rectangle>("/Icon/Border", SetButtonIconBorder)
+                    .AddSelector<Color>("/Text/TextColor", SetButtonTextColor, ControlState.Selected, ControlState.DisabledSelected)
+                    .AddSelector<float?>("/Text/PixelSize", SetButtonTextPixelSize, ControlState.Selected, ControlState.DisabledSelected),
+
+                // RadioButton
+                (new ExternalThemeKeyList(typeof(RadioButton), typeof(ButtonStyle)))
+                    .AddSelector<string>("/Icon/ResourceUrl", SetButtonIconResourceUrl, ControlState.Selected, ControlState.DisabledSelected)
+                    .Add<Rectangle>("/Icon/Border", SetButtonIconBorder)
+                    .AddSelector<Color>("/Text/TextColor", SetButtonTextColor, ControlState.Selected, ControlState.DisabledSelected)
+                    .AddSelector<float?>("/Text/PixelSize", SetButtonTextPixelSize, ControlState.Selected, ControlState.DisabledSelected),
+
+                // Switch
+                (new ExternalThemeKeyList(typeof(Switch), typeof(SwitchStyle)))
+                    .AddSelector<string>("/Track/ResourceUrl", (ViewStyle style, Selector<string> value) => ((SwitchStyle)style).Track.ResourceUrl = value, ControlState.Selected, ControlState.DisabledSelected)
+                    .AddSelector<string>("/Thumb/ResourceUrl", (ViewStyle style, Selector<string> value) => ((SwitchStyle)style).Thumb.ResourceUrl = value, ControlState.Selected, ControlState.DisabledSelected)
+                    .Add<Rectangle>("/Track/Border", (ViewStyle style, Rectangle value) => ((SwitchStyle)style).Track.Border = value)
+                    .Add<Rectangle>("/Thumb/Border", (ViewStyle style, Rectangle value) => ((SwitchStyle)style).Thumb.Border = value)
+                    .AddSelector<Color>("/Text/TextColor", SetButtonTextColor, ControlState.Selected, ControlState.DisabledSelected)
+                    .AddSelector<float?>("/Text/PixelSize", SetButtonTextPixelSize, ControlState.Selected, ControlState.DisabledSelected),
+
+                // Progress
+                (new ExternalThemeKeyList(typeof(Progress), typeof(ProgressStyle)))
+                    .AddSelector("/Track/Background", (ViewStyle style, Selector<Color> value) => ((ProgressStyle)style).Track.BackgroundColor = value)
+                    .AddSelector("/Buffer/Background", (ViewStyle style, Selector<Color> value) => ((ProgressStyle)style).Buffer.BackgroundColor = value)
+                    .AddSelector("/Progress/Background", (ViewStyle style, Selector<Color> value) => ((ProgressStyle)style).Progress.BackgroundColor = value)
+                    .AddSelector("/Track/ResourceUrl", (ViewStyle style, Selector<string> value) => ((ProgressStyle)style).Track.ResourceUrl = value)
+                    .AddSelector("/Buffer/ResourceUrl", (ViewStyle style, Selector<string> value) => ((ProgressStyle)style).Buffer.ResourceUrl = value)
+                    .AddSelector("/Progress/ResourceUrl", (ViewStyle style, Selector<string> value) => ((ProgressStyle)style).Progress.ResourceUrl = value),
+
+                // Slider
+                (new ExternalThemeKeyList(typeof(Slider), typeof(SliderStyle)))
+                    .AddSelector("/Track/Background", (ViewStyle style, Selector<Color> value) => ((SliderStyle)style).Track.BackgroundColor = value)
+                    .AddSelector("/Progress/Background", (ViewStyle style, Selector<Color> value) => ((SliderStyle)style).Progress.BackgroundColor = value)
+                    .AddSelector("/Thumb/Background", (ViewStyle style, Selector<Color> value) => ((SliderStyle)style).Thumb.BackgroundColor = value)
+                    .AddSelector("/Thumb/ResourceUrl", (ViewStyle style, Selector<string> value) => ((SliderStyle)style).Thumb.ResourceUrl = value)
+                    .AddSelector("/ValueIndicatorImage/ResourceUrl", (ViewStyle style, Selector<string> value) => ((SliderStyle)style).ValueIndicatorImage.ResourceUrl = value),
+                
+                // Pagination
+                (new ExternalThemeKeyList(typeof(Pagination), typeof(PaginationStyle)))
+                    .AddSelector("/IndicatorImageUrl", (ViewStyle style, Selector<string> value) => ((PaginationStyle)style).IndicatorImageUrl = value),
+                
+                // Scrollbar
+                (new ExternalThemeKeyList(typeof(Scrollbar), typeof(ScrollbarStyle)))
+                    .Add("/TrackColor", (ViewStyle style, Color value) => ((ScrollbarStyle)style).TrackColor = value)
+                    .Add("/ThumbColor", (ViewStyle style, Color value) => ((ScrollbarStyle)style).ThumbColor = value),
+                
+                // RecyclerViewItem
+                (new ExternalThemeKeyList(typeof(RecyclerViewItem), typeof(RecyclerViewItemStyle)))
+                    .AddBackgroundSelector("/Background", SetBackgroundColor, SetBackgroundImage, ControlState.Selected)
+                    .Add<Rectangle>("/BackgroundImageBorder", SetBackgroundBorder),
+                
+                // DefaultTitleItem
+                (new ExternalThemeKeyList(typeof(DefaultTitleItem), typeof(DefaultTitleItemStyle)))
+                    .AddBackgroundSelector("/Background", SetBackgroundColor, SetBackgroundImage)
+                    .Add<Rectangle>("/BackgroundImageBorder", SetBackgroundBorder),
+            };
+
+            return actionSet;
+        }
 
-        [SuppressMessage("Microsoft.Reliability", "CA2000: Dispose objects before losing scope", Justification = "The responsibility to dispose the object is transferred to the theme object.")]
-        public Theme Create(IEnumerable<KeyValuePair<string, string>> changedResources)
+        public static void Preload()
         {
-            var theme = new Theme() { Id = "Tizen.NUI.Theme.Common" };
-
-            theme.SetChangedResources(changedResources);
-            theme.Resources = CreateThemeResource();
-            theme.OnThemeResourcesChanged();
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Button", new ButtonStyle()
-            {
-                Size = new Size(339, 96),
-                CornerRadius = 28,
-                BackgroundColor = new Selector<Color>()
-                {
-                    Normal = (Color)theme.Resources["ButtonBackgroundColorNormal"],
-                    Pressed = (Color)theme.Resources["ButtonBackgroundColorPressed"],
-                    Disabled = (Color)theme.Resources["ButtonBackgroundColorDisabled"],
-                },
-                Text = new TextLabelStyle()
-                {
-                    PixelSize = 32,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["ButtonTextColorNormal"],
-                        Pressed = (Color)theme.Resources["ButtonTextColorPressed"],
-                        Disabled = (Color)theme.Resources["ButtonTextColorDisabled"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.CheckBox", new ButtonStyle()
-            {
-                Size = new Size(30, 30),
-                Icon = new ImageViewStyle()
-                {
-                    Opacity = new Selector<float?>()
-                    {
-                        Normal = 1.0f,
-                        Disabled = 0.4f,
-                        Selected = 1.0f,
-                    },
-                    BackgroundImage = new Selector<string>()
-                    {
-                        Pressed = (string)theme.Resources["CheckBoxIconBackgroundImagePressed"],
-                        Selected = (string)theme.Resources["CheckBoxIconBackgroundImageSelected"],
-                        Other = (string)theme.Resources["CheckBoxIconBackgroundImageOther"],
-                    },
-                    ResourceUrl = new Selector<string>()
-                    {
-                        Pressed = (string)theme.Resources["CheckBoxIconImageResourceUrlPressed"],
-                        Selected = (string)theme.Resources["CheckBoxIconImageResourceUrlSelected"],
-                        Other = (string)theme.Resources["CheckBoxIconImageResourceUrlOther"],
-                    },
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 12,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["CheckBoxTextColorNormal"],
-                        Pressed = (Color)theme.Resources["CheckBoxTextColorPressed"],
-                        Disabled = (Color)theme.Resources["CheckBoxTextColorDisabled"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Popup", new PopupStyle()
-            {
-                Size = new Size(500, 280),
-                BackgroundColor = (Color)theme.Resources["PopupBackgroundColor"],
-                ImageShadow = new ImageShadow()
-                {
-                    Url = (string)theme.Resources["PopupImageShadowUrl"],
-                    Border = new Rectangle(24, 24, 24, 24),
-                    Extents = new Vector2(48, 48)
-                },
-                Title = new TextLabelStyle()
-                {
-                    PointSize = 16,
-                    Padding = new Extents(20, 20, 20, 20),
-                },
-                Buttons = new ButtonStyle()
-                {
-                    Size = new Size(0, 80),
-                    BackgroundColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["PopupButtonBackgroundColorNormal"],
-                        Pressed = (Color)theme.Resources["PopupButtonBackgroundColorPressed"],
-                    },
-                    Overlay = new ImageViewStyle()
-                    {
-                        BackgroundColor = new Selector<Color>()
-                        {
-                            Normal = (Color)theme.Resources["PopupButtonOverlayBackgroundColorNormal"],
-                            Pressed = (Color)theme.Resources["PopupButtonOverlayBackgroundColorPressed"],
-                            Other = (Color)theme.Resources["PopupButtonOverlayBackgroundColorSelected"],
-                        },
-                    },
-                    Text = new TextLabelStyle()
-                    {
-                        TextColor = (Color)theme.Resources["PopupButtonTextColor"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Progress", new ProgressStyle()
-            {
-                Size = new Size(200, 5),
-                Track = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["ProgressTrackBackgroundColor"],
-                },
-                Buffer = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["ProgressBufferBackgroundColor"],
-                },
-                Progress = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["ProgressProgressBackgroundColor"],
-                },
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.RadioButton", new ButtonStyle()
-            {
-                Size = new Size(30, 30),
-                Icon = new ImageViewStyle()
-                {
-                    Opacity = new Selector<float?>()
-                    {
-                        Normal = 1.0f,
-                        Disabled = 0.4f,
-                        Selected = 1.0f,
-                    },
-                    BackgroundImage = new Selector<string>()
-                    {
-                        Pressed = (string)theme.Resources["RadioButtonIconBackgroundImagePressed"],
-                        Selected = (string)theme.Resources["RadioButtonIconBackgroundImageSelected"],
-                        Other = (string)theme.Resources["RadioButtonIconBackgroundImageOther"],
-                    }
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 12,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["RadioButtonTextColorNormal"],
-                        Pressed = (Color)theme.Resources["RadioButtonTextColorPressed"],
-                        Disabled = (Color)theme.Resources["RadioButtonTextColorDisabled"],
-                    }
-                }
-            });
+            ThemeManager.AddPackageTheme(Instance);
+            Instance.GetExternalThemeKeyListSet();
+        }
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Slider", new SliderStyle()
-            {
-                Size = new Size(200, 50),
-                TrackThickness = 5,
-                Track = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["SliderTrackColor"],
-                },
-                Progress = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["SliderProgressColor"],
-                },
-                Thumb = new ImageViewStyle()
-                {
-                    Size = new Size(50, 50),
-                    ResourceUrl = (string)theme.Resources["SliderThumbImageResourceUrl"],
-                    BackgroundImage = new Selector<string>()
-                    {
-                        Normal = (string)theme.Resources["SliderThumbBackgroundImageNormal"],
-                        Pressed = (string)theme.Resources["SliderThumbBackgroundImagePressed"],
-                    }
-                },
-                ValueIndicatorImage = new ImageViewStyle()
-                {
-                    Size = new Size(83, 54),
-                    ResourceUrl = (string)theme.Resources["SliderValueIndicatorImage"],
-                },
-            });
+        private static void SetBackgroundColor(ViewStyle style, Selector<Color> value) => style.BackgroundColor = value; 
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Switch", new SwitchStyle()
-            {
-                Size = new Size(96, 60),
-                Track = new ImageViewStyle()
-                {
-                    Size = new Size(96, 60),
-                    ResourceUrl = new Selector<string>()
-                    {
-                        Normal = (string)theme.Resources["SwitchTrackImageResourceUrlNormal"],
-                        Selected = (string)theme.Resources["SwitchTrackImageResourceUrlSelected"],
-                        Disabled = (string)theme.Resources["SwitchTrackImageResourceUrlDisabled"],
-                        DisabledSelected = (string)theme.Resources["SwitchTrackImageResourceUrlDisabledSelected"],
-                    }
-                },
-                Thumb = new ImageViewStyle()
-                {
-                    Size = new Size(60, 60),
-                    ResourceUrl = new Selector<string>()
-                    {
-                        Normal = (string)theme.Resources["SwitchThumbImageResourceUrlNormal"],
-                        Disabled = (string)theme.Resources["SwitchThumbImageResourceUrlDisabled"],
-                        Selected = (string)theme.Resources["SwitchThumbImageResourceUrlSelected"],
-                    }
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 12,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["SwitchTextColorNormal"],
-                        Pressed = (Color)theme.Resources["SwitchTextColorPressed"],
-                        Disabled = (Color)theme.Resources["SwitchTextColorDisabled"],
-                    }
-                }
-            });
+        private static void SetBackgroundImage(ViewStyle style, Selector<string> value) => style.BackgroundImage = value;
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Tab", new TabStyle()
-            {
-                Size = new Size(480, 80),
-                BackgroundColor = (Color)theme.Resources["TabBackgroundColor"],
-                UnderLine = new ViewStyle()
-                {
-                    Size = new Size(0, 6),
-                    BackgroundColor = (Color)theme.Resources["TabUnderLineBackgroundColor"],
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 16,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["TabTextColorNormal"],
-                        Selected = (Color)theme.Resources["TabTextColorSelected"],
-                    }
-                }
-            });
+        private static void SetBackgroundBorder(ViewStyle style, Rectangle value) => style.BackgroundImageBorder = value;
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Toast", new ToastStyle()
-            {
-                Size = new Size(480, 80),
-                BackgroundColor = (Color)theme.Resources["ToastBackgroundColor"],
-                Text = new TextLabelStyle()
-                {
-                    Padding = new Extents(12, 12, 8, 8)
-                }
-            });
+        private static void SetButtonTextColor(ViewStyle style, Selector<Color> value) => ((ButtonStyle)style).Text.TextColor = value;
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Loading", new LoadingStyle()
-            {
-                LoadingSize = new Size(100, 100),
-            });
+        private static void SetButtonTextPixelSize(ViewStyle style, Selector<float?> value) => ((ButtonStyle)style).Text.PixelSize = value;
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Pagination", new PaginationStyle()
-            {
-                IndicatorImageUrl = new Selector<string>()
-                {
-                    Normal = (string)theme.Resources["PaginationIndicatorImageUrlNormal"],
-                    Selected = (string)theme.Resources["PaginationIndicatorImageUrlSelected"],
-                }
-            });
+        private static void SetButtonIconResourceUrl(ViewStyle style, Selector<string> value) => ((ButtonStyle)style).Icon.ResourceUrl = value;
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Scrollbar", new ScrollbarStyle()
-            {
-                TrackThickness = 6,
-                ThumbThickness = 6,
-                TrackColor = (Color)theme.Resources["ScrollbarTrackColor"],
-                ThumbColor = (Color)theme.Resources["ScrollbarThumbColor"],
-                TrackPadding = 4
-            });
+        private static void SetButtonIconBorder(ViewStyle style, Rectangle value) => ((ButtonStyle)style).Icon.Border = value;
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.RecyclerViewItem", new RecyclerViewItemStyle()
-            {
-                BackgroundColor = new Selector<Color>()
-                {
-                    Normal = (Color)theme.Resources["RecyclerViewItemBackgroundColorNormal"],
-                    Pressed = (Color)theme.Resources["RecyclerViewItemBackgroundColorPressed"],
-                    Disabled = (Color)theme.Resources["RecyclerViewItemBackgroundColorDisabled"],
-                    Selected = (Color)theme.Resources["RecyclerViewItemBackgroundColorSelected"],
-                },
-            });
-            
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultLinearItem", new DefaultLinearItemStyle()
-            {
-                SizeHeight = 130,
-                Padding = new Extents(20, 20, 5, 5),
-                BackgroundColor = new Selector<Color>()
-                {
-                    Normal = (Color)theme.Resources["RecyclerViewItemBackgroundColorNormal"],
-                    Pressed = (Color)theme.Resources["RecyclerViewItemBackgroundColorPressed"],
-                    Disabled = (Color)theme.Resources["RecyclerViewItemBackgroundColorDisabled"],
-                    Selected = (Color)theme.Resources["RecyclerViewItemBackgroundColorSelected"],
-                },
-                Label = new TextLabelStyle()
-                {
-                    PointSize = 10,
-                    Ellipsis = true,
-                },
-                SubLabel = new TextLabelStyle()
-                {
-                    PointSize = 6,
-                    Ellipsis = true,
-                },
-                Icon = new ViewStyle()
-                {
-                    Margin = new Extents(0, 20, 0, 0)
-                },
-                Extra = new ViewStyle()
-                {
-                    Margin = new Extents(20, 0, 0, 0)
-                },
-                Seperator = new ViewStyle()
-                {
-                    Margin = new Extents(5, 5, 0, 0),
-                    BackgroundColor = new Color(0.78f, 0.78f, 0.78f, 1),
-                },
-            });
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultGridItem", new DefaultGridItemStyle()
-            {
-                Padding = new Extents(5, 5, 5, 5),
-                Caption = new TextLabelStyle()
-                {
-                    PointSize = 9,
-                    Ellipsis = true,
-                },
-                Badge = new ViewStyle()
-                {
-                    Margin = new Extents(5, 5, 5, 5),
-                },
-            });
+        private static void SetButtonIconBackgroundColor(ViewStyle style, Selector<Color> value) => ((ButtonStyle)style).Icon.BackgroundColor = value;
 
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultTitleItem", new DefaultTitleItemStyle()
-            {
-                SizeHeight = 90,
-                Padding = new Extents(10, 10, 5, 5),
-                BackgroundColor = new Selector<Color>()
-                {
-                    Normal = (Color)theme.Resources["TitleBackgroundColorNormal"],
-                },
-                Label = new TextLabelStyle()
-                {
-                    PointSize = 10,
-                    Ellipsis = true,
-                },
-                Icon = new ViewStyle()
-                {
-                    Margin = new Extents(10, 0, 0, 0)
-                },
-                Seperator = new ViewStyle()
-                {
-                    Margin = new Extents(0, 0, 0, 0),
-                    BackgroundColor = new Color(0.85f, 0.85f, 0.85f, 1),
-                },
-            });
+        private static void SetButtonIconBackgroundImageUrl(ViewStyle style, Selector<string> value) => ((ButtonStyle)style).Icon.BackgroundImage = value;
 
-            return theme;
-        }
+        private static void SetButtonIconBackgroundBorder(ViewStyle style, Rectangle value) => ((ButtonStyle)style).Icon.BackgroundImageBorder = value;
     }
 }
 
-#endif
diff --git a/src/Tizen.NUI.Components/Theme/DefaultThemeCommon.cs b/src/Tizen.NUI.Components/Theme/DefaultThemeCommon.cs
new file mode 100644 (file)
index 0000000..0181272
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#if !PROFILE_WEARABLE
+
+using System.Diagnostics.CodeAnalysis;
+using Tizen.NUI.BaseComponents;
+
+namespace Tizen.NUI.Components
+{
+    // It is a C# version of res/Tizen.NUI.Components_Tizen.NUI.Theme.Common.xaml
+    internal partial class DefaultThemeCreator : IThemeCreator
+    {
+        [SuppressMessage("Microsoft.Reliability", "CA2000: Dispose objects before losing scope", Justification = "The responsibility to dispose the object is transferred to the theme object.")]
+        public Theme Create()
+        {
+            var theme = new Theme()
+            {
+                Id = Tizen.NUI.DefaultThemeCreator.DefaultId,
+                Version = Tizen.NUI.DefaultThemeCreator.DefaultVersion
+            };
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.Button", new ButtonStyle()
+            {
+                Size = new Size(339, 96),
+                CornerRadiusPolicy = VisualTransformPolicyType.Relative,
+                CornerRadius = 0.2916f,
+                BackgroundColor = new Selector<Color>()
+                {
+                    Normal = new Color(0.039f, 0.055f, 0.29f, 1),
+                    Focused = new Color(0, 0.2f, 0.545f, 1),
+                    Pressed = new Color(0.106f, 0.412f, 0.792f, 1),
+                    Disabled = new Color(0.765f, 0.792f, 0.824f, 1),
+                },
+                Text = new TextLabelStyle()
+                {
+                    PixelSize = 32,
+                    TextColor = Color.White,
+                }
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.CheckBox", new ButtonStyle()
+            {
+                Size = new Size(30, 30),
+                Icon = new ImageViewStyle()
+                {
+                    Opacity = new Selector<float?>()
+                    {
+                        Normal = 1.0f,
+                        Disabled = 0.4f,
+                        Selected = 1.0f,
+                    },
+                    BackgroundImage = new Selector<string>()
+                    {
+                        Pressed = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_p.png",
+                        Selected = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_p.png",
+                        Other = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_n.png",
+                    },
+                    ResourceUrl = new Selector<string>()
+                    {
+                        Pressed = "",
+                        Selected = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_s.png",
+                        Other = "",
+                    },
+                },
+                Text = new TextLabelStyle()
+                {
+                    PointSize = 12,
+                    TextColor = new Selector<Color>()
+                    {
+                        Normal = new Color(0.22f, 0.22f, 0.22f, 1),
+                        Pressed = new Color(0.11f, 0.11f, 0.11f, 1),
+                        Disabled = new Color(0.66f, 0.66f, 0.66f, 1),
+                    }
+                }
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.Popup", new PopupStyle()
+            {
+                Size = new Size(500, 280),
+                BackgroundColor = new Color(0.9f, 0.9f, 0.9f, 1),
+                ImageShadow = new ImageShadow()
+                {
+                    Url = FrameworkInformation.ResourcePath + "nui_component_default_popup_shadow.png",
+                    Border = new Rectangle(24, 24, 24, 24),
+                    Extents = new Vector2(48, 48)
+                },
+                Title = new TextLabelStyle()
+                {
+                    PointSize = 16,
+                    Padding = new Extents(20, 20, 20, 20),
+                },
+                Buttons = new ButtonStyle()
+                {
+                    Size = new Size(0, 80),
+                    BackgroundColor = new Selector<Color>()
+                    {
+                        Normal = new Color(1, 1, 1, 1),
+                        Pressed = new Color(1, 1, 1, 0.5f),
+                    },
+                    Overlay = new ImageViewStyle()
+                    {
+                        BackgroundColor = new Selector<Color>()
+                        {
+                            Normal = new Color(1, 1, 1, 1),
+                            Pressed = new Color(0, 0, 0, 0.1f),
+                            Other = new Color(1, 1, 1, 1),
+                        },
+                    },
+                    Text = new TextLabelStyle()
+                    {
+                        TextColor = new Color(0.05f, 0.63f, 0.9f, 1),
+                    }
+                }
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.Progress", new ProgressStyle()
+            {
+                Size = new Size(200, 5),
+                Track = new ImageViewStyle()
+                {
+                    BackgroundColor = new Color(0, 0, 0, 0.1f),
+                },
+                Buffer = new ImageViewStyle()
+                {
+                    BackgroundColor = new Color(0.05f, 0.63f, 0.9f, 0.3f),
+                },
+                Progress = new ImageViewStyle()
+                {
+                    BackgroundColor = new Color(0.05f, 0.63f, 0.9f, 1),
+                },
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.RadioButton", new ButtonStyle()
+            {
+                Size = new Size(30, 30),
+                Icon = new ImageViewStyle()
+                {
+                    Opacity = new Selector<float?>()
+                    {
+                        Normal = 1.0f,
+                        Disabled = 0.4f,
+                        Selected = 1.0f,
+                    },
+                    BackgroundImage = new Selector<string>()
+                    {
+                        Pressed = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_p.png",
+                        Selected = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_s.png",
+                        Other = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_n.png",
+                    }
+                },
+                Text = new TextLabelStyle()
+                {
+                    PointSize = 12,
+                    TextColor = new Selector<Color>()
+                    {
+                        Normal = new Color(0.22f, 0.22f, 0.22f, 1),
+                        Pressed = new Color(0.11f, 0.11f, 0.11f, 1),
+                        Disabled = new Color(0.66f, 0.66f, 0.66f, 1),
+                    }
+                }
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.Slider", new SliderStyle()
+            {
+                Size = new Size(200, 50),
+                TrackThickness = 5,
+                Track = new ImageViewStyle()
+                {
+                    BackgroundColor = new Color(0, 0, 0, 0.1f),
+                },
+                Progress = new ImageViewStyle()
+                {
+                    BackgroundColor = new Color(0.5f, 0.63f, 0.9f, 1),
+                },
+                Thumb = new ImageViewStyle()
+                {
+                    Size = new Size(50, 50),
+                    ResourceUrl = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_n.png",
+                    BackgroundImage = new Selector<string>()
+                    {
+                        Normal = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_bg_p.png",
+                        Pressed = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_bg_p.png",
+                    }
+                },
+                ValueIndicatorImage = new ImageViewStyle()
+                {
+                    Size = new Size(83, 54),
+                    ResourceUrl = FrameworkInformation.ResourcePath + "nui_component_default_slider_value_indicator.png",
+                },
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.Switch", new SwitchStyle()
+            {
+                Size = new Size(96, 60),
+                Track = new ImageViewStyle()
+                {
+                    Size = new Size(96, 60),
+                    ResourceUrl = new Selector<string>()
+                    {
+                        Normal = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_n.png",
+                        Selected = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_s.png",
+                        Disabled = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_d.png",
+                        DisabledSelected = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_ds.png",
+                    }
+                },
+                Thumb = new ImageViewStyle()
+                {
+                    Size = new Size(60, 60),
+                    ResourceUrl = new Selector<string>()
+                    {
+                        Normal = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_n.png",
+                        Disabled = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_d.png",
+                        Selected = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_n.png",
+                    }
+                },
+                Text = new TextLabelStyle()
+                {
+                    PointSize = 12,
+                    TextColor = new Selector<Color>()
+                    {
+                        Normal = new Color(0.22f, 0.22f, 0.22f, 1),
+                        Pressed = new Color(0.11f, 0.11f, 0.11f, 1),
+                        Disabled = new Color(0.66f, 0.66f, 0.66f, 1),
+                    }
+                }
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.Loading", new LoadingStyle()
+            {
+                LoadingSize = new Size(100, 100),
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.Pagination", new PaginationStyle()
+            {
+                IndicatorImageUrl = new Selector<string>()
+                {
+                    Normal = FrameworkInformation.ResourcePath + "nui_component_default_pagination_normal_dot.png",
+                    Selected = FrameworkInformation.ResourcePath + "nui_component_default_pagination_focus_dot.png",
+                }
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.Scrollbar", new ScrollbarStyle()
+            {
+                TrackThickness = 6,
+                ThumbThickness = 6,
+                TrackColor = new Color(1, 1, 1, 0.15f),
+                ThumbColor = new Color(0.6f, 0.6f, 0.6f, 1.0f),
+                TrackPadding = 4
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.RecyclerViewItem", new RecyclerViewItemStyle()
+            {
+                BackgroundColor = new Selector<Color>()
+                {
+                    Normal = new Color(1, 1, 1, 1),
+                    Pressed = new Color(0.85f, 0.85f, 0.85f, 1),
+                    Disabled = new Color(0.70f, 0.70f, 0.70f, 1),
+                    Selected = new Color(0.701f, 0.898f, 0.937f, 1),
+                },
+            });
+            
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultLinearItem", new DefaultLinearItemStyle()
+            {
+                SizeHeight = 130,
+                Padding = new Extents(20, 20, 5, 5),
+                BackgroundColor = new Selector<Color>()
+                {
+                    Normal = new Color(1, 1, 1, 1),
+                    Pressed = new Color(0.85f, 0.85f, 0.85f, 1),
+                    Disabled = new Color(0.70f, 0.70f, 0.70f, 1),
+                    Selected = new Color(0.701f, 0.898f, 0.937f, 1),
+                },
+                Label = new TextLabelStyle()
+                {
+                    PointSize = 10,
+                    Ellipsis = true,
+                },
+                SubLabel = new TextLabelStyle()
+                {
+                    PointSize = 6,
+                    Ellipsis = true,
+                },
+                Icon = new ViewStyle()
+                {
+                    Margin = new Extents(0, 20, 0, 0)
+                },
+                Extra = new ViewStyle()
+                {
+                    Margin = new Extents(20, 0, 0, 0)
+                },
+                Seperator = new ViewStyle()
+                {
+                    Margin = new Extents(5, 5, 0, 0),
+                    BackgroundColor = new Color(0.78f, 0.78f, 0.78f, 1),
+                },
+            });
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultGridItem", new DefaultGridItemStyle()
+            {
+                Padding = new Extents(5, 5, 5, 5),
+                Caption = new TextLabelStyle()
+                {
+                    PointSize = 9,
+                    Ellipsis = true,
+                },
+                Badge = new ViewStyle()
+                {
+                    Margin = new Extents(5, 5, 5, 5),
+                },
+            });
+
+            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultTitleItem", new DefaultTitleItemStyle()
+            {
+                SizeHeight = 90,
+                Padding = new Extents(10, 10, 5, 5),
+                BackgroundColor = new Selector<Color>()
+                {
+                    Normal = new Color(0.78f, 0.78f, 0.78f, 1),
+                },
+                Label = new TextLabelStyle()
+                {
+                    PointSize = 10,
+                    Ellipsis = true,
+                },
+                Icon = new ViewStyle()
+                {
+                    Margin = new Extents(10, 0, 0, 0)
+                },
+                Seperator = new ViewStyle()
+                {
+                    Margin = new Extents(0, 0, 0, 0),
+                    BackgroundColor = new Color(0.85f, 0.85f, 0.85f, 1),
+                },
+            });
+
+            return theme;
+        }
+    }
+}
+
+#endif
diff --git a/src/Tizen.NUI.Components/Theme/DefaultThemeMobile.cs b/src/Tizen.NUI.Components/Theme/DefaultThemeMobile.cs
deleted file mode 100644 (file)
index ddc52c1..0000000
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright(c) 2021 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-#if PROFILE_MOBILE
-
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using Tizen.NUI.BaseComponents;
-using Tizen.NUI.Binding;
-
-namespace Tizen.NUI.Components
-{
-    // It is a C# version of res/Tizen.NUI.Components_Tizen.NUI.Theme.Common.xaml
-    internal class DefaultThemeCreator : IThemeCreator
-    {
-        public ResourceDictionary CreateThemeResource() => new ResourceDictionary()
-        {
-            ["ButtonBackgroundColorNormal"] = new Color(0.88f, 0.88f, 0.88f, 1),
-            ["ButtonBackgroundColorPressed"] = new Color(0.77f, 0.77f, 0.77f, 1),
-            ["ButtonBackgroundColorDisabled"] = new Color(0.88f, 0.88f, 0.88f, 1),
-            ["ButtonTextColorNormal"] = new Color(0.22f, 0.22f, 0.22f, 1),
-            ["ButtonTextColorPressed"] = new Color(0.11f, 0.11f, 0.11f, 1),
-            ["ButtonTextColorDisabled"] = new Color(0.66f, 0.66f, 0.66f, 1),
-            ["CheckBoxIconBackgroundImagePressed"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_p.png",
-            ["CheckBoxIconBackgroundImageSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_p.png",
-            ["CheckBoxIconBackgroundImageOther"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_n.png",
-            ["CheckBoxIconImageResourceUrlPressed"] = "",
-            ["CheckBoxIconImageResourceUrlSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_s.png",
-            ["CheckBoxIconImageResourceUrlOther"] = "",
-            ["CheckBoxTextColorNormal"] = new Color(0.22f, 0.22f, 0.22f, 1),
-            ["CheckBoxTextColorPressed"] = new Color(0.11f, 0.11f, 0.11f, 1),
-            ["CheckBoxTextColorDisabled"] = new Color(0.66f, 0.66f, 0.66f, 1),
-            ["DropDownBackgroundImagePressed"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_p.png",
-            ["DropDownBackgroundImageOther"] = FrameworkInformation.ResourcePath + "nui_component_default_checkbox_bg_n.png",
-            ["DropDownIconImageResourceUrl"] = FrameworkInformation.ResourcePath + "nui_component_default_dropdown_button_icon.png",
-            ["DropDownListBackgroundImageResourceUrl"] = FrameworkInformation.ResourcePath + "nui_component_default_dropdown_list_bg.png",
-            ["DropDownDataItemBackgroundColorPressed"] = new Color(0.05f, 0.63f, 0.9f, 1),
-            ["DropDownDataItemBackgroundColorSelected"] = new Color(0.8f, 0.8f, 0.8f, 1),
-            ["DropDownDataItemBackgroundColorNormal"] = new Color(1, 1, 1, 1),
-            ["PopupBackgroundColor"] = new Color(0.9f, 0.9f, 0.9f, 1),
-            ["PopupImageShadowUrl"] = FrameworkInformation.ResourcePath + "nui_component_default_popup_shadow.png",
-            ["PopupButtonBackgroundColorNormal"] = new Color(1, 1, 1, 1),
-            ["PopupButtonBackgroundColorPressed"] = new Color(1, 1, 1, 0.5f),
-            ["PopupButtonOverlayBackgroundColorNormal"] = new Color(1, 1, 1, 1),
-            ["PopupButtonOverlayBackgroundColorPressed"] = new Color(0, 0, 0, 0.1f),
-            ["PopupButtonOverlayBackgroundColorSelected"] = new Color(1, 1, 1, 1),
-            ["PopupButtonTextColor"] = new Color(0.05f, 0.63f, 0.9f, 1),
-            ["ProgressTrackBackgroundColor"] = new Color(0, 0, 0, 0.1f),
-            ["ProgressBufferBackgroundColor"] = new Color(0.05f, 0.63f, 0.9f, 0.3f),
-            ["ProgressProgressBackgroundColor"] = new Color(0.05f, 0.63f, 0.9f, 1),
-            ["RadioButtonIconBackgroundImagePressed"] = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_p.png",
-            ["RadioButtonIconBackgroundImageSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_s.png",
-            ["RadioButtonIconBackgroundImageOther"] = FrameworkInformation.ResourcePath + "nui_component_default_radiobutton_n.png",
-            ["RadioButtonTextColorNormal"] = new Color(0.22f, 0.22f, 0.22f, 1),
-            ["RadioButtonTextColorPressed"] = new Color(0.11f, 0.11f, 0.11f, 1),
-            ["RadioButtonTextColorDisabled"] = new Color(0.66f, 0.66f, 0.66f, 1),
-            ["SliderTrackColor"] = new Color(0, 0, 0, 0.1f),
-            ["SliderProgressColor"] = new Color(0.5f, 0.63f, 0.9f, 1),
-            ["SliderThumbImageResourceUrl"] = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_n.png",
-            ["SliderThumbBackgroundImageNormal"] = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_bg_p.png",
-            ["SliderThumbBackgroundImagePressed"] = FrameworkInformation.ResourcePath + "nui_component_default_slider_thumb_bg_p.png",
-            ["SliderValueIndicatorImage"] = FrameworkInformation.ResourcePath + "nui_component_default_slider_value_indicator.png",
-            ["SwitchTrackImageResourceUrlNormal"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_n.png",
-            ["SwitchTrackImageResourceUrlSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_s.png",
-            ["SwitchTrackImageResourceUrlDisabled"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_d.png",
-            ["SwitchTrackImageResourceUrlDisabledSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_track_ds.png",
-            ["SwitchThumbImageResourceUrlNormal"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_n.png",
-            ["SwitchThumbImageResourceUrlDisabled"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_d.png",
-            ["SwitchThumbImageResourceUrlSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_switch_thumb_n.png",
-            ["SwitchTextColorNormal"] = new Color(0.22f, 0.22f, 0.22f, 1),
-            ["SwitchTextColorPressed"] = new Color(0.11f, 0.11f, 0.11f, 1),
-            ["SwitchTextColorDisabled"] = new Color(0.66f, 0.66f, 0.66f, 1),
-            ["TabBackgroundColor"] = Color.Yellow,
-            ["TabUnderLineBackgroundColor"] = new Color(0.05f, 0.63f, 0.9f, 1.0f),
-            ["TabTextColorNormal"] = Color.Black,
-            ["TabTextColorSelected"] = new Color(0.05f, 0.63f, 0.9f, 1),
-            ["ToastBackgroundColor"] = new Color(0, 0, 0, 0.8f),
-            ["PaginationIndicatorImageUrlNormal"] = FrameworkInformation.ResourcePath + "nui_component_default_pagination_normal_dot.png",
-            ["PaginationIndicatorImageUrlSelected"] = FrameworkInformation.ResourcePath + "nui_component_default_pagination_focus_dot.png",
-            ["ScrollbarTrackColor"] = new Color(1, 1, 1, 0.15f),
-            ["ScrollbarThumbColor"] = new Color(0.6f, 0.6f, 0.6f, 1.0f),
-            ["RecyclerViewItemBackgroundColorNormal"] = new Color(1, 1, 1, 1),
-            ["RecyclerViewItemBackgroundColorPressed"] = new Color(0.85f, 0.85f, 0.85f, 1),
-            ["RecyclerViewItemBackgroundColorDisabled"] = new Color(0.70f, 0.70f, 0.70f, 1),
-            ["RecyclerViewItemBackgroundColorSelected"] = new Color(0.701f, 0.898f, 0.937f, 1),
-            ["TitleBackgroundColorNormal"] = new Color(0.78f, 0.78f, 0.78f, 1),
-        };
-
-        public Theme Create() => Create(null);
-
-        [SuppressMessage("Microsoft.Reliability", "CA2000: Dispose objects before losing scope", Justification = "The responsibility to dispose the object is transferred to the theme object.")]
-        public Theme Create(IEnumerable<KeyValuePair<string, string>> changedResources)
-        {
-            var theme = new Theme() { Id = "Tizen.NUI.Theme.Common" };
-
-            theme.SetChangedResources(changedResources);
-            theme.Resources = CreateThemeResource();
-            theme.OnThemeResourcesChanged();
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Button", new ButtonStyle()
-            {
-                Size = new Size(100, 45),
-                BackgroundColor = new Selector<Color>()
-                {
-                    Normal = (Color)theme.Resources["ButtonBackgroundColorNormal"],
-                    Pressed = (Color)theme.Resources["ButtonBackgroundColorPressed"],
-                    Disabled = (Color)theme.Resources["ButtonBackgroundColorDisabled"],
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 12,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["ButtonTextColorNormal"],
-                        Pressed = (Color)theme.Resources["ButtonTextColorPressed"],
-                        Disabled = (Color)theme.Resources["ButtonTextColorDisabled"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.CheckBox", new ButtonStyle()
-            {
-                Size = new Size(30, 30),
-                Icon = new ImageViewStyle()
-                {
-                    Opacity = new Selector<float?>()
-                    {
-                        Normal = 1.0f,
-                        Disabled = 0.4f,
-                        Selected = 1.0f,
-                    },
-                    BackgroundImage = new Selector<string>()
-                    {
-                        Pressed = (string)theme.Resources["CheckBoxIconBackgroundImagePressed"],
-                        Selected = (string)theme.Resources["CheckBoxIconBackgroundImageSelected"],
-                        Other = (string)theme.Resources["CheckBoxIconBackgroundImageOther"],
-                    },
-                    ResourceUrl = new Selector<string>()
-                    {
-                        Pressed = (string)theme.Resources["CheckBoxIconImageResourceUrlPressed"],
-                        Selected = (string)theme.Resources["CheckBoxIconImageResourceUrlSelected"],
-                        Other = (string)theme.Resources["CheckBoxIconImageResourceUrlOther"],
-                    },
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 12,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["CheckBoxTextColorNormal"],
-                        Pressed = (Color)theme.Resources["CheckBoxTextColorPressed"],
-                        Disabled = (Color)theme.Resources["CheckBoxTextColorDisabled"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Popup", new PopupStyle()
-            {
-                Size = new Size(500, 280),
-                BackgroundColor = (Color)theme.Resources["PopupBackgroundColor"],
-                ImageShadow = new ImageShadow()
-                {
-                    Url = (string)theme.Resources["PopupImageShadowUrl"],
-                    Border = new Rectangle(24, 24, 24, 24),
-                    Extents = new Vector2(48, 48)
-                },
-                Title = new TextLabelStyle()
-                {
-                    PointSize = 16,
-                    Padding = new Extents(20, 20, 20, 20),
-                },
-                Buttons = new ButtonStyle()
-                {
-                    Size = new Size(0, 80),
-                    BackgroundColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["PopupButtonBackgroundColorNormal"],
-                        Pressed = (Color)theme.Resources["PopupButtonBackgroundColorPressed"],
-                    },
-                    Overlay = new ImageViewStyle()
-                    {
-                        BackgroundColor = new Selector<Color>()
-                        {
-                            Normal = (Color)theme.Resources["PopupButtonOverlayBackgroundColorNormal"],
-                            Pressed = (Color)theme.Resources["PopupButtonOverlayBackgroundColorPressed"],
-                            Other = (Color)theme.Resources["PopupButtonOverlayBackgroundColorSelected"],
-                        },
-                    },
-                    Text = new TextLabelStyle()
-                    {
-                        TextColor = (Color)theme.Resources["PopupButtonTextColor"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Progress", new ProgressStyle()
-            {
-                Size = new Size(200, 5),
-                Track = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["ProgressTrackBackgroundColor"],
-                },
-                Buffer = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["ProgressBufferBackgroundColor"],
-                },
-                Progress = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["ProgressProgressBackgroundColor"],
-                },
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.RadioButton", new ButtonStyle()
-            {
-                Size = new Size(30, 30),
-                Icon = new ImageViewStyle()
-                {
-                    Opacity = new Selector<float?>()
-                    {
-                        Normal = 1.0f,
-                        Disabled = 0.4f,
-                        Selected = 1.0f,
-                    },
-                    BackgroundImage = new Selector<string>()
-                    {
-                        Pressed = (string)theme.Resources["RadioButtonIconBackgroundImagePressed"],
-                        Selected = (string)theme.Resources["RadioButtonIconBackgroundImageSelected"],
-                        Other = (string)theme.Resources["RadioButtonIconBackgroundImageOther"],
-                    }
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 12,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["RadioButtonTextColorNormal"],
-                        Pressed = (Color)theme.Resources["RadioButtonTextColorPressed"],
-                        Disabled = (Color)theme.Resources["RadioButtonTextColorDisabled"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Slider", new SliderStyle()
-            {
-                Size = new Size(200, 50),
-                TrackThickness = 5,
-                Track = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["SliderTrackColor"],
-                },
-                Progress = new ImageViewStyle()
-                {
-                    BackgroundColor = (Color)theme.Resources["SliderProgressColor"],
-                },
-                Thumb = new ImageViewStyle()
-                {
-                    Size = new Size(50, 50),
-                    ResourceUrl = (string)theme.Resources["SliderThumbImageResourceUrl"],
-                    BackgroundImage = new Selector<string>()
-                    {
-                        Normal = (string)theme.Resources["SliderThumbBackgroundImageNormal"],
-                        Pressed = (string)theme.Resources["SliderThumbBackgroundImagePressed"],
-                    }
-                },
-                ValueIndicatorImage = new ImageViewStyle()
-                {
-                    Size = new Size(83, 54),
-                    ResourceUrl = (string)theme.Resources["SliderValueIndicatorImage"],
-                },
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Switch", new SwitchStyle()
-            {
-                Size = new Size(96, 60),
-                Track = new ImageViewStyle()
-                {
-                    Size = new Size(96, 60),
-                    ResourceUrl = new Selector<string>()
-                    {
-                        Normal = (string)theme.Resources["SwitchTrackImageResourceUrlNormal"],
-                        Selected = (string)theme.Resources["SwitchTrackImageResourceUrlSelected"],
-                        Disabled = (string)theme.Resources["SwitchTrackImageResourceUrlDisabled"],
-                        DisabledSelected = (string)theme.Resources["SwitchTrackImageResourceUrlDisabledSelected"],
-                    }
-                },
-                Thumb = new ImageViewStyle()
-                {
-                    Size = new Size(60, 60),
-                    ResourceUrl = new Selector<string>()
-                    {
-                        Normal = (string)theme.Resources["SwitchThumbImageResourceUrlNormal"],
-                        Disabled = (string)theme.Resources["SwitchThumbImageResourceUrlDisabled"],
-                        Selected = (string)theme.Resources["SwitchThumbImageResourceUrlSelected"],
-                    }
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 12,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["SwitchTextColorNormal"],
-                        Pressed = (Color)theme.Resources["SwitchTextColorPressed"],
-                        Disabled = (Color)theme.Resources["SwitchTextColorDisabled"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Tab", new TabStyle()
-            {
-                Size = new Size(480, 80),
-                BackgroundColor = (Color)theme.Resources["TabBackgroundColor"],
-                UnderLine = new ViewStyle()
-                {
-                    Size = new Size(0, 6),
-                    BackgroundColor = (Color)theme.Resources["TabUnderLineBackgroundColor"],
-                },
-                Text = new TextLabelStyle()
-                {
-                    PointSize = 16,
-                    TextColor = new Selector<Color>()
-                    {
-                        Normal = (Color)theme.Resources["TabTextColorNormal"],
-                        Selected = (Color)theme.Resources["TabTextColorSelected"],
-                    }
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Toast", new ToastStyle()
-            {
-                Size = new Size(480, 80),
-                BackgroundColor = (Color)theme.Resources["ToastBackgroundColor"],
-                Text = new TextLabelStyle()
-                {
-                    Padding = new Extents(12, 12, 8, 8)
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Loading", new LoadingStyle()
-            {
-                LoadingSize = new Size(100, 100),
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Pagination", new PaginationStyle()
-            {
-                IndicatorImageUrl = new Selector<string>()
-                {
-                    Normal = (string)theme.Resources["PaginationIndicatorImageUrlNormal"],
-                    Selected = (string)theme.Resources["PaginationIndicatorImageUrlSelected"],
-                }
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.Scrollbar", new ScrollbarStyle()
-            {
-                TrackThickness = 6,
-                ThumbThickness = 6,
-                TrackColor = (Color)theme.Resources["ScrollbarTrackColor"],
-                ThumbColor = (Color)theme.Resources["ScrollbarThumbColor"],
-                TrackPadding = 4
-            });
-
-                        theme.AddStyleWithoutClone("Tizen.NUI.Components.RecyclerViewItem", new RecyclerViewItemStyle()
-            {
-                BackgroundColor = new Selector<Color>()
-                {
-                    Normal = (Color)theme.Resources["RecyclerViewItemBackgroundColorNormal"],
-                    Pressed = (Color)theme.Resources["RecyclerViewItemBackgroundColorPressed"],
-                    Disabled = (Color)theme.Resources["RecyclerViewItemBackgroundColorDisabled"],
-                    Selected = (Color)theme.Resources["RecyclerViewItemBackgroundColorSelected"],
-                },
-            });
-            
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultLinearItem", new DefaultLinearItemStyle()
-            {
-                SizeHeight = 160,
-                Padding = new Extents(10, 10, 20, 20),
-                BackgroundColor = new Selector<Color>()
-                {
-                    Normal = (Color)theme.Resources["RecyclerViewItemBackgroundColorNormal"],
-                    Pressed = (Color)theme.Resources["RecyclerViewItemBackgroundColorPressed"],
-                    Disabled = (Color)theme.Resources["RecyclerViewItemBackgroundColorDisabled"],
-                    Selected = (Color)theme.Resources["RecyclerViewItemBackgroundColorSelected"],
-                },
-                Label = new TextLabelStyle()
-                {
-                    PointSize = 20,
-                    Ellipsis = true,
-                },
-                SubLabel = new TextLabelStyle()
-                {
-                    PointSize = 12,
-                    Ellipsis = true,
-                },
-                Icon = new ViewStyle()
-                {
-                    Margin = new Extents(0, 10, 0, 0)
-                },
-                Extra = new ViewStyle()
-                {
-                    Margin = new Extents(10, 0, 0, 0)
-                },
-                Seperator = new ViewStyle()
-                {
-                    Margin = new Extents(5, 5, 0, 0),
-                    BackgroundColor = new Color(0.78f, 0.78f, 0.78f, 1),
-                },
-            });
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultGridItem", new DefaultGridItemStyle()
-            {
-                Padding = new Extents(5, 5, 5, 5),
-                Caption = new TextLabelStyle()
-                {
-                    PointSize = 9,
-                    Ellipsis = true,
-                },
-                Badge = new ViewStyle()
-                {
-                    Margin = new Extents(5, 5, 5, 5),
-                },
-            });
-
-            theme.AddStyleWithoutClone("Tizen.NUI.Components.DefaultTitleItem", new DefaultTitleItemStyle()
-            {
-                SizeHeight = 50,
-                Padding = new Extents(10, 10, 5, 5),
-                BackgroundColor = new Selector<Color>()
-                {
-                    Normal = (Color)theme.Resources["TitleBackgroundColorNormal"],
-                },
-                Label = new TextLabelStyle()
-                {
-                    PointSize = 15,
-                    Ellipsis = true,
-                },
-                Icon = new ViewStyle()
-                {
-                    Margin = new Extents(10, 0, 0, 0)
-                },
-                Seperator = new ViewStyle()
-                {
-                    Margin = new Extents(0, 0, 0, 0),
-                    BackgroundColor = new Color(0.85f, 0.85f, 0.85f, 1),
-                },
-            });
-
-            return theme;
-        }
-    }
-}
-
-#endif
index 7decf98..d162165 100644 (file)
@@ -23,11 +23,15 @@ using Tizen.NUI.Components.Extension;
 namespace Tizen.NUI.Components
 {
     // It is a C# version of res/Tizen.NUI.Components_Tizen.NUI.Theme.Wearable.xaml
-    internal class DefaultThemeCreator : IThemeCreator
+    internal partial class DefaultThemeCreator : IThemeCreator
     {
         public Theme Create()
         {
-            var theme = new Theme() { Id = "Tizen.NUI.Theme.Wearable" };
+            var theme = new Theme()
+            {
+                Id = Tizen.NUI.DefaultThemeCreator.DefaultId,
+                Version = Tizen.NUI.DefaultThemeCreator.DefaultVersion
+            };
 
             theme.AddStyleWithoutClone("Tizen.NUI.Components.Popup", new PopupStyle()
             {
index a5f4b63..dfc6044 100755 (executable)
@@ -59,7 +59,7 @@ namespace Tizen.NUI.Components
         {
             get
             {
-                return ThemeManager.CurrentTheme?.Id ?? ThemeManager.DefaultTheme.Id;
+                return ThemeManager.CurrentTheme.Id;
             }
             set
             {
index 0caa06d..a072a02 100644 (file)
@@ -26,12 +26,13 @@ namespace Tizen.NUI.Wearable
 
         public static IThemeCreator Instance { get; set; } = new DefaultThemeCreator();
 
-        public Theme Create() => Create(null);
-
-        public Theme Create(IEnumerable<KeyValuePair<string, string>> changedResources)
+        public Theme Create()
         {
-            _ = changedResources;
-            var theme = new Theme() { Id = "Tizen.NUI.Theme.Common" };
+            var theme = new Theme()
+            {
+                Id = Tizen.NUI.DefaultThemeCreator.DefaultId,
+                Version = Tizen.NUI.DefaultThemeCreator.DefaultVersion
+            };
 
             theme.AddStyleWithoutClone("Tizen.NUI.Wearable.CircularPagination", new CircularPaginationStyle()
             {
@@ -80,5 +81,7 @@ namespace Tizen.NUI.Wearable
 
             return theme;
         }
+
+        public HashSet<ExternalThemeKeyList> GetExternalThemeKeyListSet() => null;
     }
 }
index bcffc90..921b206 100644 (file)
@@ -21,6 +21,7 @@
     <ProjectReference Include="..\Tizen.Applications.ComponentBased\Tizen.Applications.ComponentBased.csproj" />
     <ProjectReference Include="..\Tizen.System.Information\Tizen.System.Information.csproj" />
     <ProjectReference Include="..\Tizen.System.SystemSettings\Tizen.System.SystemSettings.csproj" />
+    <ProjectReference Include="..\Tizen.Applications.ThemeManager\Tizen.Applications.ThemeManager.csproj" />
   </ItemGroup>
 
   <Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
index e5579eb..8299d7e 100755 (executable)
@@ -38,14 +38,9 @@ namespace Tizen.NUI
         /// </summary>
         private static System.Resources.ResourceManager resourceManager = null;
 
-        // TODO Enable this after tizen-theme-manager is released.
-        // private readonly ThemeLoader themeLoader = new ThemeLoader();
-
         static NUIApplication()
         {
             Registry.Instance.SavedApplicationThread = Thread.CurrentThread;
-            // TODO Enable this after tizen-theme-manager is released.
-            // themeLoader.ThemeChanged += TizenThemeChanged;
         }
 
         /// <summary>
@@ -55,6 +50,7 @@ namespace Tizen.NUI
         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
         public NUIApplication() : base(new NUICoreBackend())
         {
+            ExternalThemeManager.Initialize();
         }
 
         /// <summary>
@@ -68,6 +64,7 @@ namespace Tizen.NUI
         [EditorBrowsable(EditorBrowsableState.Never)]
         public NUIApplication(Size2D windowSize, Position2D windowPosition) : base(new NUICoreBackend("", NUIApplication.WindowMode.Opaque, windowSize, windowPosition))
         {
+            ExternalThemeManager.Initialize();
         }
 
         /// <summary>
@@ -78,6 +75,7 @@ namespace Tizen.NUI
         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
         public NUIApplication(string styleSheet) : base(new NUICoreBackend(styleSheet))
         {
+            ExternalThemeManager.Initialize();
         }
 
         /// <summary>
@@ -92,6 +90,7 @@ namespace Tizen.NUI
         [EditorBrowsable(EditorBrowsableState.Never)]
         public NUIApplication(string styleSheet, Size2D windowSize, Position2D windowPosition) : base(new NUICoreBackend(styleSheet, WindowMode.Opaque, windowSize, windowPosition))
         {
+            ExternalThemeManager.Initialize();
         }
 
         /// <summary>
@@ -103,6 +102,7 @@ namespace Tizen.NUI
         [SuppressMessage("Microsoft.Design", "CA2000: Dispose objects before losing scope", Justification = "NUICoreBackend is disposed in the base class when the application is terminated")]
         public NUIApplication(string styleSheet, WindowMode windowMode) : base(new NUICoreBackend(styleSheet, windowMode))
         {
+            ExternalThemeManager.Initialize();
         }
 
         /// <summary>
@@ -118,6 +118,7 @@ namespace Tizen.NUI
         [EditorBrowsable(EditorBrowsableState.Never)]
         public NUIApplication(string styleSheet, WindowMode windowMode, Size2D windowSize, Position2D windowPosition) : base(new NUICoreBackend(styleSheet, windowMode, windowSize, windowPosition))
         {
+            ExternalThemeManager.Initialize();
         }
 
         /// <summary>
@@ -136,6 +137,7 @@ namespace Tizen.NUI
             //windowMode and styleSheet will be added later. currenlty it's not working as expected.
             Graphics.Backend = backend;
             Tizen.Log.Error("NUI", "Plaese DO NOT set graphical backend type with this constructor! This will give no effect!");
+            ExternalThemeManager.Initialize();
         }
 
         /// <summary>
@@ -393,6 +395,7 @@ namespace Tizen.NUI
         static public void Preload()
         {
             Interop.Application.PreInitialize();
+            ThemeManager.AddPackageTheme(DefaultThemeCreator.Instance);
             IsPreload = true;
         }
 
@@ -411,29 +414,6 @@ namespace Tizen.NUI
         [EditorBrowsable(EditorBrowsableState.Never)]
         public TransitionOptions TransitionOptions { get; set; }
 
-        // TODO Enable this after tizen-theme-manager is released.
-        // private void TizenThemeChanged(object sender, ThemeEventArgs e)
-        // {
-        //     string prefix = "/theme/";
-
-        //     Dictionary<string, string> changedResources = new Dictionary<string, string>();
-        //     foreach (string key in ThemeManager.DefaultTheme.Resources.Keys)
-        //     {
-        //         // NOTE Need improve this code by checking HasKey
-        //         string newValue = null;
-        //         try
-        //         {
-        //             newValue = e.Theme.GetString(prefix + key);
-        //         }
-        //         catch { }
-        //         if (newValue != null)
-        //         {
-        //             changedResources[key] = newValue;
-        //         }
-        //     }
-        //     ThemeManager.UpdateCurrentThemeResources(changedResources);
-        // }
-
         /// <summary>
         /// Check if it is loaded as dotnet-loader-nui.
         /// </summary>
index 5985c14..8c5fe02 100755 (executable)
@@ -1229,9 +1229,12 @@ namespace Tizen.NUI.BaseComponents
 
             if (backgroundExtraData != null && backgroundExtraData.CornerRadius > 0)
             {
-                PropertyValue cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius);
-                imageMap?.Insert(Visual.Property.CornerRadius, cornerRadius);
-                cornerRadius?.Dispose();
+                using (var cornerRadius = new PropertyValue(backgroundExtraData.CornerRadius))
+                using (var cornerRadiusPolicy = new PropertyValue((int)backgroundExtraData.CornerRadiusPolicy))
+                {
+                    imageMap.Insert(Visual.Property.CornerRadius, cornerRadius);
+                    imageMap.Insert(Visual.Property.CornerRadiusPolicy, new PropertyValue((int)(backgroundExtraData.CornerRadiusPolicy)));
+                }
             }
 
             if (value != null)
index 34c44a6..34edde2 100755 (executable)
@@ -46,23 +46,19 @@ namespace Tizen.NUI.BaseComponents
         [EditorBrowsable(EditorBrowsableState.Never)]
         public void Add(ControlState state, T value)
         {
-            SelectorItems.Add(new SelectorItem<T>(state, value));
-            All = default;
-        }
+            if (state == ControlState.All)
+            {
+                All = value;
+                return;
+            }
 
-        /// <summary>
-        /// Adds the specified state and value to the <see cref="SelectorItems"/>.
-        /// </summary>
-        /// <param name="selectorItem">The selector item class that stores a state-value pair.</param>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public void Add(SelectorItem<T> selectorItem)
-        {
             // To prevent a state from having multiple values, remove existing state-value pair.
-            int index = SelectorItems.FindIndex(x => x.State == selectorItem.State);
+            int index = SelectorItems.FindIndex(x => x.State == state);
             if (index != -1)
                 SelectorItems.RemoveAt(index);
 
-            SelectorItems.Add(selectorItem);
+            SelectorItems.Add(new SelectorItem<T>(state, value));
+            All = default;
         }
 
         /// <since_tizen> 6 </since_tizen>
@@ -103,91 +99,100 @@ namespace Tizen.NUI.BaseComponents
             get;
             set;
         }
+
         /// <summary>
         /// Normal State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Normal
         {
-            get => SelectorItems.Find(x => x.State == ControlState.Normal).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.Normal);
             set => Add(ControlState.Normal, value);
         }
         /// <summary>
         /// Pressed State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Pressed
         {
-            get => SelectorItems.Find(x => x.State == ControlState.Pressed).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.Pressed);
             set => Add(ControlState.Pressed, value);
         }
         /// <summary>
         /// Focused State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Focused
         {
-            get => SelectorItems.Find(x => x.State == ControlState.Focused).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.Focused);
             set => Add(ControlState.Focused, value);
         }
         /// <summary>
         /// Selected State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Selected
         {
-            get => SelectorItems.Find(x => x.State == ControlState.Selected).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.Selected);
             set => Add(ControlState.Selected, value);
         }
         /// <summary>
         /// Disabled State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Disabled
         {
-            get => SelectorItems.Find(x => x.State == ControlState.Disabled).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.Disabled);
             set => Add(ControlState.Disabled, value);
         }
         /// <summary>
         /// DisabledFocused State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T DisabledFocused
         {
-            get => SelectorItems.Find(x => x.State == ControlState.DisabledFocused).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.DisabledFocused);
             set => Add(ControlState.DisabledFocused, value);
         }
         /// <summary>
         /// SelectedFocused State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         public T SelectedFocused
         {
-            get => SelectorItems.Find(x => x.State == ControlState.SelectedFocused).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.SelectedFocused);
             set => Add(ControlState.SelectedFocused, value);
         }
         /// <summary>
         /// DisabledSelected State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T DisabledSelected
         {
-            get => SelectorItems.Find(x => x.State == ControlState.DisabledSelected).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.DisabledSelected);
             set => Add(ControlState.DisabledSelected, value);
         }
 
@@ -195,11 +200,12 @@ namespace Tizen.NUI.BaseComponents
         /// Other State.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
+        /// <exception cref="KeyNotFoundException">Thrown when the selector does not contain the this value.</exception>
         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
         public T Other
         {
-            get => SelectorItems.Find(x => x.State == ControlState.Other).Value;
+            get => GetOrThrowKeyNotFound(x => x.State == ControlState.Other);
             set => Add(ControlState.Other, value);
         }
 
@@ -344,6 +350,26 @@ namespace Tizen.NUI.BaseComponents
         {
             return SelectorItems.Count > 1;
         }
+
+        internal void AddWithoutDuplicationCheck(ControlState state, T value)
+        {
+            if (state == ControlState.All)
+            {
+                All = value;
+                return;
+            }
+            SelectorItems.Add(new SelectorItem<T>(state, value));
+        }
+
+        private T GetOrThrowKeyNotFound(System.Predicate<SelectorItem<T>> match)
+        {
+            var item = SelectorItems.Find(match);
+            if (item == null)
+            {
+                throw new KeyNotFoundException("The selector does not contain this value.");
+            }
+            return item.Value;
+        }
     }
 
     /// <summary>
index a4cf9aa..127fc8e 100755 (executable)
@@ -93,7 +93,8 @@ namespace Tizen.NUI.BaseComponents
 
                 map.Add(Visual.Property.Type, new PropertyValue((int)Visual.Type.Color))
                    .Add(ColorVisualProperty.MixColor, new PropertyValue((Color)newValue))
-                   .Add(Visual.Property.CornerRadius, new PropertyValue(view.backgroundExtraData.CornerRadius));
+                   .Add(Visual.Property.CornerRadius, new PropertyValue(view.backgroundExtraData.CornerRadius))
+                   .Add(Visual.Property.CornerRadiusPolicy, new PropertyValue((int)(view.backgroundExtraData.CornerRadiusPolicy)));
 
                 Tizen.NUI.Object.SetProperty((System.Runtime.InteropServices.HandleRef)view.SwigCPtr, View.Property.BACKGROUND, new PropertyValue(map));
             }
@@ -160,6 +161,7 @@ namespace Tizen.NUI.BaseComponents
 
             map.Add(ImageVisualProperty.URL, new PropertyValue(url))
                .Add(Visual.Property.CornerRadius, new PropertyValue(view.backgroundExtraData.CornerRadius))
+               .Add(Visual.Property.CornerRadiusPolicy, new PropertyValue((int)(view.backgroundExtraData.CornerRadiusPolicy)))
                .Add(ImageVisualProperty.SynchronousLoading, new PropertyValue(view.backgroundImageSynchronosLoading));
 
             if (view.backgroundExtraData.BackgroundImageBorder != null)
index 0ecd0b2..b9e6784 100644 (file)
@@ -14,7 +14,6 @@
  * limitations under the License.
  *
  */
-#if !PROFILE_WEARABLE
 
 using System.Collections.Generic;
 
@@ -22,14 +21,24 @@ namespace Tizen.NUI
 {
     internal class DefaultThemeCreator : IThemeCreator
     {
-        public Theme Create() => Create(null);
-        public Theme Create(IEnumerable<KeyValuePair<string, string>> changedResources)
+        private DefaultThemeCreator() { }
+
+        internal const string DefaultId = "Tizen.NUI.Theme.Common";
+        internal const string DefaultVersion = "1.0.0";
+
+        internal static IThemeCreator Instance { get; set; } = new DefaultThemeCreator();
+
+        public Theme Create()
         {
-            Theme theme = new Theme() { Id = "Tizen.NUI.Theme.Common" };
-            theme.SetChangedResources(changedResources);
+            Theme theme = new Theme()
+            {
+                Id = DefaultId,
+                Version = DefaultVersion,
+            };
             return theme;
         }
+
+        public HashSet<ExternalThemeKeyList> GetExternalThemeKeyListSet() => null;
     }
 }
 
-#endif
diff --git a/src/Tizen.NUI/src/public/Theme/DictionaryExternalTheme.cs b/src/Tizen.NUI/src/public/Theme/DictionaryExternalTheme.cs
new file mode 100644 (file)
index 0000000..886540f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#if DEBUG
+
+using System.Collections.Generic;
+
+namespace Tizen.NUI
+{
+    /// <summary>
+    /// This is a helper class to test external theme applying.
+    /// </summary>
+    internal class DictionaryExternalTheme : IExternalTheme
+    {
+        private readonly Dictionary<string, string> theme;
+
+        public DictionaryExternalTheme(string id, string version, Dictionary<string, string> theme)
+        {
+            Id = id;
+            Version = version;
+            this.theme = theme;
+        }
+
+        public string Id { get; }
+
+        public string Version { get; }
+
+        public string GetValue(string key)
+        {
+            theme.TryGetValue(key, out string extracted);
+
+            return extracted;
+        }
+    }
+}
+#endif
diff --git a/src/Tizen.NUI/src/public/Theme/ExternalThemeKeyList.cs b/src/Tizen.NUI/src/public/Theme/ExternalThemeKeyList.cs
new file mode 100644 (file)
index 0000000..c63a314
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Xaml;
+
+namespace Tizen.NUI
+{
+    /// <summary>
+    /// This class holds a list of string key and corresponding setter function.
+    /// <para>
+    /// Key
+    /// Represents a specific property in a style, for example,
+    /// the key "/Text/PixelSize" of styleType "Button" means "ButtonStyle.Text.PixelSize".
+    /// </para>
+    /// <para>
+    /// Action
+    /// One action takes two values,
+    /// * viewStyle : A style instance in a theme.
+    /// * value: A string value that will overwrite a property value in a given viewStyle.
+    /// The action parses a given string value into a typed object and set it to the viewStyle.
+    /// </para>
+    /// </summary>
+    internal class ExternalThemeKeyList
+    {
+        private Type componentType;
+        private Type styleType;
+        private object selectorData;
+        private List<KeyActionPair> list = new List<KeyActionPair>();
+
+        /// <summary>
+        /// Create a new key list
+        /// For example,
+        /// <code>
+        /// new ExternalThemeKeyList(typeof(Button), typeof(ButtonStyle));
+        /// </code>
+        /// This means that the keys are related with ButtonStyle and they are defined to decorate Button component.
+        /// </summary>
+        internal ExternalThemeKeyList(Type componentType, Type styleType)
+        {
+            this.componentType = componentType;
+            this.styleType = styleType;
+        }
+
+        /// <summary>
+        /// Add a key with a corresponding action.
+        /// For example,
+        /// <code>
+        /// var keyList = new ExternalThemeKeyList(typeof(Button), typeof(ButtonStyle));
+        /// keyList.Add&lt;Extents&gt;("/Margin", (ViewStyle style, Extents value) => viewStyle.Margin = value);
+        /// </code>
+        /// </summary>
+        internal ExternalThemeKeyList Add<T>(string key, Action<ViewStyle, T> setter)
+        {
+            list.Add(new KeyActionPair(componentType.Name + key, (ViewStyle viewStyle, string stringInput) =>
+            {
+                if (ParseXamlStringToObject<T>(stringInput) is T tValue)
+                {
+                    if (tValue != null)
+                    {
+                        setter(viewStyle, tValue);
+                    }
+                }
+            }));
+            return this;
+        }
+
+        /// <summary>
+        /// <para>
+        /// The series of actions for a selector.
+        /// T is a content type of a selector.
+        /// For example, assume that the component type is "Progress",
+        /// <code>
+        /// AddSelector&lt;Color&gt;("/TrackColor", setter);
+        /// </code>
+        /// This will produce additional keys and actions for 5 basic ControlStates,
+        /// "Progress/TrackColor"
+        /// "Progress/TrackColorFocused"
+        /// "Progress/TrackColorPressed"
+        /// "Progress/TrackColorDisabled"
+        /// "Progress/TrackColorOther"
+        /// </para>
+        /// <para>
+        /// Note that if you want to add actions for additional control states, please specify them as parameter.
+        /// </para>
+        /// </summary>
+        /// <code>
+        /// AddSelector&lt;Color&gt;("/TrackColor", setter, ControlState.DisabledSelected);
+        /// </code>
+        internal ExternalThemeKeyList AddSelector<T>(string key, Action<ViewStyle, Selector<T>> setter, params ControlState[] additionalStates)
+        {
+            list.Add(new KeyActionPair(componentType.Name + key, GenSelectorAction<T>(ControlState.Normal)));
+            list.Add(new KeyActionPair(componentType.Name + key + nameof(ControlState.Focused), GenSelectorAction<T>(ControlState.Focused)));
+            list.Add(new KeyActionPair(componentType.Name + key + nameof(ControlState.Pressed), GenSelectorAction<T>(ControlState.Pressed)));
+            list.Add(new KeyActionPair(componentType.Name + key + nameof(ControlState.Disabled), GenSelectorAction<T>(ControlState.Disabled)));
+            list.Add(new KeyActionPair(componentType.Name + key + nameof(ControlState.Other), GenSelectorAction<T>(ControlState.Other)));
+
+            foreach (var state in additionalStates)
+            {
+                list.Add(new KeyActionPair(componentType.Name + key + nameof(state), GenSelectorAction<T>(state)));
+            }
+
+            list.Add(new KeyActionPair(GenSelectorFinalizer(setter)));
+
+            return this;
+        }
+
+        /// <summary>
+        /// Note that, the view's background can be either color or image value.
+        /// This method add keys for a selector and each action can handle both color and string (for image url).
+        /// </summary>
+        internal ExternalThemeKeyList AddBackgroundSelector(string key, Action<ViewStyle, Selector<Color>> colorSetter, Action<ViewStyle, Selector<string>> imageSetter, params ControlState[] additionalStates)
+        {
+            list.Add(new KeyActionPair(componentType.Name + key, GenBackgroundSelectorAction(ControlState.Normal)));
+            list.Add(new KeyActionPair(componentType.Name + key + nameof(ControlState.Focused), GenBackgroundSelectorAction(ControlState.Focused)));
+            list.Add(new KeyActionPair(componentType.Name + key + nameof(ControlState.Pressed), GenBackgroundSelectorAction(ControlState.Pressed)));
+            list.Add(new KeyActionPair(componentType.Name + key + nameof(ControlState.Disabled), GenBackgroundSelectorAction(ControlState.Disabled)));
+            list.Add(new KeyActionPair(componentType.Name + key + nameof(ControlState.Other), GenBackgroundSelectorAction(ControlState.Other)));
+
+            foreach (var state in additionalStates)
+            {
+                list.Add(new KeyActionPair(componentType.Name + key + nameof(state), GenBackgroundSelectorAction(state)));
+            }
+
+            list.Add(new KeyActionPair(GenColorOrImageSelectorFinalizer(colorSetter, imageSetter)));
+
+            return this;
+        }
+
+        internal void ApplyKeyActions(IExternalTheme externalTheme, Theme theme)
+        {
+            var style = theme.GetStyle(componentType.FullName);
+
+            foreach (var item in list)
+            {
+                if (item.IsFinalizer)
+                {
+                    item.Action(style, null);
+                    continue;
+                }
+
+                string newValue = externalTheme.GetValue(item.Key);
+                if (newValue != null)
+                {
+                    if (style == null || style.GetType() != styleType)
+                    {
+                        style = Activator.CreateInstance(styleType) as ViewStyle;
+                        theme.AddStyleWithoutClone(componentType.FullName, style);
+                    }
+
+                    // Invoke action with the existing style to overwrite properties of it.
+                    item.Action(style, newValue);
+                }
+            }
+        }
+
+        private Action<ViewStyle, string> GenSelectorAction<T>(ControlState state)
+        {
+            return (ViewStyle viewStyle, string stringInput) => {
+                if (ParseXamlStringToObject<T>(stringInput) is T tValue)
+                {
+                    if (selectorData == null)
+                    {
+                        selectorData = new Selector<T>();
+                    }
+                    ((Selector<T>)selectorData).AddWithoutDuplicationCheck(state, tValue);
+                }
+            };
+        }
+
+        private Action<ViewStyle, string> GenBackgroundSelectorAction(ControlState state)
+        {
+            return (ViewStyle viewStyle, string stringInput) => {
+                var imageUrl = TryConvertToResourcePath(stringInput);
+
+                if (imageUrl != null)
+                {
+                    if (selectorData == null || (selectorData as Selector<string> == null))
+                    {
+                        selectorData = new Selector<string>();
+                    }
+                    ((Selector<string>)selectorData).AddWithoutDuplicationCheck(state, imageUrl);
+                }
+                else if (ParseXamlStringToObject<Color>(stringInput) is Color color)
+                {
+                    if (selectorData == null || (selectorData as Selector<Color> == null))
+                    {
+                        selectorData = new Selector<Color>();
+                    }
+                    ((Selector<Color>)selectorData).AddWithoutDuplicationCheck(state, color);
+                }
+            };
+        }
+
+        private Action<ViewStyle, string> GenSelectorFinalizer<T>(Action<ViewStyle, Selector<T>> setter)
+        {
+            return (ViewStyle viewStyle, string value) => {
+                if (selectorData == null || viewStyle == null)
+                {
+                    return;
+                }
+                setter(viewStyle, (Selector<T>)selectorData);
+                selectorData = null;
+            };
+        }
+
+        private Action<ViewStyle, string> GenColorOrImageSelectorFinalizer(Action<ViewStyle, Selector<Color>> colorSetter, Action<ViewStyle, Selector<string>> imageSetter)
+        {
+            return (ViewStyle viewStyle, string value) => {
+                if (viewStyle == null)
+                {
+                    return;
+                }
+                if (selectorData is Selector<Color> colorSelector)
+                {
+                    colorSetter(viewStyle, colorSelector);
+                }
+                else if (selectorData is Selector<string> imageSelector)
+                {
+                    imageSetter(viewStyle, imageSelector);
+                }
+                selectorData = null;
+            };
+        }
+
+        private static object ParseXamlStringToObject<T>(string stringInput)
+        {
+            if (typeof(T) == typeof(string))
+            {
+                return TryConvertToResourcePath(stringInput) ?? stringInput;
+            }
+            return stringInput.ConvertTo(typeof(T), () => typeof(T).GetTypeInfo(), null);
+        }
+
+        private static string TryConvertToResourcePath(string stringInput)
+        {
+            Debug.Assert(stringInput != null);
+            if (stringInput.StartsWith("{") && stringInput.EndsWith("}"))
+            {
+                // TODO Need to use Tizen.Applications.ThemeManager.Theme.GetPath instead SharedResourcePath after fixing abort problem.
+                return ExternalThemeManager.SharedResourcePath + "/" + stringInput.Substring(1, stringInput.Length - 2);
+            }
+            return null;
+        }
+
+        internal struct KeyActionPair
+        {
+            public KeyActionPair(string key, Action<ViewStyle, string> action)
+            {
+                Key = key;
+                Action = action;
+            }
+
+            public KeyActionPair(Action<ViewStyle, string> action)
+            {
+                Key = null;
+                Action = action;
+            }
+
+            public bool IsFinalizer => (Key == null);
+
+            public string Key { get; }
+
+            public Action<ViewStyle, string> Action { get; }
+        }
+    }
+}
diff --git a/src/Tizen.NUI/src/public/Theme/ExternalThemeManager.cs b/src/Tizen.NUI/src/public/Theme/ExternalThemeManager.cs
new file mode 100644 (file)
index 0000000..839660d
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using Tizen.Applications;
+
+namespace Tizen.NUI
+{
+    [SuppressMessage("Microsoft.Design", "CA1031: Do not catch general exception types", Justification = "This method is to handle external resources that may throw an exception but ignorable. This method should not interupt the main stream.")]
+    internal static class ExternalThemeManager
+    {
+        private static readonly Tizen.Applications.ThemeManager.ThemeLoader themeLoader = new Tizen.Applications.ThemeManager.ThemeLoader();
+        private static string sharedResourcePath;
+#if DEBUG
+        private static IExternalTheme theme;
+#endif
+        static ExternalThemeManager() { }
+
+        public static string SharedResourcePath
+        {
+            get
+            {
+#if DEBUG
+                if (theme != null)
+                {
+                    return string.Empty;
+                }
+#endif
+                if (sharedResourcePath != null)
+                {
+                    return sharedResourcePath;
+                }
+
+                var tizenTheme = themeLoader.CurrentTheme;
+
+                if (tizenTheme == null || string.IsNullOrEmpty(tizenTheme.Id) || string.IsNullOrEmpty(tizenTheme.Version))
+                {
+                    sharedResourcePath = string.Empty;
+                }
+                else
+                {
+                    ApplicationInfo themePkgInfo;
+                    try
+                    {
+                        themePkgInfo = ApplicationManager.GetInstalledApplication(tizenTheme.Id);
+                    }
+                    catch (ArgumentException e)
+                    {
+                        Tizen.Log.Error("NUI", $"{e.GetType().Name} occured while getting theme application info.");
+                        throw e;
+                    }
+                    catch (InvalidOperationException e)
+                    {
+                        Tizen.Log.Error("NUI", $"{e.GetType().Name} occured while getting theme application info.");
+                        throw e;
+                    }
+
+                    if (themePkgInfo == null)
+                    {
+                        sharedResourcePath = string.Empty;
+                    }
+                    else
+                    {
+                        sharedResourcePath = themePkgInfo.SharedResourcePath;
+                    }
+                }
+
+                return sharedResourcePath;
+            }
+        }
+
+        public static void Initialize()
+        {
+            themeLoader.ThemeChanged += OnTizenThemeChanged;
+        }
+
+        public static IExternalTheme GetCurrentTheme()
+        {
+#if DEBUG
+            if (theme != null)
+            {
+                return theme;
+            }
+#endif
+            Tizen.Applications.ThemeManager.Theme tizenTheme = null;
+
+            try
+            {
+                tizenTheme = themeLoader.CurrentTheme;
+            }
+            catch (Exception e)
+            {
+                Tizen.Log.Info("NUI", $"[Ignorable] {e.GetType().Name} occured while getting current theme using {themeLoader.GetType().FullName}: {e.Message}");
+            }
+
+            if (tizenTheme == null || string.IsNullOrEmpty(tizenTheme.Id) || string.IsNullOrEmpty(tizenTheme.Version))
+            {
+                return null;
+            }
+
+            Tizen.Log.Info("NUI", $"TizenTheme: Id({tizenTheme.Id}), Version({tizenTheme.Version}), Title({tizenTheme.Title})");
+
+            return new TizenExternalTheme(tizenTheme);
+        }
+
+        public static IExternalTheme GetTheme(string id)
+        {
+            Tizen.Applications.ThemeManager.Theme tizenTheme = null;
+
+            try
+            {
+                tizenTheme = themeLoader.LoadTheme(id);
+            }
+            catch (Exception e)
+            {
+                Tizen.Log.Info("NUI", $"[Ignorable] {e.GetType().Name} occured while getting load theme using {themeLoader.GetType().FullName}: {e.Message}");
+            }
+
+            return tizenTheme == null ? null : new TizenExternalTheme(tizenTheme);
+        }
+
+#if DEBUG
+        public static void SetTestTheme(IExternalTheme testTheme)
+        {
+            if (testTheme == null)
+            {
+                throw new ArgumentNullException(nameof(testTheme));
+            }
+
+            if (string.IsNullOrEmpty(testTheme.Id) || string.IsNullOrEmpty(testTheme.Version))
+            {
+                throw new ArgumentException();
+            }
+
+            theme = testTheme;
+            ThemeManager.ApplyExternalTheme(theme);
+        }
+
+        public static void SetTestTheme(string id, string version, Dictionary<string, string> testData)
+        {
+            if (id == null)
+            {
+                throw new ArgumentNullException(nameof(id));
+            }
+            if (version == null)
+            {
+                throw new ArgumentNullException(nameof(version));
+            }
+            if (testData == null)
+            {
+                throw new ArgumentNullException(nameof(testData));
+            }
+
+            theme = new DictionaryExternalTheme(id, version, testData);
+            ThemeManager.ApplyExternalTheme(theme);
+        }
+#endif
+
+        private static void OnTizenThemeChanged(object sender, Tizen.Applications.ThemeManager.ThemeEventArgs e)
+        {
+#if DEBUG
+            theme = null;
+#endif
+            Tizen.Log.Info("NUI", $"TizenTheme: Id({e.Theme.Id}), Version({e.Theme.Version}), Title({e.Theme.Title})");
+            sharedResourcePath = null;
+            ThemeManager.ApplyExternalTheme(new TizenExternalTheme(e.Theme));
+        }
+    }
+}
+
diff --git a/src/Tizen.NUI/src/public/Theme/IExternalTheme.cs b/src/Tizen.NUI/src/public/Theme/IExternalTheme.cs
new file mode 100644 (file)
index 0000000..cb75be4
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Tizen.NUI
+{
+    /// <summary>
+    /// This is a wrapper to express external theme, such as, tizen-theme-manager's theme.
+    /// </summary>
+    internal interface IExternalTheme
+    {
+        string Id { get; }
+        string Version { get; }
+        string GetValue(string key);
+    }
+}
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  *
  */
-#if PROFILE_WEARABLE
+
+using System.Collections.Generic;
 
 namespace Tizen.NUI
 {
-    internal class DefaultThemeCreator : IThemeCreator
+    internal interface IThemeCreator
     {
-        public Theme Create()
-        {
-            return new Theme() { Id = "Tizen.NUI.Theme.Wearable" };
-        }
+        Theme Create();
+        HashSet<ExternalThemeKeyList> GetExternalThemeKeyListSet();
     }
 }
-
-#endif
index 7c200da..d5e866d 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -93,6 +93,12 @@ namespace Tizen.NUI
         public string Id { get; set; }
 
         /// <summary>
+        /// The string key to identify the Theme.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public string Version { get; set; } = null;
+
+        /// <summary>
         /// For Xaml use only.
         /// The bulit-in theme id that will be used as base of this.
         /// View styles with same key are merged.
@@ -106,7 +112,7 @@ namespace Tizen.NUI
 
                 if (string.IsNullOrEmpty(baseTheme)) return;
 
-                var baseThemeInstance = ThemeManager.GetBuiltinTheme(baseTheme);
+                var baseThemeInstance = (Theme)ThemeManager.GetBuiltinTheme(baseTheme)?.Clone();
 
                 if (baseThemeInstance != null)
                 {
@@ -186,6 +192,8 @@ namespace Tizen.NUI
 
         internal int Count => map.Count;
 
+        internal int PackageCount { get; set; } = 0;
+
         /// <summary>
         /// Get an enumerator of the theme.
         /// </summary>
@@ -218,7 +226,11 @@ namespace Tizen.NUI
         /// <param name="styleName">The string key to find a ViewStyle.</param>
         /// <returns>Founded style instance.</returns>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public ViewStyle GetStyle(string styleName) => map.ContainsKey(styleName) ? map[styleName] : null;
+        public ViewStyle GetStyle(string styleName)
+        {
+            map.TryGetValue(styleName, out ViewStyle result);
+            return result;
+        }
 
         /// <summary>
         /// Gets a style of given view type.
@@ -313,7 +325,15 @@ namespace Tizen.NUI
             if (theme == null)
                 throw new ArgumentNullException(nameof(theme));
 
-            if (Id == null) Id = theme.Id;
+            if (Id == null)
+            {
+                Id = theme.Id;
+            }
+
+            if (Version == null)
+            {
+                Version = theme.Version;
+            }
 
             foreach (var item in theme)
             {
@@ -345,6 +365,33 @@ namespace Tizen.NUI
         /// </summary>
         internal void AddStyleWithoutClone(string styleName, ViewStyle value) => map[styleName] = value;
 
+        internal void ApplyExternalTheme(IExternalTheme externalTheme, HashSet<ExternalThemeKeyList> keyListSet)
+        {
+            Id = externalTheme.Id;
+            Version = externalTheme.Version;
+
+            if (keyListSet == null)
+            {
+                // Nothing to apply
+                return;
+            }
+
+            foreach (var keyList in keyListSet)
+            {
+                keyList?.ApplyKeyActions(externalTheme, this);
+            }
+        }
+
+        internal bool HasSameIdAndVersion(IExternalTheme externalTheme)
+        {
+            if (externalTheme == null)
+            {
+                return false;
+            }
+
+            return string.Equals(Id, externalTheme.Id, StringComparison.OrdinalIgnoreCase) && string.Equals(Version, externalTheme.Version, StringComparison.OrdinalIgnoreCase);
+        }
+
         internal void SetChangedResources(IEnumerable<KeyValuePair<string, string>> changedResources)
         {
             this.changedResources = changedResources;
index 04fb963..5480b67 100755 (executable)
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Diagnostics;
 using Tizen.NUI.BaseComponents;
 
 namespace Tizen.NUI
 {
-    internal interface IThemeCreator
-    {
-        Theme Create();
-        Theme Create(IEnumerable<KeyValuePair<string, string>> changedResources);
-    }
-
     /// <summary>
     /// This static module provides methods that can manage NUI <seealso cref="Theme"/>.
     /// </summary>
@@ -42,23 +37,14 @@ namespace Tizen.NUI
     [EditorBrowsable(EditorBrowsableState.Never)]
     public static class ThemeManager
     {
-        private static readonly string[] nuiThemeProjects =
-        {
-            "Tizen.NUI",
-            "Tizen.NUI.Components",
-            "Tizen.NUI.Wearable"
-        };
-
-        private static Theme currentTheme;
         private static Theme defaultTheme;
+        private static Theme currentTheme;
         private static readonly List<Theme> builtinThemes = new List<Theme>(); // Themes provided by framework.
-        private static readonly List<Theme> customThemes = new List<Theme>(); // Themes registered by user. (Legacy support)
-        private static readonly List<IThemeCreator> packages = new List<IThemeCreator>();
+        private static readonly List<IThemeCreator> packages = new List<IThemeCreator>();// This is to store default theme creators by packages.
 
         static ThemeManager()
         {
-            defaultTheme = new DefaultThemeCreator().Create();
-            builtinThemes.Add(defaultTheme);
+            AddPackageTheme(DefaultThemeCreator.Instance);
         }
 
         /// <summary>
@@ -72,9 +58,16 @@ namespace Tizen.NUI
         /// </summary>
         internal static WeakEvent<EventHandler<ThemeChangedEventArgs>> ThemeChangedInternal = new WeakEvent<EventHandler<ThemeChangedEventArgs>>();
 
+        /// NOTE that, please remove this after remove Tizen.NUI.Components.StyleManager
+        internal static Theme DefaultTheme
+        {
+            get => defaultTheme;
+            set => defaultTheme = value;
+        }
+
         internal static Theme CurrentTheme
         {
-            get => currentTheme;
+            get => currentTheme ?? defaultTheme;
             set
             {
                 currentTheme = value;
@@ -82,28 +75,7 @@ namespace Tizen.NUI
             }
         }
 
-        /// <summary>
-        /// The fallback theme that depends on the device profile.
-        /// </summary>
-        internal static Theme DefaultTheme
-        {
-            get => defaultTheme;
-            set => defaultTheme = (Theme)value?.Clone();
-        }
-
-        internal static bool ThemeApplied => DefaultTheme.Count > 0 || (currentTheme != null && currentTheme.Count > 0);
-
-        /// <summary>
-        /// Set a theme to be used as fallback.
-        /// The fallback theme is set to profile specified theme by default.
-        /// </summary>
-        /// <param name="fallbackTheme">The theme instance to be applied as a fallback.</param>
-        /// <exception cref="ArgumentNullException">The given theme is null.</exception>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public static void ApplyFallbackTheme(Theme fallbackTheme)
-        {
-            DefaultTheme = fallbackTheme ?? throw new ArgumentNullException(nameof(fallbackTheme));
-        }
+        internal static bool ThemeApplied => defaultTheme.Count > 0 || (currentTheme != null && currentTheme.Count > 0);
 
         /// <summary>
         /// Apply theme to the NUI.
@@ -126,65 +98,29 @@ namespace Tizen.NUI
         }
 
         /// <summary>
-        /// <para>
-        /// Note that this API is to support legacy Tizen.NUI.Components.StyleManager.
-        /// Please use <seealso cref="ApplyTheme(Theme)"/> instead.
-        /// </para>
-        /// <para>
-        /// Apply theme to the NUI using theme id.
-        /// The id of theme should be either a registered custom theme or a built-in theme.
-        /// You can register custom theme using <seealso cref="RegisterTheme(Theme)"/>.
-        /// This will change the appreance of the existing components with property <seealso cref="View.ThemeChangeSensitive"/> on.
-        /// This also affects all components created afterwards.
-        /// </para>
+        /// Change base theme.
+        /// Originally base theme is a platform profile specific theme.
+        /// User may change this to one of platform installed one.
         /// </summary>
-        /// <param name="themeId">The theme Id.</param>
+        /// <param name="themeId">The installed theme Id.</param>
+        /// <returns>true on success, false when it failed to find installed theme with given themeId.</returns>
         /// <exception cref="ArgumentNullException">Thrown when the given themeId is null.</exception>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static void ApplyTheme(string themeId)
+        public static bool ApplyBaseTheme(string themeId)
         {
             if (themeId == null) throw new ArgumentNullException(nameof(themeId));
 
-            int index = customThemes.FindIndex(x => x.Id.Equals(themeId, StringComparison.OrdinalIgnoreCase));
-            if (index >= 0)
-            {
-                CurrentTheme = customThemes[index];
-                return;
-            }
+            var theme = GetBuiltinTheme(themeId);
 
-            index = builtinThemes.FindIndex(x => string.Equals(x.Id, themeId, StringComparison.OrdinalIgnoreCase));
-            if (index >= 0)
-            {
-                CurrentTheme = builtinThemes[index];
-            }
-            else
+            if (theme != null)
             {
-                Tizen.Log.Info("NUI", $"No Theme found with given id : {themeId}");
+                CurrentTheme = theme;
+                return true;
             }
-        }
 
-        /// <summary>
-        /// <para> Note that this API is to support legacy Tizen.NUI.Components.StyleManager. </para>
-        /// <para> Register a custom theme that can be used as an id when calling <seealso cref="ApplyTheme(string)"/>. </para>
-        /// </summary>
-        /// <param name="theme">The theme instance.</param>
-        /// <exception cref="ArgumentNullException">Thrown when the given theme is null.</exception>
-        /// <exception cref="ArgumentException">Thrown when the given theme id is invalid.</exception>
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public static void RegisterTheme(Theme theme)
-        {
-            if (theme == null) throw new ArgumentNullException(nameof(theme));
-            if (string.IsNullOrEmpty(theme.Id)) throw new ArgumentException("Invalid theme id.");
+            Tizen.Log.Info("NUI", $"No Theme found with given id : {themeId}");
 
-            int index = customThemes.FindIndex(x => x.Id.Equals(theme.Id, StringComparison.OrdinalIgnoreCase));
-            if (index >= 0)
-            {
-                customThemes[index] = (Theme)theme.Clone();
-            }
-            else
-            {
-                customThemes.Add((Theme)theme.Clone());
-            }
+            return false;
         }
 
         /// <summary>
@@ -200,7 +136,7 @@ namespace Tizen.NUI
 
             if (!ThemeApplied) return null;
 
-            return (CurrentTheme?.GetStyle(styleName) ?? DefaultTheme.GetStyle(styleName))?.Clone();
+            return (currentTheme?.GetStyle(styleName) ?? defaultTheme.GetStyle(styleName))?.Clone();
         }
 
         /// <summary>
@@ -215,18 +151,17 @@ namespace Tizen.NUI
 
             if (!ThemeApplied) return null;
 
-            return (CurrentTheme?.GetStyle(viewType) ?? DefaultTheme.GetStyle(viewType))?.Clone();
+            return (currentTheme?.GetStyle(viewType) ?? defaultTheme.GetStyle(viewType))?.Clone();
         }
 
         /// <summary>
-        /// Get a cloned built-in theme.
+        /// Get a built-in theme.
         /// </summary>
         /// <param name="themeId">The built-in theme id.</param>
-        /// <exception cref="ArgumentNullException">Thrown when the given themeId is null.</exception>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static Theme GetBuiltinTheme(string themeId)
+        internal static Theme GetBuiltinTheme(string themeId)
         {
-            if (themeId == null) throw new ArgumentNullException(nameof(themeId));
+            Debug.Assert(themeId != null);
 
             Theme result = null;
             int index = builtinThemes.FindIndex(x => string.Equals(x.Id, themeId, StringComparison.OrdinalIgnoreCase));
@@ -236,29 +171,64 @@ namespace Tizen.NUI
             }
             else
             {
-                var theme = LoadBuiltinTheme(themeId);
-                builtinThemes.Add(theme);
-                result = theme;
+                result = LoadBuiltinTheme(themeId);
             }
-            return (Theme)result?.Clone();
+            return result;
         }
 
         /// <summary>
-        /// Update current theme resources.
+        /// !!! This is for internal use in fhub-nui. Please do not open it.
+        /// Set a theme to be used as fallback.
+        /// The fallback theme is set to profile specified theme by default.
         /// </summary>
-        /// <param name="changedResources"> An enumerable collection of the changed resources </param>
+        /// <param name="fallbackTheme">The theme instance to be applied as a fallback.</param>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static void UpdateCurrentThemeResources(IEnumerable<KeyValuePair<string, string>> changedResources)
+        internal static void ApplyFallbackTheme(Theme fallbackTheme)
         {
-            if (CurrentTheme == null) // if current theme is default theme,
+            Debug.Assert(fallbackTheme != null);
+            defaultTheme = (Theme)fallbackTheme?.Clone();
+        }
+
+        /// <summary>
+        /// Set an external theme as a base theme.
+        /// </summary>
+        /// <param name="externalTheme">The external theme instance to be applied as base.</param>
+        internal static void ApplyExternalTheme(IExternalTheme externalTheme)
+        {
+            Debug.Assert(defaultTheme != null);
+
+            if (defaultTheme.HasSameIdAndVersion(externalTheme))
             {
-                DefaultTheme.Clear();
-                foreach (IThemeCreator themeCreator in packages)
-                {
-                    DefaultTheme.MergeWithoutClone(themeCreator.Create(changedResources));
-                }
+                return;
+            }
+
+            int index = builtinThemes.FindIndex(x => x.HasSameIdAndVersion(externalTheme));
+            if (index >= 0 && builtinThemes[index].PackageCount == packages.Count)
+            {
+                defaultTheme = builtinThemes[index];
                 NotifyThemeChanged();
+                return;
             }
+
+            var newTheme = new Theme()
+            {
+                Id = externalTheme.Id,
+                Version = externalTheme.Version
+            };
+
+            AddToBuiltinThemes(newTheme);
+
+            foreach (IThemeCreator themeCreator in packages)
+            {
+                var packageTheme = themeCreator.Create();
+                Debug.Assert(packageTheme != null);
+
+                packageTheme.ApplyExternalTheme(externalTheme, themeCreator.GetExternalThemeKeyListSet());
+                newTheme.MergeWithoutClone(packageTheme);
+            }
+
+            defaultTheme = newTheme;
+            NotifyThemeChanged();
         }
 
         internal static void AddPackageTheme(IThemeCreator themeCreator)
@@ -268,27 +238,81 @@ namespace Tizen.NUI
                 return;
             }
             packages.Add(themeCreator);
-            DefaultTheme.MergeWithoutClone(themeCreator.Create());
+
+            var packageTheme = themeCreator.Create();
+            Debug.Assert(packageTheme != null);
+
+            var externalTheme = ExternalThemeManager.GetCurrentTheme();
+            if (externalTheme != null && !packageTheme.HasSameIdAndVersion(externalTheme))
+            {
+                packageTheme.ApplyExternalTheme(externalTheme, themeCreator.GetExternalThemeKeyListSet());
+            }
+
+            if (defaultTheme == null)
+            {
+                defaultTheme = new Theme()
+                {
+                    Id = packageTheme.Id,
+                    Version = packageTheme.Version
+                };
+                AddToBuiltinThemes(defaultTheme);
+            }
+
+            defaultTheme.MergeWithoutClone(packageTheme);
+            defaultTheme.PackageCount++;
+        }
+
+        private static void AddToBuiltinThemes(Theme theme)
+        {
+            int index = builtinThemes.FindIndex(x => x.Id.Equals(theme.Id, StringComparison.OrdinalIgnoreCase));
+            if (index >= 0)
+            {
+                builtinThemes[index] = theme;
+            }
+            else
+            {
+                builtinThemes.Add(theme);
+            }
         }
 
         private static Theme LoadBuiltinTheme(string id)
         {
-            var loaded = new Theme()
+            Debug.Assert(id != null);
+            // Load from tizen-theme-manager
+            var externalTheme = ExternalThemeManager.GetTheme(id);
+
+            if (externalTheme == null)
             {
-                Id = id,
+                return null;
+            }
+
+            var newTheme = new Theme()
+            {
+                Id = externalTheme.Id,
+                Version = externalTheme.Version
             };
 
-            if (string.IsNullOrEmpty(id)) return loaded;
+            AddToBuiltinThemes(newTheme);
+
+            foreach (IThemeCreator themeCreator in packages)
+            {
+                var packageTheme = themeCreator.Create();
+                Debug.Assert(packageTheme != null);
 
-            // TODO
+                packageTheme.ApplyExternalTheme(externalTheme, themeCreator.GetExternalThemeKeyListSet());
+                newTheme.MergeWithoutClone(packageTheme);
+            }
 
-            return loaded;
+            return newTheme;
         }
 
         private static void NotifyThemeChanged()
         {
-            ThemeChangedInternal.Invoke(null, new ThemeChangedEventArgs(CurrentTheme?.Id));
-            ThemeChanged?.Invoke(null, new ThemeChangedEventArgs(CurrentTheme?.Id));
+            Debug.Assert(defaultTheme != null);
+
+            var id = currentTheme?.Id ?? defaultTheme.Id;
+            ThemeChangedInternal.Invoke(null, new ThemeChangedEventArgs(id));
+            ThemeChanged?.Invoke(null, new ThemeChangedEventArgs(id));
         }
     }
 }
diff --git a/src/Tizen.NUI/src/public/Theme/TizenExternalTheme.cs b/src/Tizen.NUI/src/public/Theme/TizenExternalTheme.cs
new file mode 100644 (file)
index 0000000..a3bf0b4
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright(c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Tizen.NUI
+{
+    /// <summary>
+    /// This is a wrapper to express tizen-theme-manager's theme.
+    /// </summary>
+    internal class TizenExternalTheme : IExternalTheme
+    {
+        private const string prefix = "/theme/";
+        private readonly Tizen.Applications.ThemeManager.Theme theme;
+
+        internal TizenExternalTheme(Tizen.Applications.ThemeManager.Theme theme)
+        {
+            this.theme = theme;
+        }
+
+        public string Id
+        {
+            get => theme.Id;
+        }
+
+        public string Version
+        {
+            get => theme.Version;
+        }
+
+        [SuppressMessage("Microsoft.Design", "CA1031: Do not catch general exception types", Justification = "This method is to handle external resources that may throw an exception but ignorable. This method should not interupt the main stream.")]
+        public string GetValue(string key)
+        {
+            string themeKey = prefix + key;
+            string extracted = null;
+
+            try
+            {
+                if (theme.HasKey(themeKey))
+                {
+                    extracted = theme.GetString(themeKey);
+                }
+            }
+            catch (Exception e)
+            {
+                Tizen.Log.Error("NUI", $"{e.GetType().Name} occured while getting value from {theme.GetType().FullName}: {e.Message}");
+            }
+
+            return extracted;
+        }
+    }
+}