Fix Module Circular Dependency.
authorPiotr Czaja/Advanced Frameworks (PLT) /SRPOL/Engineer/Samsung Electronics <p.czaja@samsung.com>
Mon, 3 Apr 2023 12:31:18 +0000 (14:31 +0200)
committerPiotr Czaja/Tizen Services & IoT (PLT) /SRPOL/Engineer/Samsung Electronics <p.czaja@samsung.com>
Mon, 3 Apr 2023 13:22:01 +0000 (15:22 +0200)
14 files changed:
SettingCore/Customization/CustomizationChangedEventArgs.cs [deleted file]
SettingCore/Customization/FileStorage.cs [deleted file]
SettingCore/Customization/GadgetProvider.cs [deleted file]
SettingCore/Customization/JsonParser.cs [deleted file]
SettingCore/Customization/MenuCustomizationItem.cs [deleted file]
SettingCore/Customization/Sections.cs [deleted file]
SettingCore/CustomizationChangedEventArgs.cs [new file with mode: 0644]
SettingCore/FileStorage.cs [new file with mode: 0644]
SettingCore/GadgetProvider.cs [new file with mode: 0644]
SettingCore/JsonParser.cs [new file with mode: 0644]
SettingCore/MenuCustomizationItem.cs [new file with mode: 0644]
SettingCore/Sections.cs [new file with mode: 0644]
SettingMainGadget/Display/DisplayGadget.cs [new file with mode: 0644]
SettingMainGadget/DisplayGadget.cs [deleted file]

diff --git a/SettingCore/Customization/CustomizationChangedEventArgs.cs b/SettingCore/Customization/CustomizationChangedEventArgs.cs
deleted file mode 100644 (file)
index 9501f17..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace SettingCore.Customization
-{
-    public class CustomizationChangedEventArgs : EventArgs
-    {
-        public CustomizationChangedEventArgs(string menuPath, int order)
-        {
-            CustomizationItems = new MenuCustomizationItem[] { new MenuCustomizationItem(menuPath, order) };
-        }
-
-        public CustomizationChangedEventArgs(IEnumerable<MenuCustomizationItem> items)
-        {
-            CustomizationItems = items;
-        }
-
-        public IEnumerable<MenuCustomizationItem> CustomizationItems { get; private set; }
-    }
-}
diff --git a/SettingCore/Customization/FileStorage.cs b/SettingCore/Customization/FileStorage.cs
deleted file mode 100644 (file)
index e21e252..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.Json;
-
-namespace SettingCore.Customization
-{
-    internal class FileStorage
-    {
-        private static readonly FileStorage instance = new FileStorage();
-        public static FileStorage Instance => instance;
-
-        private System.IO.FileSystemWatcher fsw;
-
-        public event Action Changed;
-        public event Action Lost;
-
-        private readonly string InitialFileName;
-        private readonly string CurrentFileName;
-        private readonly string BackupFileName;
-        private readonly string DirectoryPath;
-
-        public static string InitialFilePath { get; private set; }
-        public static string CurrentFilePath { get; private set; }
-        public static string BackupFilePath { get; private set; }
-
-        private FileStorage()
-        {
-            InitialFileName = "initial.json";
-            CurrentFileName = "current.json";
-            BackupFileName = "backup.json";
-            DirectoryPath = Tizen.Applications.Application.Current.DirectoryInfo.Data;
-            InitialFilePath = System.IO.Path.Combine(DirectoryPath, InitialFileName);
-            CurrentFilePath = System.IO.Path.Combine(DirectoryPath, CurrentFileName);
-            BackupFilePath = System.IO.Path.Combine(DirectoryPath, BackupFileName);
-        }
-
-        private void OnFileChanged(object sender, System.IO.FileSystemEventArgs e)
-        {
-            InvokeChangedEventHandler(e.ChangeType);
-        }
-
-        private void OnFileRenamed(object sender, System.IO.RenamedEventArgs e)
-        {
-            InvokeLostEventHandler(e.ChangeType);
-        }
-
-        private void OnFileDeleted(object sender, System.IO.FileSystemEventArgs e)
-        {
-            InvokeLostEventHandler(e.ChangeType);
-        }
-
-        private void InvokeChangedEventHandler(System.IO.WatcherChangeTypes changeType)
-        {
-            Logger.Warn($"Invoking {changeType}");
-
-            Tizen.Applications.CoreApplication.Post(() =>
-            {
-                var handler = Changed;
-                handler?.Invoke();
-            });
-        }
-
-        private async void InvokeLostEventHandler(System.IO.WatcherChangeTypes changeType)
-        {
-            Logger.Warn($"Invoking {changeType}");
-
-            await System.Threading.Tasks.Task.Delay(200);
-            bool exists = System.IO.File.Exists(CurrentFilePath);
-            if (exists)
-            {
-                Logger.Verbose($"{CurrentFilePath} still exist, so may have been overwritten...");
-                return;
-            }
-
-            Tizen.Applications.CoreApplication.Post(() =>
-            {
-                var handler = Lost;
-                handler?.Invoke();
-            });
-        }
-
-        public void StartMonitoring()
-        {
-            if (fsw != null)
-            {
-                Logger.Warn("File watching already enabled.");
-                return;
-            }
-
-            try
-            {
-                fsw = new System.IO.FileSystemWatcher(DirectoryPath, CurrentFileName);
-                fsw.Changed += OnFileChanged;
-                fsw.Renamed += OnFileRenamed;
-                fsw.Deleted += OnFileDeleted;
-                fsw.EnableRaisingEvents = true;
-                Logger.Warn("File watching enabled.");
-            }
-            catch (Exception ex)
-            {
-                Logger.Warn($"{ex}");
-
-                fsw.Dispose();
-                fsw = null;
-            }
-        }
-
-        public void StopMonitoring()
-        {
-            if (fsw == null)
-            {
-                Logger.Warn("File watching already disabled.");
-                return;
-            }
-
-            try
-            {
-                fsw.Changed -= OnFileChanged;
-                fsw.Renamed -= OnFileRenamed;
-                fsw.Deleted -= OnFileDeleted;
-                fsw.EnableRaisingEvents = false;
-            }
-            catch (Exception ex)
-            {
-                Logger.Warn($"{ex}");
-            }
-            finally
-            {
-                fsw.Dispose();
-                fsw = null;
-                Logger.Warn("File watching disabled.");
-            }
-        }
-
-        public static IEnumerable<MenuCustomizationItem> ReadFromFile(string filepath)
-        {
-            Logger.Verbose($"Reading customization from file {System.IO.Path.GetFileName(filepath)}");
-
-            bool exists = System.IO.File.Exists(filepath);
-            if (!exists)
-            {
-                Logger.Verbose($"Customization file does not exists.");
-                return null;
-            }
-
-            try
-            {
-                string text = System.IO.File.ReadAllText(filepath);
-                text = JsonParser.RemoveComments(text);
-                var dict = JsonSerializer.Deserialize<Dictionary<string, int>>(text);
-
-                var items = dict.Select(pair => new MenuCustomizationItem(pair.Key.ToLowerInvariant(), pair.Value));
-
-                StringBuilder sb = new StringBuilder("Read from file:" + Environment.NewLine);
-                foreach (var item in items)
-                {
-                    sb.AppendLine($"{item}");
-                }
-                Logger.Verbose($"{sb}");
-
-                return items;
-            }
-            catch (Exception exc)
-            {
-                Logger.Warn($"Could not parse file ({exc.Message}).");
-                return null;
-            }
-        }
-
-        private static void WriteToFile(IEnumerable<MenuCustomizationItem> items, string filepath)
-        {
-            Logger.Verbose($"Writing customization to file {System.IO.Path.GetFileName(filepath)}");
-
-            items = JsonParser.SortByNesting(items);
-            var pairs = items.Select(i => new KeyValuePair<string, int>(i.MenuPath, i.Order));
-            var dict = new Dictionary<string, int>(pairs);
-
-            var options = new JsonSerializerOptions { WriteIndented = true };
-            string jsonString = JsonSerializer.Serialize(dict, options);
-            jsonString = JsonParser.GenerateComments(jsonString);
-            try
-            {
-                System.IO.File.Create(filepath).Dispose();
-                System.IO.File.WriteAllText(filepath, jsonString);
-            }
-            catch (Exception exc)
-            {
-                Logger.Warn($"Could not write customization to file: {exc}");
-            }
-        }
-
-        public static void WriteToFiles(IEnumerable<MenuCustomizationItem> items)
-        {
-            WriteToFile(items, CurrentFilePath);
-            WriteToFile(items, BackupFilePath);
-        }
-    }
-}
diff --git a/SettingCore/Customization/GadgetProvider.cs b/SettingCore/Customization/GadgetProvider.cs
deleted file mode 100644 (file)
index c0e6447..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using Tizen.NUI;
-
-namespace SettingCore.Customization
-{
-    internal class GadgetProvider
-    {
-        private static readonly string[] SettingGadgetPackagePrefixes = new string[]
-        {
-            "org.tizen.setting",
-            "org.tizen.cssetting",
-        };
-
-        public static IEnumerable<SettingGadgetInfo> Gadgets => getSettingGadgetInfos();
-
-        private static IEnumerable<SettingGadgetInfo> getSettingGadgetInfos()
-        {
-            var allGadgetPackages = NUIGadgetManager.GetGadgetInfos();
-
-            static bool StartsWithAny(string packageId, IEnumerable<string> prefixes)
-            {
-                foreach (var prefix in prefixes)
-                {
-                    if (packageId.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
-                        return true;
-                }
-                return false;
-            }
-            var settingGadgetPackages = allGadgetPackages.Where(pkg => StartsWithAny(pkg.PackageId, SettingGadgetPackagePrefixes));
-
-            Logger.Debug($"all gadget packages: {allGadgetPackages.Count()}, setting gadget packages: {settingGadgetPackages.Count()}");
-            foreach (var pkg in settingGadgetPackages)
-                Logger.Debug($"setting gadget package (pkgId: {pkg.PackageId}, resType: {pkg.ResourceType})");
-            foreach (var pkg in allGadgetPackages.Where(p => !settingGadgetPackages.Contains(p)))
-                Logger.Debug($"other gadget package (pkgId: {pkg.PackageId}, resType: {pkg.ResourceType})");
-
-            List<SettingGadgetInfo> collection = new List<SettingGadgetInfo>();
-
-            foreach (var gadgetInfo in settingGadgetPackages)
-            {
-                var settingGadgetInfos = getSettingGadgetInfos(gadgetInfo);
-                collection.AddRange(settingGadgetInfos);
-            }
-
-            // check is there is more than one gadget with the same Menu Path
-            var uniqueMenuPaths = collection.Select(i => i.Path).Distinct();
-            foreach (var menuPath in uniqueMenuPaths)
-            {
-                var found = collection.Where(i => i.Path == menuPath);
-                if (found.Count() > 1)
-                {
-                    Logger.Warn($"Customization may work INCORRECTLY due to the same menu path '{menuPath}' for {found.Count()} gadgets.");
-                    foreach (var info in found)
-                        Logger.Warn($"Menu path: {menuPath} -> {info.ClassName} @ {info.Pkg.PackageId}");
-                }
-            }
-
-            return collection;
-        }
-
-        private static IEnumerable<SettingGadgetInfo> getSettingGadgetInfos(NUIGadgetInfo gadgetInfo)
-        {
-            string assemblyPath = System.IO.Path.Combine(gadgetInfo.ResourcePath, gadgetInfo.ExecutableFile);
-            Assembly assembly = null;
-            try
-            {
-                Logger.Verbose($"Opening assembly from {assemblyPath} ({gadgetInfo.ResourcePath}, {gadgetInfo.ExecutableFile})");
-                assembly = Assembly.Load(System.IO.File.ReadAllBytes(assemblyPath));
-            }
-            catch (System.IO.FileLoadException)
-            {
-                Logger.Warn($"could not load assembly {assemblyPath}");
-                yield break;
-            }
-            catch (System.IO.FileNotFoundException)
-            {
-                Logger.Warn($"could not find assembly {assemblyPath}");
-                yield break;
-            }
-
-            var providerType = assembly.GetExportedTypes()
-                .Where(t => t.IsSubclassOf(typeof(SettingMenuProvider)))
-                .SingleOrDefault();
-            if (providerType == null)
-            {
-                Logger.Warn($"could not find setting menu provider at {assemblyPath}");
-                yield break;
-            }
-
-            var settingMenuProvider = assembly.CreateInstance(providerType.FullName) as SettingMenuProvider;
-            var settingMenus = settingMenuProvider.Provide();
-            Logger.Debug($"Provider {providerType.FullName} contains {settingMenus.Count()} menus");
-
-            foreach (var settingMenu in settingMenus)
-            {
-                Logger.Verbose($"{settingMenu}");
-                yield return new SettingGadgetInfo(gadgetInfo, settingMenu);
-            }
-        }
-    }
-}
diff --git a/SettingCore/Customization/JsonParser.cs b/SettingCore/Customization/JsonParser.cs
deleted file mode 100644 (file)
index 45762ca..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-
-namespace SettingCore.Customization
-{
-    internal static class JsonParser
-    {
-        private static readonly string customizationPattern = @"^\s*""\s*([a-z.]*)\s*""\s*:\s*[-0-9]*\s*[,]?\s*";
-        private static readonly string commentPattern = @"\s*//.*$";
-        public static string RemoveComments(string jsonString)
-        {
-            Regex commentRegex = new Regex(commentPattern);
-            Regex custRegex = new Regex(customizationPattern);
-            StringBuilder jsonStringWithoutComments = new StringBuilder();
-            foreach (var jsonLine in jsonString.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
-            {
-                Match commentMatch = commentRegex.Match(jsonLine);
-                if (!commentMatch.Success)
-                {
-                    jsonStringWithoutComments.AppendLine(jsonLine);
-                }
-                else
-                {
-                    Match custMatch = custRegex.Match(jsonLine);
-                    if (custMatch.Success)
-                    {
-                        jsonStringWithoutComments.AppendLine(custMatch.Value);
-                    }
-                }
-            }
-            return jsonStringWithoutComments.ToString();
-        }
-
-        public static IEnumerable<MenuCustomizationItem> SortByNesting(IEnumerable<MenuCustomizationItem> items)
-        {
-            List<MenuCustomizationItem> sorted = new List<MenuCustomizationItem>();
-            IEnumerable<MenuCustomizationItem> mainMenus = items.Where(item => getMenuItemDepth(item.MenuPath) == 1);
-            sorted.AddRange(mainMenus);
-            foreach (var mainMenuItem in mainMenus)
-            {
-                var children = addChildren(mainMenuItem, items);
-                sorted.AddRange(children);
-            }
-
-            return sorted;
-        }
-
-        public static string GenerateComments(string jsonString)
-        {
-            Regex regex = new Regex(customizationPattern);
-            StringBuilder jsonStringWithComments = new StringBuilder();
-            string lastMenuGroup = "without";
-            foreach (var JsonLine in jsonString.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
-            {
-                Match match = regex.Match(JsonLine);
-                if (match.Success)
-                {
-                    string menuPath = match.Groups[1].Value;
-                    string currentMenuGroup = getMenuGroup(menuPath);
-                    if (currentMenuGroup != lastMenuGroup)
-                    {
-                        if (jsonStringWithComments.Length > 2)
-                        {
-                            jsonStringWithComments.AppendLine(string.Empty);
-                        }
-                        jsonStringWithComments.AppendLine($"{generateComment(menuPath)}");
-                    }
-                    lastMenuGroup = currentMenuGroup;
-                }
-                jsonStringWithComments.AppendLine($"{JsonLine}");
-            }
-            return jsonStringWithComments.ToString();
-        }
-
-        private static List<MenuCustomizationItem> addChildren(MenuCustomizationItem item, IEnumerable<MenuCustomizationItem> items)
-        {
-            List<MenuCustomizationItem> sorted = new List<MenuCustomizationItem>();
-            IEnumerable<MenuCustomizationItem> directChildren = items.Where(currItem => checkIfIsDirectChild(item, currItem));
-            sorted.AddRange(directChildren);
-            foreach (var menuItem in directChildren)
-            {
-                var children = addChildren(menuItem, items);
-                sorted.AddRange(children);
-            }
-
-            return sorted;
-        }
-
-        private static int getMenuItemDepth(string menuItem)
-        {
-            return menuItem.Split('.').Length;
-        }
-
-        private static bool checkIfIsDirectChild(MenuCustomizationItem item, MenuCustomizationItem currItem)
-        {
-            return item.MenuPath == string.Join(".", currItem.MenuPath.Split('.').SkipLast(1));
-        }
-
-        private static object generateComment(string menuPath)
-        {
-            StringBuilder comment = new StringBuilder("\t// group menu: main");
-            var splitted = menuPath.Split('.');
-
-            if (splitted.Length > 1)
-            {
-                foreach (var menuItem in splitted.SkipLast(1))
-                {
-                    comment.Append($" > { menuItem }");
-                }
-            }
-            return comment.ToString();
-        }
-
-        private static string getMenuGroup(string menuPath)
-        {
-            return menuPath.Split('.').Reverse().Skip(1).FirstOrDefault() ?? string.Empty;
-        }
-    }
-}
diff --git a/SettingCore/Customization/MenuCustomizationItem.cs b/SettingCore/Customization/MenuCustomizationItem.cs
deleted file mode 100644 (file)
index 5df7b19..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-using System.Linq;
-
-namespace SettingCore.Customization
-{
-    public class MenuCustomizationItem
-    {
-        /// <summary>
-        /// full key (e.g. "setting.menu.display.theme")
-        /// </summary>
-        public string MenuPath { get; private set; }
-
-        /// <summary>
-        /// last part of key (e.g. "theme" for key "setting.menu.display.theme")
-        /// </summary>
-        public string Name => MenuPath.Split('.').Last();
-
-        public int Order { get; private set; }
-
-        public bool IsVisible => Order > 0;
-
-        public MenuCustomizationItem(string menuPath, int order)
-        {
-            MenuPath = menuPath.ToLowerInvariant();
-            Order = order;
-        }
-
-        public override string ToString() => $"MenuItem (MenuPath:{MenuPath}, Name:{Name}, Order:{Order}, IsVisible:{IsVisible})";
-    }
-}
diff --git a/SettingCore/Customization/Sections.cs b/SettingCore/Customization/Sections.cs
deleted file mode 100644 (file)
index 08f9f2d..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Tizen.NUI.BaseComponents;
-
-namespace SettingCore.Customization
-{
-    public class Sections
-    {
-        private Dictionary<string, View> sections = new Dictionary<string, View>();
-
-        public IEnumerable<View> Views => sections.Values;
-
-        public bool Add(string menuPath, View view)
-        {
-            try
-            {
-                menuPath = menuPath.ToLowerInvariant();
-                sections.Add(menuPath, view);
-                return true;
-            }
-            catch (ArgumentNullException)
-            {
-                Logger.Warn("Cannot add view with null menuPath to Sections.");
-            }
-            catch (ArgumentException)
-            {
-                Logger.Warn($"Cannot add view, because menuPath '{menuPath}' already exists in Sections.");
-            }
-            return false;
-        }
-
-        public bool TryGetValue(string menuPath, out View view)
-        {
-            try
-            {
-                return sections.TryGetValue(menuPath, out view);
-            }
-            catch (ArgumentNullException)
-            {
-                Logger.Warn("Cannot get view with null menuPath from Sections.");
-                view = null;
-                return false;
-            }
-        }
-
-        public void RemoveAllSectionsFromView(View parentView)
-        {
-            foreach (var view in sections.Values)
-            {
-                try
-                {
-                    parentView.Remove(view);
-                }
-                catch (InvalidOperationException)
-                {
-                    Logger.Warn($"Parent view does not contain child view.");
-                }
-            }
-            sections.Clear();
-        }
-    }
-}
diff --git a/SettingCore/CustomizationChangedEventArgs.cs b/SettingCore/CustomizationChangedEventArgs.cs
new file mode 100644 (file)
index 0000000..9501f17
--- /dev/null
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace SettingCore.Customization
+{
+    public class CustomizationChangedEventArgs : EventArgs
+    {
+        public CustomizationChangedEventArgs(string menuPath, int order)
+        {
+            CustomizationItems = new MenuCustomizationItem[] { new MenuCustomizationItem(menuPath, order) };
+        }
+
+        public CustomizationChangedEventArgs(IEnumerable<MenuCustomizationItem> items)
+        {
+            CustomizationItems = items;
+        }
+
+        public IEnumerable<MenuCustomizationItem> CustomizationItems { get; private set; }
+    }
+}
diff --git a/SettingCore/FileStorage.cs b/SettingCore/FileStorage.cs
new file mode 100644 (file)
index 0000000..e21e252
--- /dev/null
@@ -0,0 +1,200 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+
+namespace SettingCore.Customization
+{
+    internal class FileStorage
+    {
+        private static readonly FileStorage instance = new FileStorage();
+        public static FileStorage Instance => instance;
+
+        private System.IO.FileSystemWatcher fsw;
+
+        public event Action Changed;
+        public event Action Lost;
+
+        private readonly string InitialFileName;
+        private readonly string CurrentFileName;
+        private readonly string BackupFileName;
+        private readonly string DirectoryPath;
+
+        public static string InitialFilePath { get; private set; }
+        public static string CurrentFilePath { get; private set; }
+        public static string BackupFilePath { get; private set; }
+
+        private FileStorage()
+        {
+            InitialFileName = "initial.json";
+            CurrentFileName = "current.json";
+            BackupFileName = "backup.json";
+            DirectoryPath = Tizen.Applications.Application.Current.DirectoryInfo.Data;
+            InitialFilePath = System.IO.Path.Combine(DirectoryPath, InitialFileName);
+            CurrentFilePath = System.IO.Path.Combine(DirectoryPath, CurrentFileName);
+            BackupFilePath = System.IO.Path.Combine(DirectoryPath, BackupFileName);
+        }
+
+        private void OnFileChanged(object sender, System.IO.FileSystemEventArgs e)
+        {
+            InvokeChangedEventHandler(e.ChangeType);
+        }
+
+        private void OnFileRenamed(object sender, System.IO.RenamedEventArgs e)
+        {
+            InvokeLostEventHandler(e.ChangeType);
+        }
+
+        private void OnFileDeleted(object sender, System.IO.FileSystemEventArgs e)
+        {
+            InvokeLostEventHandler(e.ChangeType);
+        }
+
+        private void InvokeChangedEventHandler(System.IO.WatcherChangeTypes changeType)
+        {
+            Logger.Warn($"Invoking {changeType}");
+
+            Tizen.Applications.CoreApplication.Post(() =>
+            {
+                var handler = Changed;
+                handler?.Invoke();
+            });
+        }
+
+        private async void InvokeLostEventHandler(System.IO.WatcherChangeTypes changeType)
+        {
+            Logger.Warn($"Invoking {changeType}");
+
+            await System.Threading.Tasks.Task.Delay(200);
+            bool exists = System.IO.File.Exists(CurrentFilePath);
+            if (exists)
+            {
+                Logger.Verbose($"{CurrentFilePath} still exist, so may have been overwritten...");
+                return;
+            }
+
+            Tizen.Applications.CoreApplication.Post(() =>
+            {
+                var handler = Lost;
+                handler?.Invoke();
+            });
+        }
+
+        public void StartMonitoring()
+        {
+            if (fsw != null)
+            {
+                Logger.Warn("File watching already enabled.");
+                return;
+            }
+
+            try
+            {
+                fsw = new System.IO.FileSystemWatcher(DirectoryPath, CurrentFileName);
+                fsw.Changed += OnFileChanged;
+                fsw.Renamed += OnFileRenamed;
+                fsw.Deleted += OnFileDeleted;
+                fsw.EnableRaisingEvents = true;
+                Logger.Warn("File watching enabled.");
+            }
+            catch (Exception ex)
+            {
+                Logger.Warn($"{ex}");
+
+                fsw.Dispose();
+                fsw = null;
+            }
+        }
+
+        public void StopMonitoring()
+        {
+            if (fsw == null)
+            {
+                Logger.Warn("File watching already disabled.");
+                return;
+            }
+
+            try
+            {
+                fsw.Changed -= OnFileChanged;
+                fsw.Renamed -= OnFileRenamed;
+                fsw.Deleted -= OnFileDeleted;
+                fsw.EnableRaisingEvents = false;
+            }
+            catch (Exception ex)
+            {
+                Logger.Warn($"{ex}");
+            }
+            finally
+            {
+                fsw.Dispose();
+                fsw = null;
+                Logger.Warn("File watching disabled.");
+            }
+        }
+
+        public static IEnumerable<MenuCustomizationItem> ReadFromFile(string filepath)
+        {
+            Logger.Verbose($"Reading customization from file {System.IO.Path.GetFileName(filepath)}");
+
+            bool exists = System.IO.File.Exists(filepath);
+            if (!exists)
+            {
+                Logger.Verbose($"Customization file does not exists.");
+                return null;
+            }
+
+            try
+            {
+                string text = System.IO.File.ReadAllText(filepath);
+                text = JsonParser.RemoveComments(text);
+                var dict = JsonSerializer.Deserialize<Dictionary<string, int>>(text);
+
+                var items = dict.Select(pair => new MenuCustomizationItem(pair.Key.ToLowerInvariant(), pair.Value));
+
+                StringBuilder sb = new StringBuilder("Read from file:" + Environment.NewLine);
+                foreach (var item in items)
+                {
+                    sb.AppendLine($"{item}");
+                }
+                Logger.Verbose($"{sb}");
+
+                return items;
+            }
+            catch (Exception exc)
+            {
+                Logger.Warn($"Could not parse file ({exc.Message}).");
+                return null;
+            }
+        }
+
+        private static void WriteToFile(IEnumerable<MenuCustomizationItem> items, string filepath)
+        {
+            Logger.Verbose($"Writing customization to file {System.IO.Path.GetFileName(filepath)}");
+
+            items = JsonParser.SortByNesting(items);
+            var pairs = items.Select(i => new KeyValuePair<string, int>(i.MenuPath, i.Order));
+            var dict = new Dictionary<string, int>(pairs);
+
+            var options = new JsonSerializerOptions { WriteIndented = true };
+            string jsonString = JsonSerializer.Serialize(dict, options);
+            jsonString = JsonParser.GenerateComments(jsonString);
+            try
+            {
+                System.IO.File.Create(filepath).Dispose();
+                System.IO.File.WriteAllText(filepath, jsonString);
+            }
+            catch (Exception exc)
+            {
+                Logger.Warn($"Could not write customization to file: {exc}");
+            }
+        }
+
+        public static void WriteToFiles(IEnumerable<MenuCustomizationItem> items)
+        {
+            WriteToFile(items, CurrentFilePath);
+            WriteToFile(items, BackupFilePath);
+        }
+    }
+}
diff --git a/SettingCore/GadgetProvider.cs b/SettingCore/GadgetProvider.cs
new file mode 100644 (file)
index 0000000..c0e6447
--- /dev/null
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Tizen.NUI;
+
+namespace SettingCore.Customization
+{
+    internal class GadgetProvider
+    {
+        private static readonly string[] SettingGadgetPackagePrefixes = new string[]
+        {
+            "org.tizen.setting",
+            "org.tizen.cssetting",
+        };
+
+        public static IEnumerable<SettingGadgetInfo> Gadgets => getSettingGadgetInfos();
+
+        private static IEnumerable<SettingGadgetInfo> getSettingGadgetInfos()
+        {
+            var allGadgetPackages = NUIGadgetManager.GetGadgetInfos();
+
+            static bool StartsWithAny(string packageId, IEnumerable<string> prefixes)
+            {
+                foreach (var prefix in prefixes)
+                {
+                    if (packageId.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
+                        return true;
+                }
+                return false;
+            }
+            var settingGadgetPackages = allGadgetPackages.Where(pkg => StartsWithAny(pkg.PackageId, SettingGadgetPackagePrefixes));
+
+            Logger.Debug($"all gadget packages: {allGadgetPackages.Count()}, setting gadget packages: {settingGadgetPackages.Count()}");
+            foreach (var pkg in settingGadgetPackages)
+                Logger.Debug($"setting gadget package (pkgId: {pkg.PackageId}, resType: {pkg.ResourceType})");
+            foreach (var pkg in allGadgetPackages.Where(p => !settingGadgetPackages.Contains(p)))
+                Logger.Debug($"other gadget package (pkgId: {pkg.PackageId}, resType: {pkg.ResourceType})");
+
+            List<SettingGadgetInfo> collection = new List<SettingGadgetInfo>();
+
+            foreach (var gadgetInfo in settingGadgetPackages)
+            {
+                var settingGadgetInfos = getSettingGadgetInfos(gadgetInfo);
+                collection.AddRange(settingGadgetInfos);
+            }
+
+            // check is there is more than one gadget with the same Menu Path
+            var uniqueMenuPaths = collection.Select(i => i.Path).Distinct();
+            foreach (var menuPath in uniqueMenuPaths)
+            {
+                var found = collection.Where(i => i.Path == menuPath);
+                if (found.Count() > 1)
+                {
+                    Logger.Warn($"Customization may work INCORRECTLY due to the same menu path '{menuPath}' for {found.Count()} gadgets.");
+                    foreach (var info in found)
+                        Logger.Warn($"Menu path: {menuPath} -> {info.ClassName} @ {info.Pkg.PackageId}");
+                }
+            }
+
+            return collection;
+        }
+
+        private static IEnumerable<SettingGadgetInfo> getSettingGadgetInfos(NUIGadgetInfo gadgetInfo)
+        {
+            string assemblyPath = System.IO.Path.Combine(gadgetInfo.ResourcePath, gadgetInfo.ExecutableFile);
+            Assembly assembly = null;
+            try
+            {
+                Logger.Verbose($"Opening assembly from {assemblyPath} ({gadgetInfo.ResourcePath}, {gadgetInfo.ExecutableFile})");
+                assembly = Assembly.Load(System.IO.File.ReadAllBytes(assemblyPath));
+            }
+            catch (System.IO.FileLoadException)
+            {
+                Logger.Warn($"could not load assembly {assemblyPath}");
+                yield break;
+            }
+            catch (System.IO.FileNotFoundException)
+            {
+                Logger.Warn($"could not find assembly {assemblyPath}");
+                yield break;
+            }
+
+            var providerType = assembly.GetExportedTypes()
+                .Where(t => t.IsSubclassOf(typeof(SettingMenuProvider)))
+                .SingleOrDefault();
+            if (providerType == null)
+            {
+                Logger.Warn($"could not find setting menu provider at {assemblyPath}");
+                yield break;
+            }
+
+            var settingMenuProvider = assembly.CreateInstance(providerType.FullName) as SettingMenuProvider;
+            var settingMenus = settingMenuProvider.Provide();
+            Logger.Debug($"Provider {providerType.FullName} contains {settingMenus.Count()} menus");
+
+            foreach (var settingMenu in settingMenus)
+            {
+                Logger.Verbose($"{settingMenu}");
+                yield return new SettingGadgetInfo(gadgetInfo, settingMenu);
+            }
+        }
+    }
+}
diff --git a/SettingCore/JsonParser.cs b/SettingCore/JsonParser.cs
new file mode 100644 (file)
index 0000000..45762ca
--- /dev/null
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace SettingCore.Customization
+{
+    internal static class JsonParser
+    {
+        private static readonly string customizationPattern = @"^\s*""\s*([a-z.]*)\s*""\s*:\s*[-0-9]*\s*[,]?\s*";
+        private static readonly string commentPattern = @"\s*//.*$";
+        public static string RemoveComments(string jsonString)
+        {
+            Regex commentRegex = new Regex(commentPattern);
+            Regex custRegex = new Regex(customizationPattern);
+            StringBuilder jsonStringWithoutComments = new StringBuilder();
+            foreach (var jsonLine in jsonString.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
+            {
+                Match commentMatch = commentRegex.Match(jsonLine);
+                if (!commentMatch.Success)
+                {
+                    jsonStringWithoutComments.AppendLine(jsonLine);
+                }
+                else
+                {
+                    Match custMatch = custRegex.Match(jsonLine);
+                    if (custMatch.Success)
+                    {
+                        jsonStringWithoutComments.AppendLine(custMatch.Value);
+                    }
+                }
+            }
+            return jsonStringWithoutComments.ToString();
+        }
+
+        public static IEnumerable<MenuCustomizationItem> SortByNesting(IEnumerable<MenuCustomizationItem> items)
+        {
+            List<MenuCustomizationItem> sorted = new List<MenuCustomizationItem>();
+            IEnumerable<MenuCustomizationItem> mainMenus = items.Where(item => getMenuItemDepth(item.MenuPath) == 1);
+            sorted.AddRange(mainMenus);
+            foreach (var mainMenuItem in mainMenus)
+            {
+                var children = addChildren(mainMenuItem, items);
+                sorted.AddRange(children);
+            }
+
+            return sorted;
+        }
+
+        public static string GenerateComments(string jsonString)
+        {
+            Regex regex = new Regex(customizationPattern);
+            StringBuilder jsonStringWithComments = new StringBuilder();
+            string lastMenuGroup = "without";
+            foreach (var JsonLine in jsonString.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
+            {
+                Match match = regex.Match(JsonLine);
+                if (match.Success)
+                {
+                    string menuPath = match.Groups[1].Value;
+                    string currentMenuGroup = getMenuGroup(menuPath);
+                    if (currentMenuGroup != lastMenuGroup)
+                    {
+                        if (jsonStringWithComments.Length > 2)
+                        {
+                            jsonStringWithComments.AppendLine(string.Empty);
+                        }
+                        jsonStringWithComments.AppendLine($"{generateComment(menuPath)}");
+                    }
+                    lastMenuGroup = currentMenuGroup;
+                }
+                jsonStringWithComments.AppendLine($"{JsonLine}");
+            }
+            return jsonStringWithComments.ToString();
+        }
+
+        private static List<MenuCustomizationItem> addChildren(MenuCustomizationItem item, IEnumerable<MenuCustomizationItem> items)
+        {
+            List<MenuCustomizationItem> sorted = new List<MenuCustomizationItem>();
+            IEnumerable<MenuCustomizationItem> directChildren = items.Where(currItem => checkIfIsDirectChild(item, currItem));
+            sorted.AddRange(directChildren);
+            foreach (var menuItem in directChildren)
+            {
+                var children = addChildren(menuItem, items);
+                sorted.AddRange(children);
+            }
+
+            return sorted;
+        }
+
+        private static int getMenuItemDepth(string menuItem)
+        {
+            return menuItem.Split('.').Length;
+        }
+
+        private static bool checkIfIsDirectChild(MenuCustomizationItem item, MenuCustomizationItem currItem)
+        {
+            return item.MenuPath == string.Join(".", currItem.MenuPath.Split('.').SkipLast(1));
+        }
+
+        private static object generateComment(string menuPath)
+        {
+            StringBuilder comment = new StringBuilder("\t// group menu: main");
+            var splitted = menuPath.Split('.');
+
+            if (splitted.Length > 1)
+            {
+                foreach (var menuItem in splitted.SkipLast(1))
+                {
+                    comment.Append($" > { menuItem }");
+                }
+            }
+            return comment.ToString();
+        }
+
+        private static string getMenuGroup(string menuPath)
+        {
+            return menuPath.Split('.').Reverse().Skip(1).FirstOrDefault() ?? string.Empty;
+        }
+    }
+}
diff --git a/SettingCore/MenuCustomizationItem.cs b/SettingCore/MenuCustomizationItem.cs
new file mode 100644 (file)
index 0000000..5df7b19
--- /dev/null
@@ -0,0 +1,29 @@
+using System.Linq;
+
+namespace SettingCore.Customization
+{
+    public class MenuCustomizationItem
+    {
+        /// <summary>
+        /// full key (e.g. "setting.menu.display.theme")
+        /// </summary>
+        public string MenuPath { get; private set; }
+
+        /// <summary>
+        /// last part of key (e.g. "theme" for key "setting.menu.display.theme")
+        /// </summary>
+        public string Name => MenuPath.Split('.').Last();
+
+        public int Order { get; private set; }
+
+        public bool IsVisible => Order > 0;
+
+        public MenuCustomizationItem(string menuPath, int order)
+        {
+            MenuPath = menuPath.ToLowerInvariant();
+            Order = order;
+        }
+
+        public override string ToString() => $"MenuItem (MenuPath:{MenuPath}, Name:{Name}, Order:{Order}, IsVisible:{IsVisible})";
+    }
+}
diff --git a/SettingCore/Sections.cs b/SettingCore/Sections.cs
new file mode 100644 (file)
index 0000000..08f9f2d
--- /dev/null
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using Tizen.NUI.BaseComponents;
+
+namespace SettingCore.Customization
+{
+    public class Sections
+    {
+        private Dictionary<string, View> sections = new Dictionary<string, View>();
+
+        public IEnumerable<View> Views => sections.Values;
+
+        public bool Add(string menuPath, View view)
+        {
+            try
+            {
+                menuPath = menuPath.ToLowerInvariant();
+                sections.Add(menuPath, view);
+                return true;
+            }
+            catch (ArgumentNullException)
+            {
+                Logger.Warn("Cannot add view with null menuPath to Sections.");
+            }
+            catch (ArgumentException)
+            {
+                Logger.Warn($"Cannot add view, because menuPath '{menuPath}' already exists in Sections.");
+            }
+            return false;
+        }
+
+        public bool TryGetValue(string menuPath, out View view)
+        {
+            try
+            {
+                return sections.TryGetValue(menuPath, out view);
+            }
+            catch (ArgumentNullException)
+            {
+                Logger.Warn("Cannot get view with null menuPath from Sections.");
+                view = null;
+                return false;
+            }
+        }
+
+        public void RemoveAllSectionsFromView(View parentView)
+        {
+            foreach (var view in sections.Values)
+            {
+                try
+                {
+                    parentView.Remove(view);
+                }
+                catch (InvalidOperationException)
+                {
+                    Logger.Warn($"Parent view does not contain child view.");
+                }
+            }
+            sections.Clear();
+        }
+    }
+}
diff --git a/SettingMainGadget/Display/DisplayGadget.cs b/SettingMainGadget/Display/DisplayGadget.cs
new file mode 100644 (file)
index 0000000..9eca6fd
--- /dev/null
@@ -0,0 +1,274 @@
+using SettingCore.TextResources;
+using SettingCore;
+using SettingCore.Customization;
+using SettingCore.Views;
+using SettingMainGadget;
+using SettingMainGadget.Display;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.System;
+
+namespace Setting.Menu
+{
+    public class DisplayGadget : SettingCore.MainMenuGadget
+    {
+        public override Color ProvideIconColor() => new Color(IsLightTheme ? "#0075FF" : "#1A85FF");
+
+        public override string ProvideIconPath() => GetResourcePath("display.svg");
+
+        public override string ProvideTitle() => Resources.IDS_ST_HEADER_DISPLAY;
+
+        private View content;
+        private Sections sections = new Sections();
+
+        private SliderListItem brightnessItem;
+        private TextListItem fontItem;
+        private TextListItem screenTimeOutItem;
+        private TextListItem themeItem;
+
+        private bool isBrightnessSupported;
+
+        private static readonly string[] iconPath = {
+            "display/Brightness_0.svg",
+            "display/Brightness_50.svg",
+            "display/Brightness_100.svg",
+        };
+
+        private static readonly string[] iconDisabledPath = {
+            "display/Brightness_light.svg",
+            "display/Brightness_dark.svg",
+        };
+
+        protected override View OnCreate()
+        {
+            base.OnCreate();
+
+            content = new ScrollableBase
+            {
+                WidthSpecification = LayoutParamPolicies.MatchParent,
+                HeightSpecification = LayoutParamPolicies.MatchParent,
+                ScrollingDirection = ScrollableBase.Direction.Vertical,
+                HideScrollbar = false,
+                Layout = new LinearLayout()
+                {
+                    LinearOrientation = LinearLayout.Orientation.Vertical,
+                },
+            };
+
+            SystemSettings.ScreenBacklightTimeChanged += SystemSettings_ScreenBacklightTimeChanged;
+            SystemSettings.FontSizeChanged += SystemSettings_FontSizeChanged;
+            SystemSettings.FontTypeChanged += SystemSettings_FontTypeChanged;
+            ThemeManager.ThemeChanged += ThemeManager_ThemeChanged;
+
+            CreateView();
+
+            return content;
+        }
+
+        protected override void OnDestroy()
+        {
+            SystemSettings.ScreenBacklightTimeChanged -= SystemSettings_ScreenBacklightTimeChanged;
+            SystemSettings.FontSizeChanged -= SystemSettings_FontSizeChanged;
+            SystemSettings.FontTypeChanged -= SystemSettings_FontTypeChanged;
+            ThemeManager.ThemeChanged -= ThemeManager_ThemeChanged;
+
+            base.OnDestroy();
+        }
+
+        private void CreateView()
+        {
+            sections.RemoveAllSectionsFromView(content);
+
+            // section: brightness
+
+            if (Tizen.System.Display.NumberOfDisplays > 0)
+            {
+                int brightness = 0;
+                int maxbrightness = 1;
+
+                try
+                {
+                    Tizen.System.Display.Displays[0].Brightness = Tizen.System.Display.Displays[0].Brightness;
+                    isBrightnessSupported = true;
+                }
+                catch (Exception)
+                {
+                    Logger.Warn($"Brightness is not supported on the device.");
+                }
+
+                
+                try
+                {
+                    brightness = Tizen.System.Display.Displays[0].Brightness;
+                    maxbrightness = Tizen.System.Display.Displays[0].MaxBrightness;
+
+                    Logger.Debug($"Current-Max display brightness: {brightness}-{maxbrightness}");
+                }
+                catch (Exception ex)
+                {
+                    Logger.Error($"Error while getting the display brightness: {ex.GetType()}, {ex.Message}");
+                }
+
+                GetBrightnessSliderIcon(brightness, out string iconpath);
+
+                brightnessItem = new SliderListItem(Resources.IDS_ST_BODY_BRIGHTNESS_M_POWER_SAVING, iconpath, (brightness * 1.0f) / maxbrightness);
+                if (brightnessItem != null)
+                {
+                    if(!isBrightnessSupported)
+                    {
+                        brightnessItem.Slider.CurrentValue = brightnessItem.Slider.MaxValue;
+                    }
+
+                    brightnessItem.Margin = new Extents(0, 0, 16, 0).SpToPx();
+                    brightnessItem.Slider.ValueChanged += MSlider_ValueChanged;
+                    brightnessItem.IsEnabled = isBrightnessSupported;
+                    sections.Add(MainMenuProvider.Display_Brightness, brightnessItem);
+                }
+            }
+
+            // section: font
+
+            fontItem = TextListItem.CreatePrimaryTextItemWithSecondaryText(Resources.IDS_ST_BODY_FONT, $"{SystemSettings.FontSize}, {SystemSettings.FontType}");
+            if (fontItem != null)
+            {
+                fontItem.Clicked += (o, e) =>
+                {
+                    NavigateTo(MainMenuProvider.Display_Font);
+                };
+                sections.Add(MainMenuProvider.Display_Font, fontItem);
+            }
+
+            // section: TimeOut
+
+            screenTimeOutItem = TextListItem.CreatePrimaryTextItemWithSecondaryText(Resources.IDS_ST_BODY_SCREEN_TIMEOUT_ABB2, DisplayTimeOutManager.GetScreenTimeoutName());
+            if (screenTimeOutItem != null)
+            {
+                screenTimeOutItem.Clicked += (o, e) =>
+                {
+                    NavigateTo(MainMenuProvider.Display_Timeout);
+                };
+                sections.Add(MainMenuProvider.Display_Timeout, screenTimeOutItem);
+            }
+
+            // section: Theme
+
+            themeItem = TextListItem.CreatePrimaryTextItemWithSecondaryText(Resources.IDS_ST_BODY_THEME, DisplayThemeManager.GetThemeName());
+            if (themeItem != null)
+            {
+                themeItem.Clicked += (o, e) =>
+                {
+                    NavigateTo(MainMenuProvider.Display_Theme);
+                };
+                sections.Add(MainMenuProvider.Display_Theme, themeItem);
+            }
+
+            var customization = GetCustomization().OrderBy(c => c.Order);
+            Logger.Debug($"customization: {customization.Count()}");
+            foreach (var cust in customization)
+            {
+                string visibility = cust.IsVisible ? "visible" : "hidden";
+                Logger.Verbose($"Customization: {cust.MenuPath} - {visibility} - {cust.Order}");
+                if (cust.IsVisible && sections.TryGetValue(cust.MenuPath, out View row))
+                {
+                    content.Add(row);
+                }
+            }
+        }
+
+
+        protected override void OnCustomizationUpdate(IEnumerable<MenuCustomizationItem> items)
+        {
+            Logger.Verbose($"{nameof(DisplayGadget)} got customization with {items.Count()} items. Recreating view.");
+            CreateView();
+        }
+
+        private void GetBrightnessSliderIcon(int brightness, out string iconpath)
+        {
+            if(!isBrightnessSupported)
+            {
+                // TODO : create a theme helper that provides information about the current theme using an enum variable. 
+                iconpath = System.IO.Path.Combine(Tizen.Applications.Application.Current.DirectoryInfo.Resource, iconDisabledPath[DisplayThemeManager.GetThemeIndex()]);
+                return;
+            }
+
+            int iconlevel = iconPath.Length;
+
+            int mapped_level = 0;
+            if (iconlevel > 1)
+            {
+                int minbrightness = 1;
+                int maxbrightness = Tizen.System.Display.Displays[0].MaxBrightness;
+                if (brightness > minbrightness)
+                {
+                    int levelcount = maxbrightness - minbrightness;
+                    int level = brightness - (minbrightness + 1);
+                    mapped_level = (level * (iconlevel - 1) / levelcount) + 1;
+                }
+            }
+            Logger.Debug($"mapped_level: {mapped_level} {System.IO.Path.Combine(Tizen.Applications.Application.Current.DirectoryInfo.Resource, iconPath[mapped_level])}");
+
+            iconpath = System.IO.Path.Combine(Tizen.Applications.Application.Current.DirectoryInfo.Resource, iconPath[mapped_level]);
+        }
+
+        private void MSlider_ValueChanged(object sender, SliderValueChangedEventArgs args)
+        {
+            var slider = sender as Slider;
+
+            int minbrightness = 1;
+            int maxbrightness = Tizen.System.Display.Displays[0].MaxBrightness;
+
+            int brightness = (int)(slider.CurrentValue * (maxbrightness - minbrightness)) + minbrightness;
+            if (brightness >= maxbrightness) brightness = maxbrightness;
+
+            Logger.Debug($"maxbrightness : {maxbrightness}, brightness : {brightness}");
+
+            if (brightnessItem != null)
+            {
+                GetBrightnessSliderIcon(brightness, out string iconpath);
+                brightnessItem.IconPath = iconpath;
+            }
+
+            try
+            {
+                Tizen.System.Display.Displays[0].Brightness = brightness;
+            }
+            catch (Exception e)
+            {
+                Logger.Error(string.Format("error :({0}) {1} ", e.GetType().ToString(), e.Message));
+            }
+        }
+
+        private void SystemSettings_ScreenBacklightTimeChanged(object sender, ScreenBacklightTimeChangedEventArgs e)
+        {
+            if (screenTimeOutItem != null)
+                screenTimeOutItem.Secondary = DisplayTimeOutManager.GetScreenTimeoutName();
+        }
+
+        private void SystemSettings_FontSizeChanged(object sender, FontSizeChangedEventArgs e)
+        {
+            CreateView(); // TODO : change only secondary text instead of re-create all view
+        }
+
+        private void SystemSettings_FontTypeChanged(object sender, FontTypeChangedEventArgs e)
+        {
+            if(fontItem != null)
+                fontItem.Secondary = $"{SystemSettings.FontSize}, {SystemSettings.FontType}"; // TODO : show default BreezeSans if FontType = DefaultFontType
+        }
+
+        private void ThemeManager_ThemeChanged(object sender, ThemeChangedEventArgs e)
+        {
+            if (e.IsPlatformThemeChanged)
+            {
+                Logger.Debug($"theme changed to: {e.PlatformThemeId}");
+                themeItem.Secondary = DisplayThemeManager.GetThemeName();
+
+                // reassign CurrentValue to trigger slider icon path update
+                brightnessItem.Slider.CurrentValue = brightnessItem.Slider.CurrentValue;
+            }
+        }
+    }
+}
diff --git a/SettingMainGadget/DisplayGadget.cs b/SettingMainGadget/DisplayGadget.cs
deleted file mode 100644 (file)
index 9eca6fd..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-using SettingCore.TextResources;
-using SettingCore;
-using SettingCore.Customization;
-using SettingCore.Views;
-using SettingMainGadget;
-using SettingMainGadget.Display;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Tizen.NUI;
-using Tizen.NUI.BaseComponents;
-using Tizen.NUI.Components;
-using Tizen.System;
-
-namespace Setting.Menu
-{
-    public class DisplayGadget : SettingCore.MainMenuGadget
-    {
-        public override Color ProvideIconColor() => new Color(IsLightTheme ? "#0075FF" : "#1A85FF");
-
-        public override string ProvideIconPath() => GetResourcePath("display.svg");
-
-        public override string ProvideTitle() => Resources.IDS_ST_HEADER_DISPLAY;
-
-        private View content;
-        private Sections sections = new Sections();
-
-        private SliderListItem brightnessItem;
-        private TextListItem fontItem;
-        private TextListItem screenTimeOutItem;
-        private TextListItem themeItem;
-
-        private bool isBrightnessSupported;
-
-        private static readonly string[] iconPath = {
-            "display/Brightness_0.svg",
-            "display/Brightness_50.svg",
-            "display/Brightness_100.svg",
-        };
-
-        private static readonly string[] iconDisabledPath = {
-            "display/Brightness_light.svg",
-            "display/Brightness_dark.svg",
-        };
-
-        protected override View OnCreate()
-        {
-            base.OnCreate();
-
-            content = new ScrollableBase
-            {
-                WidthSpecification = LayoutParamPolicies.MatchParent,
-                HeightSpecification = LayoutParamPolicies.MatchParent,
-                ScrollingDirection = ScrollableBase.Direction.Vertical,
-                HideScrollbar = false,
-                Layout = new LinearLayout()
-                {
-                    LinearOrientation = LinearLayout.Orientation.Vertical,
-                },
-            };
-
-            SystemSettings.ScreenBacklightTimeChanged += SystemSettings_ScreenBacklightTimeChanged;
-            SystemSettings.FontSizeChanged += SystemSettings_FontSizeChanged;
-            SystemSettings.FontTypeChanged += SystemSettings_FontTypeChanged;
-            ThemeManager.ThemeChanged += ThemeManager_ThemeChanged;
-
-            CreateView();
-
-            return content;
-        }
-
-        protected override void OnDestroy()
-        {
-            SystemSettings.ScreenBacklightTimeChanged -= SystemSettings_ScreenBacklightTimeChanged;
-            SystemSettings.FontSizeChanged -= SystemSettings_FontSizeChanged;
-            SystemSettings.FontTypeChanged -= SystemSettings_FontTypeChanged;
-            ThemeManager.ThemeChanged -= ThemeManager_ThemeChanged;
-
-            base.OnDestroy();
-        }
-
-        private void CreateView()
-        {
-            sections.RemoveAllSectionsFromView(content);
-
-            // section: brightness
-
-            if (Tizen.System.Display.NumberOfDisplays > 0)
-            {
-                int brightness = 0;
-                int maxbrightness = 1;
-
-                try
-                {
-                    Tizen.System.Display.Displays[0].Brightness = Tizen.System.Display.Displays[0].Brightness;
-                    isBrightnessSupported = true;
-                }
-                catch (Exception)
-                {
-                    Logger.Warn($"Brightness is not supported on the device.");
-                }
-
-                
-                try
-                {
-                    brightness = Tizen.System.Display.Displays[0].Brightness;
-                    maxbrightness = Tizen.System.Display.Displays[0].MaxBrightness;
-
-                    Logger.Debug($"Current-Max display brightness: {brightness}-{maxbrightness}");
-                }
-                catch (Exception ex)
-                {
-                    Logger.Error($"Error while getting the display brightness: {ex.GetType()}, {ex.Message}");
-                }
-
-                GetBrightnessSliderIcon(brightness, out string iconpath);
-
-                brightnessItem = new SliderListItem(Resources.IDS_ST_BODY_BRIGHTNESS_M_POWER_SAVING, iconpath, (brightness * 1.0f) / maxbrightness);
-                if (brightnessItem != null)
-                {
-                    if(!isBrightnessSupported)
-                    {
-                        brightnessItem.Slider.CurrentValue = brightnessItem.Slider.MaxValue;
-                    }
-
-                    brightnessItem.Margin = new Extents(0, 0, 16, 0).SpToPx();
-                    brightnessItem.Slider.ValueChanged += MSlider_ValueChanged;
-                    brightnessItem.IsEnabled = isBrightnessSupported;
-                    sections.Add(MainMenuProvider.Display_Brightness, brightnessItem);
-                }
-            }
-
-            // section: font
-
-            fontItem = TextListItem.CreatePrimaryTextItemWithSecondaryText(Resources.IDS_ST_BODY_FONT, $"{SystemSettings.FontSize}, {SystemSettings.FontType}");
-            if (fontItem != null)
-            {
-                fontItem.Clicked += (o, e) =>
-                {
-                    NavigateTo(MainMenuProvider.Display_Font);
-                };
-                sections.Add(MainMenuProvider.Display_Font, fontItem);
-            }
-
-            // section: TimeOut
-
-            screenTimeOutItem = TextListItem.CreatePrimaryTextItemWithSecondaryText(Resources.IDS_ST_BODY_SCREEN_TIMEOUT_ABB2, DisplayTimeOutManager.GetScreenTimeoutName());
-            if (screenTimeOutItem != null)
-            {
-                screenTimeOutItem.Clicked += (o, e) =>
-                {
-                    NavigateTo(MainMenuProvider.Display_Timeout);
-                };
-                sections.Add(MainMenuProvider.Display_Timeout, screenTimeOutItem);
-            }
-
-            // section: Theme
-
-            themeItem = TextListItem.CreatePrimaryTextItemWithSecondaryText(Resources.IDS_ST_BODY_THEME, DisplayThemeManager.GetThemeName());
-            if (themeItem != null)
-            {
-                themeItem.Clicked += (o, e) =>
-                {
-                    NavigateTo(MainMenuProvider.Display_Theme);
-                };
-                sections.Add(MainMenuProvider.Display_Theme, themeItem);
-            }
-
-            var customization = GetCustomization().OrderBy(c => c.Order);
-            Logger.Debug($"customization: {customization.Count()}");
-            foreach (var cust in customization)
-            {
-                string visibility = cust.IsVisible ? "visible" : "hidden";
-                Logger.Verbose($"Customization: {cust.MenuPath} - {visibility} - {cust.Order}");
-                if (cust.IsVisible && sections.TryGetValue(cust.MenuPath, out View row))
-                {
-                    content.Add(row);
-                }
-            }
-        }
-
-
-        protected override void OnCustomizationUpdate(IEnumerable<MenuCustomizationItem> items)
-        {
-            Logger.Verbose($"{nameof(DisplayGadget)} got customization with {items.Count()} items. Recreating view.");
-            CreateView();
-        }
-
-        private void GetBrightnessSliderIcon(int brightness, out string iconpath)
-        {
-            if(!isBrightnessSupported)
-            {
-                // TODO : create a theme helper that provides information about the current theme using an enum variable. 
-                iconpath = System.IO.Path.Combine(Tizen.Applications.Application.Current.DirectoryInfo.Resource, iconDisabledPath[DisplayThemeManager.GetThemeIndex()]);
-                return;
-            }
-
-            int iconlevel = iconPath.Length;
-
-            int mapped_level = 0;
-            if (iconlevel > 1)
-            {
-                int minbrightness = 1;
-                int maxbrightness = Tizen.System.Display.Displays[0].MaxBrightness;
-                if (brightness > minbrightness)
-                {
-                    int levelcount = maxbrightness - minbrightness;
-                    int level = brightness - (minbrightness + 1);
-                    mapped_level = (level * (iconlevel - 1) / levelcount) + 1;
-                }
-            }
-            Logger.Debug($"mapped_level: {mapped_level} {System.IO.Path.Combine(Tizen.Applications.Application.Current.DirectoryInfo.Resource, iconPath[mapped_level])}");
-
-            iconpath = System.IO.Path.Combine(Tizen.Applications.Application.Current.DirectoryInfo.Resource, iconPath[mapped_level]);
-        }
-
-        private void MSlider_ValueChanged(object sender, SliderValueChangedEventArgs args)
-        {
-            var slider = sender as Slider;
-
-            int minbrightness = 1;
-            int maxbrightness = Tizen.System.Display.Displays[0].MaxBrightness;
-
-            int brightness = (int)(slider.CurrentValue * (maxbrightness - minbrightness)) + minbrightness;
-            if (brightness >= maxbrightness) brightness = maxbrightness;
-
-            Logger.Debug($"maxbrightness : {maxbrightness}, brightness : {brightness}");
-
-            if (brightnessItem != null)
-            {
-                GetBrightnessSliderIcon(brightness, out string iconpath);
-                brightnessItem.IconPath = iconpath;
-            }
-
-            try
-            {
-                Tizen.System.Display.Displays[0].Brightness = brightness;
-            }
-            catch (Exception e)
-            {
-                Logger.Error(string.Format("error :({0}) {1} ", e.GetType().ToString(), e.Message));
-            }
-        }
-
-        private void SystemSettings_ScreenBacklightTimeChanged(object sender, ScreenBacklightTimeChangedEventArgs e)
-        {
-            if (screenTimeOutItem != null)
-                screenTimeOutItem.Secondary = DisplayTimeOutManager.GetScreenTimeoutName();
-        }
-
-        private void SystemSettings_FontSizeChanged(object sender, FontSizeChangedEventArgs e)
-        {
-            CreateView(); // TODO : change only secondary text instead of re-create all view
-        }
-
-        private void SystemSettings_FontTypeChanged(object sender, FontTypeChangedEventArgs e)
-        {
-            if(fontItem != null)
-                fontItem.Secondary = $"{SystemSettings.FontSize}, {SystemSettings.FontType}"; // TODO : show default BreezeSans if FontType = DefaultFontType
-        }
-
-        private void ThemeManager_ThemeChanged(object sender, ThemeChangedEventArgs e)
-        {
-            if (e.IsPlatformThemeChanged)
-            {
-                Logger.Debug($"theme changed to: {e.PlatformThemeId}");
-                themeItem.Secondary = DisplayThemeManager.GetThemeName();
-
-                // reassign CurrentValue to trigger slider icon path update
-                brightnessItem.Slider.CurrentValue = brightnessItem.Slider.CurrentValue;
-            }
-        }
-    }
-}