diff --git a/CustomRules.ruleset b/CustomRules.ruleset new file mode 100644 index 0000000..c6f6e51 --- /dev/null +++ b/CustomRules.ruleset @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Installer/Setup.nsi b/Installer/Setup.nsi index 4468774..cb52f35 100644 --- a/Installer/Setup.nsi +++ b/Installer/Setup.nsi @@ -60,6 +60,7 @@ Name "${APPNAME} (${FILE_ARCHITECTURE})" !insertmacro MUI_LANGUAGE "English" !insertmacro MUI_LANGUAGE "Russian" +!insertmacro MUI_LANGUAGE "German" Function .onInit !insertmacro MUI_LANGDLL_DISPLAY diff --git a/README.md b/README.md index d26b2a8..cf66f47 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,17 @@ # WTManager -[![Build status](https://ci.appveyor.com/api/projects/status/g4fn787xjdqvokpw?svg=true)](https://ci.appveyor.com/project/segrived/wtmanager) +[![Build status](https://ci.appveyor.com/api/projects/status/8r2tta8r797rxf87?svg=true)](https://ci.appveyor.com/project/gschafra/wtmanager) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/2c77caeef89d4d84816fa320732c4ba5)](https://www.codacy.com/manual/gschafra/WTManager?utm_source=github.com&utm_medium=referral&utm_content=gschafra/WTManager&utm_campaign=Badge_Grade) + +**This is an active fork of the great work of [@segrived](https://github.com/segrived)'s [WTManager](https://github.com/segrived/wtmanager) with some private modifiations/enhancements** Windows tray manager. Manage your windows services with tray! -**NOTE: EARLY ALPHA VERSION** +**NOTE: ACCORDING TO [@segrived](https://github.com/segrived) STILL EARLY ALPHA VERSION, BUT I'VE GOT THIS RUNNING STABLE FOR YEARS NOW :wink:** ![Screenshot](http://i.imgur.com/3HA2DBB.png) ## Installation -You can get latest build [here](https://ci.appveyor.com/project/segrived/wtmanager/build/artifacts) +You can get latest build [here](https://ci.appveyor.com/project/gschafra/wtmanager/build/artifacts) ## License Copyright (c) segrived 2015 @@ -21,6 +24,7 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Credits +- [@segrived](https://github.com/segrived) - of course :wink: - [@conradoqg](https://github.com/conradoqg) - some useful improvements - Menu icons from "[Elysium Icons Pack (by HazelDev)](https://www.iconfinder.com/iconsets/elysium-icons)" - Tray and executable icon from "[One bit Pack (by Icojam)](https://www.iconfinder.com/iconsets/onebit)" diff --git a/WTManager.Resources/Resources/Images/dialog/add.png b/WTManager.Resources/Images/dialog/add.png similarity index 100% rename from WTManager.Resources/Resources/Images/dialog/add.png rename to WTManager.Resources/Images/dialog/add.png diff --git a/WTManager.Resources/Images/dialog/apply.png b/WTManager.Resources/Images/dialog/apply.png new file mode 100644 index 0000000..c25e5f7 Binary files /dev/null and b/WTManager.Resources/Images/dialog/apply.png differ diff --git a/WTManager.Resources/Resources/Images/dialog/cancel.png b/WTManager.Resources/Images/dialog/cancel.png similarity index 100% rename from WTManager.Resources/Resources/Images/dialog/cancel.png rename to WTManager.Resources/Images/dialog/cancel.png diff --git a/WTManager.Resources/Resources/Images/dialog/down.png b/WTManager.Resources/Images/dialog/down.png similarity index 100% rename from WTManager.Resources/Resources/Images/dialog/down.png rename to WTManager.Resources/Images/dialog/down.png diff --git a/WTManager.Resources/Resources/Images/dialog/edit.png b/WTManager.Resources/Images/dialog/edit.png similarity index 100% rename from WTManager.Resources/Resources/Images/dialog/edit.png rename to WTManager.Resources/Images/dialog/edit.png diff --git a/WTManager.Resources/Resources/Images/dialog/ok.png b/WTManager.Resources/Images/dialog/ok.png similarity index 100% rename from WTManager.Resources/Resources/Images/dialog/ok.png rename to WTManager.Resources/Images/dialog/ok.png diff --git a/WTManager.Resources/Resources/Images/dialog/remove.png b/WTManager.Resources/Images/dialog/remove.png similarity index 100% rename from WTManager.Resources/Resources/Images/dialog/remove.png rename to WTManager.Resources/Images/dialog/remove.png diff --git a/WTManager.Resources/Resources/Images/dialog/up.png b/WTManager.Resources/Images/dialog/up.png similarity index 100% rename from WTManager.Resources/Resources/Images/dialog/up.png rename to WTManager.Resources/Images/dialog/up.png diff --git a/WTManager.Resources/Resources/Images/menu/app-exit.png b/WTManager.Resources/Images/menu/app-exit.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/app-exit.png rename to WTManager.Resources/Images/menu/app-exit.png diff --git a/WTManager.Resources/Resources/Images/menu/service-config.png b/WTManager.Resources/Images/menu/service-config.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-config.png rename to WTManager.Resources/Images/menu/service-config.png diff --git a/WTManager.Resources/Resources/Images/menu/service-edit-config.png b/WTManager.Resources/Images/menu/service-edit-config.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-edit-config.png rename to WTManager.Resources/Images/menu/service-edit-config.png diff --git a/WTManager.Resources/Resources/Images/menu/service-group.png b/WTManager.Resources/Images/menu/service-group.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-group.png rename to WTManager.Resources/Images/menu/service-group.png diff --git a/WTManager.Resources/Resources/Images/menu/service-open-browser.png b/WTManager.Resources/Images/menu/service-open-browser.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-open-browser.png rename to WTManager.Resources/Images/menu/service-open-browser.png diff --git a/WTManager.Resources/Resources/Images/menu/service-open-data-directory.png b/WTManager.Resources/Images/menu/service-open-data-directory.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-open-data-directory.png rename to WTManager.Resources/Images/menu/service-open-data-directory.png diff --git a/WTManager.Resources/Resources/Images/menu/service-restart.png b/WTManager.Resources/Images/menu/service-restart.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-restart.png rename to WTManager.Resources/Images/menu/service-restart.png diff --git a/WTManager.Resources/Resources/Images/menu/service-show-log.png b/WTManager.Resources/Images/menu/service-show-log.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-show-log.png rename to WTManager.Resources/Images/menu/service-show-log.png diff --git a/WTManager.Resources/Resources/Images/menu/service-start.png b/WTManager.Resources/Images/menu/service-start.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-start.png rename to WTManager.Resources/Images/menu/service-start.png diff --git a/WTManager.Resources/Images/menu/service-status-na.png b/WTManager.Resources/Images/menu/service-status-na.png new file mode 100644 index 0000000..0898953 Binary files /dev/null and b/WTManager.Resources/Images/menu/service-status-na.png differ diff --git a/WTManager.Resources/Resources/Images/menu/service-status-pending.png b/WTManager.Resources/Images/menu/service-status-pending.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-status-pending.png rename to WTManager.Resources/Images/menu/service-status-pending.png diff --git a/WTManager.Resources/Resources/Images/menu/service-status-started.png b/WTManager.Resources/Images/menu/service-status-started.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-status-started.png rename to WTManager.Resources/Images/menu/service-status-started.png diff --git a/WTManager.Resources/Resources/Images/menu/service-status-stopped.png b/WTManager.Resources/Images/menu/service-status-stopped.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-status-stopped.png rename to WTManager.Resources/Images/menu/service-status-stopped.png diff --git a/WTManager.Resources/Resources/Images/menu/service-stop.png b/WTManager.Resources/Images/menu/service-stop.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/service-stop.png rename to WTManager.Resources/Images/menu/service-stop.png diff --git a/WTManager.Resources/Images/menu/services-scheduler.png b/WTManager.Resources/Images/menu/services-scheduler.png new file mode 100644 index 0000000..106e0af Binary files /dev/null and b/WTManager.Resources/Images/menu/services-scheduler.png differ diff --git a/WTManager.Resources/Resources/Images/menu/settings-manager.png b/WTManager.Resources/Images/menu/settings-manager.png similarity index 100% rename from WTManager.Resources/Resources/Images/menu/settings-manager.png rename to WTManager.Resources/Images/menu/settings-manager.png diff --git a/WTManager.Resources/Images/menu/system-services-manager.png b/WTManager.Resources/Images/menu/system-services-manager.png new file mode 100644 index 0000000..a855064 Binary files /dev/null and b/WTManager.Resources/Images/menu/system-services-manager.png differ diff --git a/WTManager.Resources/Resources/Images/tray.ico b/WTManager.Resources/Images/tray.ico similarity index 100% rename from WTManager.Resources/Resources/Images/tray.ico rename to WTManager.Resources/Images/tray.ico diff --git a/WTManager.Resources/Locales/english.ini b/WTManager.Resources/Locales/english.ini new file mode 100644 index 0000000..1777a52 --- /dev/null +++ b/WTManager.Resources/Locales/english.ini @@ -0,0 +1,55 @@ +[Meta] +Code=en +Language=English +Author=Babaev Evgeniy + +[Localization] +TrayMenu.ServiceEdit=Edit {serviceName} +TrayMenu.ServiceOpenDataDirectory=Open data directory… +TrayMenu.ServiceOpenInBrower=Open in browser… +TrayMenu.ServiceEditConfiguration=Edit configuration +TrayMenu.ServiceStart=Start service +TrayMenu.ServiceStop=Stop service +TrayMenu.ServiceRestart=Restart service +TrayMenu.ServiceGroup.Ungrouped=Ungrouped +TrayMenu.ServiceGroupStart=Start service group +TrayMenu.ServiceGroupStop=Stop service group +TrayMenu.ServiceGroupRestart=Restart service group +TrayMenu.ServiceGroupLogFiles=Log files +TrayMenu.ServiceGroupConfigFiles=Config files +TrayMenu.ServiceScheduler=Service scheduler +TrayMenu.SystemServiceManager=System service manager +TrayMenu.ProgramConfiguration=Program configuration +TrayMenu.AppExit=Exit +VisualItem.Configuration.ConfigEditorPath=Config editor path +VisualItem.Configuration.UseInternalLogViewer=Use internal log viewer +VisualItem.Configuration.LogViewerPath=Log viewer path +VisualItem.Configuration.Language=Language +VisualItem.Configuration.RunOnStart=Run WTManager on start +VisualItem.Configuration.MenuFont=Tray menu font +VisualItem.Configuration.MenuTitleFont=Tray menu title font +VisualItem.Configuration.ThemeName=Theme name +VisualItem.Configuration.ShowPopup=Show tray menu popups +VisualItem.Configuration.ShowMenuBeyoundTaskbar=Show menu beyound taskbar +VisualItem.Configuration.OpenTrayMenuOnLeftClick=Open tray menu on left click +VisualItem.Configuration.UseNestedServiceGroups=Use nested service groups in menu +VisualItem.Configuration.ShowServiceGroupOperations=Show service group operations in nested menu (experimental) +VisualItem.Configuration.Services=Services +VisualItem.Configuration.Tasks=Scheduled tasks +VisualItem.ServiceTask.TaskName=Task name +VisualItem.ServiceTask.ServiceName=Service name +VisualItem.ServiceTask.OperationType=Operation type +VisualItem.ServiceTask.ExecuteTime=Trigger execute time +VisualItem.Service.ServiceName=Service name +VisualItem.Service.DisplayName=Display name +VisualItem.Service.Group=Service group (optional) +VisualItem.Service.ConfigFiles=Config files +VisualItem.Service.LogFiles=Log files +VisualItem.Service.DataDirectory=Data directory +VisualItem.Service.BrowserUrl=Browser URL +DialogButtons.Ok=Ok +DialogButtons.Apply=Apply +DialogButtons.Cancel=Cancel +Enums.ServiceGroupOperationType.Start=Start +Enums.ServiceGroupOperationType.Stop=Stop +Enums.ServiceGroupOperationType.Restart=Restart \ No newline at end of file diff --git a/WTManager.Resources/Locales/german.ini b/WTManager.Resources/Locales/german.ini new file mode 100644 index 0000000..c0aa218 --- /dev/null +++ b/WTManager.Resources/Locales/german.ini @@ -0,0 +1,55 @@ +[Meta] +Code=de +Language=German +Author=Gnter Schafranek + +[Localization] +TrayMenu.ServiceEdit={serviceName} bearbeiten +TrayMenu.ServiceOpenDataDirectory=Datenverzeichnis ffnen +TrayMenu.ServiceOpenInBrower=Im Browser ffnen +TrayMenu.ServiceEditConfiguration=Konfiguration bearbeiten +TrayMenu.ServiceStart=Dienst starten +TrayMenu.ServiceStop=Dienst beenden +TrayMenu.ServiceRestart=Dienst neu starten +TrayMenu.ServiceGroup.Ungrouped=Nicht gruppiert +TrayMenu.ServiceGroupStart=Dienste in Gruppe starten +TrayMenu.ServiceGroupStop=Dienste in Gruppe beeenden +TrayMenu.ServiceGroupRestart=Dienste in Gruppe neu starten +TrayMenu.ServiceGroupLogFiles=Log-Dateien +TrayMenu.ServiceGroupConfigFiles=Konfigurations-Dateien +TrayMenu.ServiceScheduler=Service scheduler +TrayMenu.SystemServiceManager=Verwaltung lokaler Dienste +TrayMenu.ProgramConfiguration=Programm-Konfiguration +TrayMenu.AppExit=Beenden +VisualItem.Configuration.ConfigEditorPath=Pfad zum Konfigurations-Editor +VisualItem.Configuration.UseInternalLogViewer=Internen Log-Viewer verwenden +VisualItem.Configuration.LogViewerPath=Pfad zum Log-Viewer +VisualItem.Configuration.Language=Sprache +VisualItem.Configuration.RunOnStart=WTManager automatisch starten +VisualItem.Configuration.MenuFont=Schriftart des Tray-Mens +VisualItem.Configuration.MenuTitleFont=Schriftart des Tray-Men-Titels +VisualItem.Configuration.ThemeName=Theme-Name +VisualItem.Configuration.ShowPopup=Tray-Men-Popups anzeigen +VisualItem.Configuration.ShowMenuBeyoundTaskbar=Men ber die Taskleiste anzeigen +VisualItem.Configuration.OpenTrayMenuOnLeftClick=ffnen Sie das Tray-Men mit einem Linksklick +VisualItem.Configuration.UseNestedServiceGroups=Verschachtelte Dienstgruppen im Men verwenden +VisualItem.Configuration.ShowServiceGroupOperations=Anzeigen von Servicegruppenoperationen im verschachtelten Men (experimentell) +VisualItem.Configuration.Services=Dienste +VisualItem.Configuration.Tasks=Geplante Aufgaben +VisualItem.ServiceTask.TaskName=Aufgabenname +VisualItem.ServiceTask.ServiceName=Name des Dienstes +VisualItem.ServiceTask.OperationType=Betriebsart +VisualItem.ServiceTask.ExecuteTime=Ausfhrungszeit +VisualItem.Service.ServiceName=Name des Dienstes +VisualItem.Service.DisplayName=Anzeigename +VisualItem.Service.Group=Dienst-Gruppe (optional) +VisualItem.Service.ConfigFiles=Konfigurationsdateien +VisualItem.Service.LogFiles=Log-Dateien +VisualItem.Service.DataDirectory=Datenverzeichnis +VisualItem.Service.BrowserUrl=Browser URL +DialogButtons.Ok=Ok +DialogButtons.Apply=Anwenden +DialogButtons.Cancel=Abbrechen +Enums.ServiceGroupOperationType.Start=Starten +Enums.ServiceGroupOperationType.Stop=Beenden +Enums.ServiceGroupOperationType.Restart=Neu starte \ No newline at end of file diff --git a/WTManager.Resources/Locales/russian.ini b/WTManager.Resources/Locales/russian.ini new file mode 100644 index 0000000..35b17a6 --- /dev/null +++ b/WTManager.Resources/Locales/russian.ini @@ -0,0 +1,55 @@ +[Meta] +Code=ru_RU +Language=Russian +Author=Babaev Evgeniy + +[Localization] +TrayMenu.ServiceEdit=Edit {serviceName} +TrayMenu.ServiceOpenDataDirectory=Открыть папку с данными… +TrayMenu.ServiceOpenInBrower=Открыть в браузере… +TrayMenu.ServiceEditConfiguration=Редактировать конфигурацию +TrayMenu.ServiceStart=Запустить сервис +TrayMenu.ServiceStop=Остановить сервис +TrayMenu.ServiceRestart=Перезапустить сервис +TrayMenu.ServiceGroup.Ungrouped=Без группы +TrayMenu.ServiceGroupStart=Запустить группу сервисов +TrayMenu.ServiceGroupStop=Остановить группу сервисов +TrayMenu.ServiceGroupRestart=Перезапустить группу сервисов +TrayMenu.ServiceGroupLogFiles=Лог файлы +TrayMenu.ServiceGroupConfigFiles=Конфигурационные файлы +TrayMenu.ServiceScheduler=Планировщик сервисов +TrayMenu.SystemServiceManager=Системный менеджер сервисов +TrayMenu.ProgramConfiguration=Настройки программы +TrayMenu.AppExit=Выход +VisualItem.Configuration.ConfigEditorPath=Пусть к редактору конфигов +VisualItem.Configuration.UseInternalLogViewer=Использовать встроенный просмотрщик логов +VisualItem.Configuration.LogViewerPath=Пусть к просмотрщику логов +VisualItem.Configuration.Language=Язык +VisualItem.Configuration.RunOnStart=Запускать WTManager при запуске системы +VisualItem.Configuration.MenuFont=Шрифт меню трея +VisualItem.Configuration.MenuTitleFont=Шрифт заголовков меню трея +VisualItem.Configuration.ThemeName=Тема +VisualItem.Configuration.ShowPopup=Покащывать сообщения около трея +VisualItem.Configuration.ShowMenuBeyoundTaskbar=Показывать меню над панелью задач +VisualItem.Configuration.OpenTrayMenuOnLeftClick=Открывать меню по левому клику +VisualItem.Configuration.UseNestedServiceGroups=Использовать вложенные меню для групп +VisualItem.Configuration.ShowServiceGroupOperations=Показывать групповые операции во вложенных меню +VisualItem.Configuration.Services=Сервисы +VisualItem.Configuration.Tasks=Запланированные задачи +VisualItem.ServiceTask.TaskName=Название задачи +VisualItem.ServiceTask.ServiceName=Имя сервиса +VisualItem.ServiceTask.OperationType=Тип операции +VisualItem.ServiceTask.ExecuteTime=Время исполнения +VisualItem.Service.ServiceName=Сервис +VisualItem.Service.DisplayName=Оторбажаемое имя +VisualItem.Service.Group=Груупа сервиса (опционально) +VisualItem.Service.ConfigFiles=Конфиги +VisualItem.Service.LogFiles=Логи +VisualItem.Service.DataDirectory=Директория с данными +VisualItem.Service.BrowserUrl=URL браузера +DialogButtons.Ok=Ok +DialogButtons.Apply=Применить +DialogButtons.Cancel=Отменить +Enums.ServiceGroupOperationType.Start=Запуск +Enums.ServiceGroupOperationType.Stop=Остановка +Enums.ServiceGroupOperationType.Restart=Перезапуск \ No newline at end of file diff --git a/WTManager.Resources/LocalizationManager.cs b/WTManager.Resources/LocalizationManager.cs new file mode 100644 index 0000000..4a06fe2 --- /dev/null +++ b/WTManager.Resources/LocalizationManager.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using IniParser.Model; +using IniParser.Parser; + +namespace WtManager.Resources +{ + public static class LocalizationManager + { + private static LocalizationItem _item; + + public static readonly List LocalesList = new List { "english", "russian", "german" }; + + static LocalizationManager() + { + UpdateLocale("english"); + } + + public static void UpdateLocale(string locale) + { + var localization = ResourcesProcessor.GetLocalizationFile(locale); + _item = new LocalizationItem(localization); + } + + public static string Get(string key, params string[] parameters) + { + try + { + return _item.GetValue(key) ?? key; + } + catch + { + return key; + } + } + } + + public class LocalizationItem + { + private IniData _localizationData; + + public LocalizationItem(string inputStream) + { + var parser = new IniDataParser(); + this._localizationData = parser.Parse(inputStream); + } + + public string GetValue(string key) + { + return this._localizationData["Localization"][key]; + } + } +} \ No newline at end of file diff --git a/WTManager.Resources/ResourcesHelper.cs b/WTManager.Resources/ResourcesHelper.cs new file mode 100644 index 0000000..8e9f3ea --- /dev/null +++ b/WTManager.Resources/ResourcesHelper.cs @@ -0,0 +1,7 @@ +namespace WtManager.Resources +{ + class ResourcesHelper + { + + } +} diff --git a/WTManager.Resources/ResourcesProcessor.cs b/WTManager.Resources/ResourcesProcessor.cs index b611ded..746007b 100644 --- a/WTManager.Resources/ResourcesProcessor.cs +++ b/WTManager.Resources/ResourcesProcessor.cs @@ -4,10 +4,12 @@ using System.IO; using System.Reflection; -namespace WTManager.Resources +namespace WtManager.Resources { public static class ResourcesProcessor { + private const string THEMES_DIRECTORY = "themes"; + private static readonly Dictionary ResourcesCache; public static event Action ThemeChanged; @@ -41,11 +43,8 @@ private static Stream GetResourceStream(string baseCategory, string resourceName if (ThemeName != null) resourceStream = GetThemeFileStream(baseCategory, resourceName); - if (resourceStream != null) - return resourceStream; - - // fallback to default embedded resource - return GetEmbeddedFileStream(baseCategory, resourceName); + // fallback to default embedded resource if theme file is not exist + return resourceStream ?? GetEmbeddedFileStream(baseCategory, resourceName); } public static string GetThemesRootDirectory() @@ -57,7 +56,7 @@ public static string GetThemesRootDirectory() if (assemblyFolder == null) return null; - return Path.Combine(assemblyFolder, "themes"); + return Path.Combine(assemblyFolder, THEMES_DIRECTORY); } private static Stream GetThemeFileStream(string baseCategory, string resourceName) @@ -86,7 +85,7 @@ private static Stream GetEmbeddedFileStream(string baseCategory, string resource var assembly = Assembly.GetExecutingAssembly(); string defaultNamespace = assembly.GetName().Name; - return assembly.GetManifestResourceStream($"{defaultNamespace}.Resources.{baseCategory}.{resourceName}"); + return assembly.GetManifestResourceStream($"{defaultNamespace}.{baseCategory}.{resourceName}"); } private static T GetResource(string resourceName, string baseCategory, Func objectProducer) @@ -126,6 +125,11 @@ public static Image GetImage(string imageName) return GetResource(imageName + ".png", "Images", stream => new Bitmap(stream)); } + public static string GetLocalizationFile(string language) + { + return GetResource(language + ".ini", "Locales", stream => new StreamReader(stream).ReadToEnd()); + } + public static IEnumerable GetThemesList() { if (! Directory.Exists(GetThemesRootDirectory())) diff --git a/WTManager.Resources/WTManager.Resources.csproj b/WTManager.Resources/WTManager.Resources.csproj index ff78091..f67edd9 100644 --- a/WTManager.Resources/WTManager.Resources.csproj +++ b/WTManager.Resources/WTManager.Resources.csproj @@ -30,61 +30,82 @@ 4 + + ..\packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll + + + - + - - - - - + + + + + - - + + - + - + - + - + - + - - - + + + - - - + + + - + - + - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WTManager.Resources/WtManager.Resources.csproj b/WTManager.Resources/WtManager.Resources.csproj new file mode 100644 index 0000000..f67edd9 --- /dev/null +++ b/WTManager.Resources/WtManager.Resources.csproj @@ -0,0 +1,111 @@ + + + + + Debug + AnyCPU + {8E6C262C-AB2C-4B32-B761-1CAFB8DC4E93} + Library + Properties + WTManager.Resources + WTManager.Resources + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WTManager.Resources/packages.config b/WTManager.Resources/packages.config new file mode 100644 index 0000000..80cf4be --- /dev/null +++ b/WTManager.Resources/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/WTManager.sln b/WTManager.sln index bf4d125..d3f71cf 100644 --- a/WTManager.sln +++ b/WTManager.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.16 +VisualStudioVersion = 15.0.26730.12 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WTManager", "WTManager\WTManager.csproj", "{9FAD443F-F504-47FA-802C-6470413097D0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WtManager", "WTManager\WtManager.csproj", "{9FAD443F-F504-47FA-802C-6470413097D0}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FAA71F4E-669C-468A-BFCB-74572827DE48}" ProjectSection(SolutionItems) = preProject @@ -12,7 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Installer\Setup.nsi = Installer\Setup.nsi EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WTManager.Resources", "WTManager.Resources\WTManager.Resources.csproj", "{8E6C262C-AB2C-4B32-B761-1CAFB8DC4E93}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WtManager.Resources", "WTManager.Resources\WtManager.Resources.csproj", "{8E6C262C-AB2C-4B32-B761-1CAFB8DC4E93}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -52,4 +52,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8FAB0BF1-0C24-4801-B244-A218716D15EF} + EndGlobalSection EndGlobal diff --git a/WTManager/Program.cs b/WTManager/Program.cs index 085bf46..07b7cf0 100644 --- a/WTManager/Program.cs +++ b/WTManager/Program.cs @@ -1,10 +1,10 @@ using System; using System.Threading; using System.Windows.Forms; -using WTManager.Forms; -using WTManager.Helpers; +using WtManager.Forms; +using WtManager.Helpers; -namespace WTManager +namespace WtManager { internal static class Program { @@ -20,15 +20,21 @@ private static void Main(string[] args) case "/installtask": SchedulerHelpers.AutoStartTaskState = true; break; + case "/removetask": SchedulerHelpers.AutoStartTaskState = false; break; + + default: + throw new InvalidOperationException("Invalid command line argument " + args[0]); } Environment.Exit(0); } if (!AppMutex.WaitOne(TimeSpan.Zero, true)) + { return; + } Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); diff --git a/WTManager/Properties/AssemblyInfo.cs b/WTManager/Properties/AssemblyInfo.cs index 3da6274..9af7906 100644 --- a/WTManager/Properties/AssemblyInfo.cs +++ b/WTManager/Properties/AssemblyInfo.cs @@ -1,11 +1,11 @@ using System.Reflection; using System.Runtime.InteropServices; -[assembly: AssemblyTitle("WTManager")] +[assembly: AssemblyTitle("WtManager")] [assembly: AssemblyDescription("Control your Windows services with tray")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Babaev Evgeniy")] -[assembly: AssemblyProduct("WTManager")] +[assembly: AssemblyProduct("WtManager")] [assembly: AssemblyCopyright("Copyright © 2015-2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/WTManager/Properties/Resources.Designer.cs b/WTManager/Properties/Resources.Designer.cs index cb18db5..a097e50 100644 --- a/WTManager/Properties/Resources.Designer.cs +++ b/WTManager/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace WTManager.Properties { +namespace WtManager.Properties { using System; @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WTManager.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WtManager.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/WTManager/WTManager.csproj b/WTManager/WTManager.csproj index 447407e..89ac596 100644 --- a/WTManager/WTManager.csproj +++ b/WTManager/WTManager.csproj @@ -1,5 +1,10 @@  + + + + + Debug @@ -7,8 +12,8 @@ {9FAD443F-F504-47FA-802C-6470413097D0} WinExe Properties - WTManager - WTManager + WtManager + WtManager v4.5 512 true @@ -20,6 +25,8 @@ None.None.Increment.DeltaDayStamp Properties\AssemblyInfo.cs false + + publish\ true Disk @@ -72,7 +79,7 @@ x64 default prompt - MinimumRecommendedRules.ruleset + ..\CustomRules.ruleset bin\x64\Release\ @@ -82,7 +89,9 @@ x64 default prompt - MinimumRecommendedRules.ruleset + ..\CustomRules.ruleset + false + false true @@ -105,18 +114,20 @@ MinimumRecommendedRules.ruleset - WTManager.Program + WtManager.Program - - ..\packages\TaskScheduler.2.5.28\lib\net40\Microsoft.Win32.TaskScheduler.dll + + + ..\packages\TaskScheduler.2.8.15\lib\net40\Microsoft.Win32.TaskScheduler.dll - - ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + @@ -133,21 +144,34 @@ - - + UserControl + + Form + + + WtDialog.cs + Component + + UserControl + + + WtTimeSpanSelector.cs + + + - + Component @@ -179,7 +203,7 @@ - + UserControl @@ -200,34 +224,32 @@ - - Form - - - AddEditServiceForm.cs - - - Form - - - ConfigurationForm.cs - + ResXFileCodeGenerator Resources.Designer.cs + + WtConfiguratorControl.cs + + + WtDialog.cs + WtItemEditor.cs WtSelector.cs + + WtTimeSpanSelector.cs + LogFileViewerForm.cs Designer @@ -236,14 +258,6 @@ MainForm.cs Designer - - AddEditServiceForm.cs - Designer - - - ConfigurationForm.cs - Designer - Designer @@ -263,15 +277,34 @@ - + {8e6c262c-ab2c-4b32-b761-1cafb8dc4e93} - WTManager.Resources + WtManager.Resources - + + + + + + + + + + + + + Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". + + + + + + + \ No newline at end of file diff --git a/WTManager/packages.config b/WTManager/packages.config index 78d5092..5b939c1 100644 --- a/WTManager/packages.config +++ b/WTManager/packages.config @@ -1,5 +1,10 @@  - - + + + + + + + \ No newline at end of file diff --git a/WTManager/src/Config/ConfigManager.cs b/WTManager/src/Config/ConfigManager.cs index be2ddfb..5a834b5 100644 --- a/WTManager/src/Config/ConfigManager.cs +++ b/WTManager/src/Config/ConfigManager.cs @@ -1,8 +1,9 @@ using System; using System.IO; using Newtonsoft.Json; +using WtManager.Resources; -namespace WTManager.Config +namespace WtManager.Config { public class ConfigManager { @@ -13,9 +14,22 @@ public class ConfigManager public Configuration Config { get; private set; } + /// + /// Configuration was loaded from file + /// + public event Action ConfigLoaded; + + /// + /// Cofiguration was saved to file + /// public event Action ConfigSaved; private ConfigManager() + { + this.Config = this.LoadConfig(); + } + + public Configuration LoadConfig() { var resultObj = new Configuration(); @@ -26,11 +40,14 @@ private ConfigManager() { string fileContent = File.ReadAllText(configFileName); resultObj = JsonConvert.DeserializeObject(fileContent); + + this.PostProcessConfig(resultObj); + this.ConfigLoaded?.Invoke(resultObj); } } catch { /* ... */ } - this.Config = resultObj; + return resultObj; } public void SaveConfig() @@ -38,10 +55,29 @@ public void SaveConfig() try { string configFileName = this.GetConfigFileName(); + + var configDirectory = Path.GetDirectoryName(configFileName); + + if (!Directory.Exists(configDirectory)) + { + Directory.CreateDirectory(configDirectory); + } + File.WriteAllText(configFileName, JsonConvert.SerializeObject(this.Config, Formatting.Indented)); + + this.PostProcessConfig(this.Config); this.ConfigSaved?.Invoke(this.Config); } - catch { /* ... */ } + catch { /* ... */ } + } + + /// + /// Executes after every load/save config operation + /// + private void PostProcessConfig(Configuration config) + { + ResourcesProcessor.ThemeName = config.ThemeName; + LocalizationManager.UpdateLocale(config.Language); } #region Utils @@ -52,6 +88,6 @@ private string GetConfigFileName() return Path.Combine(appDataDir, "WTManager", "config.json"); } - #endregion + #endregion Utils } -} +} \ No newline at end of file diff --git a/WTManager/src/Config/Configuration.cs b/WTManager/src/Config/Configuration.cs index f82b124..0124aae 100644 --- a/WTManager/src/Config/Configuration.cs +++ b/WTManager/src/Config/Configuration.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Drawing; +using System.ServiceProcess; using Newtonsoft.Json; -using WTManager.Controls.WtStyle.WtConfigurator; -using WTManager.Helpers; -using WTManager.VisualItemRenderers; +using WtManager.Controls.WtStyle.WtConfigurator; +using WtManager.Helpers; +using WtManager.VisualItemRenderers; // ReSharper disable ArgumentsStyleLiteral // ReSharper disable UnusedMember.Global @@ -13,14 +15,15 @@ // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable CollectionNeverUpdated.Global -namespace WTManager.Config +namespace WtManager.Config { [Serializable] - public class Configuration : IVisualProviderObject + public class Configuration : IVisualSourceObject { public const string GROUP_GENERAL = "General"; public const string GROUP_UI = "UI settings"; public const string GROUP_SERVICES = "Services"; + public const string GROUP_TASKS = "Service tasks"; public const string GROUP_SYSTEM = "System"; public Configuration() @@ -36,21 +39,31 @@ public Configuration() /// /// Path to configuration files executable file editor /// - [VisualItem(typeof(VisualFileSelectorRenderer), "Config editor path", GROUP_GENERAL)] + [VisualItem(typeof(VisualFileSelectorRenderer), GROUP_GENERAL)] public string ConfigEditorPath { get; set; } + [VisualItem(typeof(VisualCheckboxRenderer), GROUP_GENERAL)] + public bool UseInternalLogViewer { get; set; } + /// /// Path to log viewer executable file editor /// - [VisualItem(typeof(VisualFileSelectorRenderer), "Log viewer path", GROUP_GENERAL)] + [VisualItem(typeof(VisualFileSelectorRenderer), GROUP_GENERAL)] + [VisualItemDependentOn(nameof(UseInternalLogViewer), reverseDependent: true)] public string LogViewerPath { get; set; } + /// + /// Path to log viewer executable file editor + /// + [VisualItem(typeof(VisualLanguageSelectorRenderer), GROUP_GENERAL)] + public string Language { get; set; } + #endregion #region System settings [JsonIgnore] - [VisualItem(typeof(VisualCheckboxRenderer), "Run WTManager on start", GROUP_SYSTEM)] + [VisualItem(typeof(VisualCheckboxRenderer), GROUP_SYSTEM)] public bool RunOnStart { get { return SchedulerHelpers.AutoStartTaskState; } @@ -65,35 +78,35 @@ public bool RunOnStart /// Tray menu item font, except group titles /// [JsonConverter(typeof(Converters.FontConverter))] - [VisualItem(typeof(VisualFontSelectorRenderer), "Tray menu font", GROUP_UI)] + [VisualItem(typeof(VisualFontSelectorRenderer), GROUP_UI)] public Font MenuFont { get; set; } /// /// Tray menu group title items font /// [JsonConverter(typeof(Converters.FontConverter))] - [VisualItem(typeof(VisualFontSelectorRenderer), "Tray menu title font", GROUP_UI)] + [VisualItem(typeof(VisualFontSelectorRenderer), GROUP_UI)] public Font MenuTitleFont { get; set; } /// /// Current icons theme name /// - [VisualItem(typeof(VisualThemeSelectorRenderer), "Theme name", GROUP_UI)] + [VisualItem(typeof(VisualThemeSelectorRenderer), GROUP_UI)] public string ThemeName { get; set; } - [VisualItem(typeof(VisualCheckboxRenderer), "Show tray menu popups", GROUP_UI)] + [VisualItem(typeof(VisualCheckboxRenderer), GROUP_UI)] public bool ShowPopup { get; set; } - [VisualItem(typeof(VisualCheckboxRenderer), "Show menu beyound taskbar", GROUP_UI)] + [VisualItem(typeof(VisualCheckboxRenderer), GROUP_UI)] public bool ShowMenuBeyoundTaskbar { get; set; } - [VisualItem(typeof(VisualCheckboxRenderer), "Open tray menu on left click", GROUP_UI)] + [VisualItem(typeof(VisualCheckboxRenderer), GROUP_UI)] public bool OpenTrayMenuOnLeftClick { get; set; } - [VisualItem(typeof(VisualCheckboxRenderer), "Use nested service groups in menu", GROUP_UI)] + [VisualItem(typeof(VisualCheckboxRenderer), GROUP_UI)] public bool UseNestedServiceGroups { get; set; } - [VisualItem(typeof(VisualCheckboxRenderer), "Show service group operations in nested menu (experimental)", GROUP_UI)] + [VisualItem(typeof(VisualCheckboxRenderer), GROUP_UI)] [VisualItemDependentOn(nameof(UseNestedServiceGroups))] public bool ShowServiceGroupOperations { get; set; } @@ -101,15 +114,45 @@ public bool RunOnStart #region Services settings - [VisualItem(typeof(VisualServicesItemsEditorRenderer), "Services", GROUP_SERVICES)] + [VisualItem(typeof(VisualDialogItemsEditorRenderer), GROUP_SERVICES)] public IEnumerable Services { get; set; } #endregion + + [VisualItem(typeof(VisualDialogItemsEditorRenderer), GROUP_TASKS)] + public IEnumerable Tasks { get; set; } + + public string LocalizationPrefix => "Configuration"; } + [Serializable] + public class ServiceTask : IVisualSourceObject + { + public const string GROUP_GENERAL = "General configuration"; + public const string GROUP_REPEAT = "Repeat process cofiguration"; + + [VisualItem(typeof(VisualTextRenderer), GROUP_GENERAL)] + public string TaskName { get; set; } + + [VisualItem(typeof(VisualServiceSelectorRenderer), GROUP_GENERAL)] + public string ServiceName { get; set; } + + [VisualItem(typeof(VisualEnumSelectorType), GROUP_GENERAL)] + public ServiceGroupOperationType OperationType { get; set; } + + [VisualItem(typeof(VisualDateTimeRenderer), GROUP_GENERAL)] + public DateTime ExecuteTime { get; set; } + + public override string ToString() + { + return $"{this.TaskName} (Service: {this.ServiceName}, operation: {this.OperationType}, trigger on {this.ExecuteTime})"; + } + + public string LocalizationPrefix => "ServiceTask"; + } [Serializable] - public class Service : IVisualProviderObject + public class Service : IVisualSourceObject { public const string GROUP_GENERAL = "Basic service configuration"; public const string GROUP_LOGCONFIG = "Logs and config"; @@ -124,50 +167,67 @@ public Service() /// /// Service name /// - [VisualItem(typeof(VisualServiceSelectorRenderer), "Service name", GROUP_GENERAL)] + [VisualItem(typeof(VisualServiceSelectorRenderer), GROUP_GENERAL)] public string ServiceName { get; set; } /// /// Service display name (will be displayed in menu) /// - [VisualItem(typeof(VisualTextRenderer), "Service display name", GROUP_GENERAL)] + [VisualItem(typeof(VisualTextRenderer), GROUP_GENERAL)] public string DisplayName { get; set; } /// /// Service group (for menu generation) /// - [VisualItem(typeof(VisualServiceGroupSelectorRenderer), "Service group (optional)", GROUP_GENERAL)] + [VisualItem(typeof(VisualServiceGroupSelectorRenderer), GROUP_GENERAL)] public string Group { get; set; } /// /// Service configuration files /// - [VisualItem(typeof(VisualFilesItemsEditorRenderer), "Config files", GROUP_LOGCONFIG)] + [VisualItem(typeof(VisualFilesItemsEditorRenderer), GROUP_LOGCONFIG)] [VisualItemCustomization(customHeight: 80)] public IEnumerable ConfigFiles { get; set; } /// /// Service log files /// - [VisualItem(typeof(VisualFilesItemsEditorRenderer), "Log files", GROUP_LOGCONFIG)] + [VisualItem(typeof(VisualFilesItemsEditorRenderer), GROUP_LOGCONFIG)] [VisualItemCustomization(customHeight: 80)] public IEnumerable LogFiles { get; set; } /// /// Service data directory (for example WWW for web-servers) /// - [VisualItem(typeof(VisualDirectorySelectorRenderer), "Data directory", GROUP_ADDITIONAL)] + [VisualItem(typeof(VisualDirectorySelectorRenderer), GROUP_ADDITIONAL)] public string DataDirectory { get; set; } /// /// Browser URL /// - [VisualItem(typeof(VisualFileSelectorRenderer), "Browser URL", GROUP_ADDITIONAL)] + [VisualItem(typeof(VisualFileSelectorRenderer), GROUP_ADDITIONAL)] public string BrowserUrl { get; set; } public override string ToString() { return this.DisplayName; } + + [JsonIgnore] + public ServiceController Controller => ServiceHelpers.GetServiceController(this.ServiceName); + + public string LocalizationPrefix => "Service"; + } + + public enum ServiceGroupOperationType + { + [Description("Start")] + Start, + + [Description("Stop")] + Stop, + + [Description("Restart")] + Restart } } diff --git a/WTManager/src/Controls/WTManagerForm.cs b/WTManager/src/Controls/WTManagerForm.cs index 1979062..a5fed27 100644 --- a/WTManager/src/Controls/WTManagerForm.cs +++ b/WTManager/src/Controls/WTManagerForm.cs @@ -1,10 +1,10 @@ using System; using System.Drawing; using System.Windows.Forms; -using WTManager.Config; -using WTManager.Resources; +using WtManager.Config; +using WtManager.Resources; -namespace WTManager.Controls +namespace WtManager.Controls { [System.ComponentModel.DesignerCategory("")] public class WtManagerForm : Form, IConfigurableForm diff --git a/WTManager/src/Controls/WtManagerMainForm.cs b/WTManager/src/Controls/WtManagerMainForm.cs index d14029a..4469172 100644 --- a/WTManager/src/Controls/WtManagerMainForm.cs +++ b/WTManager/src/Controls/WtManagerMainForm.cs @@ -1,4 +1,4 @@ -namespace WTManager.Controls +namespace WtManager.Controls { [System.ComponentModel.DesignerCategory("")] public class WtManagerMainForm : WtManagerForm diff --git a/WTManager/src/Controls/WtStyle/WtCheckBox.cs b/WTManager/src/Controls/WtStyle/WtCheckBox.cs index ee87216..b05c676 100644 --- a/WTManager/src/Controls/WtStyle/WtCheckBox.cs +++ b/WTManager/src/Controls/WtStyle/WtCheckBox.cs @@ -1,6 +1,6 @@ using System.Windows.Forms; -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { public class WtCheckBox : CheckBox { diff --git a/WTManager/src/Controls/WtStyle/WtComboBox.cs b/WTManager/src/Controls/WtStyle/WtComboBox.cs index c24a25b..3931a54 100644 --- a/WTManager/src/Controls/WtStyle/WtComboBox.cs +++ b/WTManager/src/Controls/WtStyle/WtComboBox.cs @@ -2,31 +2,36 @@ using System.Collections; using System.Linq; using System.Windows.Forms; -using WTManager.Lib; +using WtManager.Lib; -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { public class WtComboBox : ComboBox { public object GetSelectedValue() { - var comboItem = this.SelectedItem as ComboBoxItem; - - if (comboItem != null) + if (this.SelectedItem is ComboBoxItem comboItem) + { return comboItem.Value; + } - if (this.SelectedItem != null) - return this.SelectedItem; - - return this.Text; + return this.SelectedItem ?? this.Text; } public void SetItems(IEnumerable items) { this.Items.Clear(); this.Items.AddRange(items.Cast().ToArray()); + + if (this.Items.Count > 0) + { + this.SelectedIndex = 0; + } } + public void SetEnumItems() where T : struct + => this.SetItems(ComboBoxItem.FromEnum()); + #region Helpers private int FindIndex(object value) @@ -34,11 +39,14 @@ private int FindIndex(object value) bool IsEqual(object item) { if (item == null && value == null) + { return true; + } - var comparable = item as IComparable; - if (comparable != null && comparable.CompareTo(value) == 0) + if (item is IComparable comparable && comparable.CompareTo(value) == 0) + { return true; + } return false; } @@ -46,17 +54,23 @@ bool IsEqual(object item) for (int i = 0; i < this.Items.Count; i++) { var comboItem = this.Items[i] as ComboBoxItem; - if (comboItem == null && IsEqual(this.Items[i]) || comboItem != null && IsEqual(comboItem.Value)) + if ((comboItem == null && IsEqual(this.Items[i])) || (comboItem != null && IsEqual(comboItem.Value))) + { return i; + } } return -1; } public void SelectByValue(object value) { - this.SelectedIndex = this.FindIndex(value); + var itemIndex = this.FindIndex(value); + if (this.Items.Count > 0) + { + this.SelectedIndex = itemIndex == -1 ? 0 : itemIndex; + } } - #endregion + #endregion Helpers } } \ No newline at end of file diff --git a/WTManager/src/Controls/WtStyle/WtConfigurator/DynamicPropertiesProcessor.cs b/WTManager/src/Controls/WtStyle/WtConfigurator/DynamicPropertiesProcessor.cs index b51da0c..6ead384 100644 --- a/WTManager/src/Controls/WtStyle/WtConfigurator/DynamicPropertiesProcessor.cs +++ b/WTManager/src/Controls/WtStyle/WtConfigurator/DynamicPropertiesProcessor.cs @@ -3,15 +3,15 @@ using System.Linq; using System.Reflection; -namespace WTManager.Controls.WtStyle.WtConfigurator +namespace WtManager.Controls.WtStyle.WtConfigurator { public class DynamicPropertiesProcessor { - private readonly IVisualProviderObject _dataObject; + private readonly IVisualSourceObject _dataObject; private PropertyInfo[] Properties => this._dataObject.GetType().GetProperties(); - public DynamicPropertiesProcessor(IVisualProviderObject dataObject) + public DynamicPropertiesProcessor(IVisualSourceObject dataObject) { this._dataObject = dataObject; } @@ -24,7 +24,7 @@ public IEnumerable EnumerateGroupNames() private bool IsVisualRendererProperty(PropertyInfo prop) => prop.GetCustomAttribute() != null; - private string GetGroupName(PropertyInfo prop) + private string GetGroupName(PropertyInfo prop) => prop.GetCustomAttribute()?.GroupTitle ?? String.Empty; public List GetGroupProperties(string groupName) @@ -34,19 +34,39 @@ public List GetGroupProperties(string groupName) foreach (var prop in this.Properties) { if (this.IsVisualRendererProperty(prop) && this.GetGroupName(prop) == groupName) + { propertiesList.Add(prop); + } } return propertiesList; } - public IEnumerable FindDependentControls(string dependencyName) + public IEnumerable FindDependentControls(string dependencyName) { foreach (var propertyInfo in this.Properties) { var dependentOn = propertyInfo.GetCustomAttributes().ToList(); - if (dependentOn.Select(d => d.DependentProperty).Contains(dependencyName)) - yield return propertyInfo.Name; + var depOn = dependentOn.FirstOrDefault(d => d.DependentProperty == dependencyName); + if (depOn != null) + { + yield return new DependentInfo(propertyInfo.Name, depOn.ReverseDependent); + } } } } + + public class DependentInfo + { + private string propertyName; + private bool isReversed; + + public string PropertyName { get => propertyName; set => propertyName = value; } + public bool IsReversed { get => isReversed; set => isReversed = value; } + + public DependentInfo(string propertyName, bool isReversed) + { + this.propertyName = propertyName; + this.isReversed = isReversed; + } + } } \ No newline at end of file diff --git a/WTManager/src/Controls/WtStyle/WtConfigurator/IDependentStateProvider.cs b/WTManager/src/Controls/WtStyle/WtConfigurator/IDependentStateProvider.cs index 596fd0d..785706c 100644 --- a/WTManager/src/Controls/WtStyle/WtConfigurator/IDependentStateProvider.cs +++ b/WTManager/src/Controls/WtStyle/WtConfigurator/IDependentStateProvider.cs @@ -1,6 +1,6 @@ using System; -namespace WTManager.Controls.WtStyle.WtConfigurator +namespace WtManager.Controls.WtStyle.WtConfigurator { public interface IDependentStateProvider { diff --git a/WTManager/src/Controls/WtStyle/WtConfigurator/IVisualProviderObject.cs b/WTManager/src/Controls/WtStyle/WtConfigurator/IVisualProviderObject.cs deleted file mode 100644 index 56f3af0..0000000 --- a/WTManager/src/Controls/WtStyle/WtConfigurator/IVisualProviderObject.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace WTManager.Controls.WtStyle.WtConfigurator -{ - public interface IVisualProviderObject - { - } -} \ No newline at end of file diff --git a/WTManager/src/Controls/WtStyle/WtConfigurator/IVisualSourceObject.cs b/WTManager/src/Controls/WtStyle/WtConfigurator/IVisualSourceObject.cs new file mode 100644 index 0000000..de959f2 --- /dev/null +++ b/WTManager/src/Controls/WtStyle/WtConfigurator/IVisualSourceObject.cs @@ -0,0 +1,10 @@ +namespace WtManager.Controls.WtStyle.WtConfigurator +{ + /// + /// Data source for configurator + /// + public interface IVisualSourceObject + { + string LocalizationPrefix { get; } + } +} \ No newline at end of file diff --git a/WTManager/src/Controls/WtStyle/WtConfigurator/LabelRendererConfiguration.cs b/WTManager/src/Controls/WtStyle/WtConfigurator/LabelRendererConfiguration.cs deleted file mode 100644 index 39fb1f1..0000000 --- a/WTManager/src/Controls/WtStyle/WtConfigurator/LabelRendererConfiguration.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel; - -namespace WTManager.Controls.WtStyle.WtConfigurator -{ - public class LabelRendererConfiguration - { - [Category("WT Controls")] - [DisplayName("ShowExternalLables")] - public bool ShowLables { get; set; } = true; - - [Category("WT Controls")] - [DisplayName("LabelPostfix")] - public string LabelPostfix { get; set; } = ":"; - } -} \ No newline at end of file diff --git a/WTManager/src/Controls/WtStyle/WtConfigurator/VisualItemAttributes.cs b/WTManager/src/Controls/WtStyle/WtConfigurator/VisualItemAttributes.cs index f1f2dc3..fc78aae 100644 --- a/WTManager/src/Controls/WtStyle/WtConfigurator/VisualItemAttributes.cs +++ b/WTManager/src/Controls/WtStyle/WtConfigurator/VisualItemAttributes.cs @@ -1,6 +1,6 @@ using System; -namespace WTManager.Controls.WtStyle.WtConfigurator +namespace WtManager.Controls.WtStyle.WtConfigurator { [AttributeUsage(AttributeTargets.Property)] public class VisualItemAttribute : Attribute @@ -8,13 +8,11 @@ public class VisualItemAttribute : Attribute public Type RendererType { get; private set; } public string GroupTitle { get; private set; } - public string DisplayText { get; private set; } - public VisualItemAttribute(Type rendererType, string displayText, string group) + public VisualItemAttribute(Type rendererType, string group) { this.RendererType = rendererType; this.GroupTitle = group; - this.DisplayText = displayText; } } @@ -31,10 +29,12 @@ public VisualItemCustomizationAttribute(int customHeight = -1) public class VisualItemDependentOnAttribute : Attribute { public string DependentProperty { get; private set; } + public bool ReverseDependent { get; private set; } - public VisualItemDependentOnAttribute(string dependentOnPropertName) + public VisualItemDependentOnAttribute(string dependentOnPropertName, bool reverseDependent = false) { this.DependentProperty = dependentOnPropertName; + this.ReverseDependent = reverseDependent; } } } diff --git a/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfigurator.cs b/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorControl.cs similarity index 79% rename from WTManager/src/Controls/WtStyle/WtConfigurator/WtConfigurator.cs rename to WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorControl.cs index dfe6e84..710d3f9 100644 --- a/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfigurator.cs +++ b/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorControl.cs @@ -4,24 +4,24 @@ using System.Linq; using System.Reflection; using System.Windows.Forms; -using WTManager.Helpers; -using WTManager.Lib; +using WtManager.Resources; +using WtManager.VisualItemRenderers; +using WtManager.Helpers; -namespace WTManager.Controls.WtStyle.WtConfigurator +namespace WtManager.Controls.WtStyle.WtConfigurator { /// /// !!! TODO: Refactor !!! /// - public partial class WtConfigurator : WtUserControl + public partial class WtConfiguratorControl : WtUserControl { private int _currentTopCoord; private DynamicPropertiesProcessor _processor; private readonly List _dependentProvidersCache; - private readonly ScrollableControl _mainPanel; - public WtConfigurator() + public WtConfiguratorControl() { this._dependentProvidersCache = new List(); @@ -33,19 +33,27 @@ public WtConfigurator() this.Controls.Add(this._mainPanel); } - public void FillSettings(IVisualProviderObject propClass, params string[] groupNames) + public void FillSettings(IVisualSourceObject propClass, params string[] groupNames) { // initialize this._currentTopCoord = 0; this._processor = new DynamicPropertiesProcessor(propClass); - if (groupNames.Length == 0) + if (groupNames == null || groupNames.Length == 0) + { groupNames = this._processor.EnumerateGroupNames().ToArray(); + } for (int i = 0; i < groupNames.Length; i++) { var propertyGroups = this._processor.GetGroupProperties(groupNames[i]); + // empty group, skipping + if (propertyGroups.Count == 0) + { + continue; + } + bool isLastGroup = i == groupNames.Length - 1; var group = this.CreateGroup(propClass, groupNames[i], propertyGroups, this.FillLastGroup && isLastGroup); @@ -53,7 +61,7 @@ public void FillSettings(IVisualProviderObject propClass, params string[] groupN } } - private Control CreateGroup(IVisualProviderObject propClass, string groupName, IEnumerable props, bool isLastGroup) + private Control CreateGroup(IVisualSourceObject propClass, string groupName, IEnumerable props, bool isLastGroup) { var mainGroupBoxContainer = new WtGroupSeparator { @@ -77,12 +85,16 @@ private Control CreateGroup(IVisualProviderObject propClass, string groupName, I var rendererAttr = prop.GetCustomAttribute(); if (rendererAttr == null) + { continue; + } var renderer = Activator.CreateInstance(rendererAttr.RendererType, propClass) as VisualItemRenderer; if (renderer?.Control == null) + { continue; + } var customData = prop.GetCustomAttribute(); @@ -90,23 +102,29 @@ private Control CreateGroup(IVisualProviderObject propClass, string groupName, I int controlHeight = this.ItemHeight; if (customData != null && customData.CustomHeight != -1) + { controlHeight = customData.CustomHeight; + } renderer.Control.Location = new Point(this.HorizontalItemPadding, initTop); - renderer.Control.Size = new Size(panel.Width - this.HorizontalItemPadding * 2, controlHeight); + renderer.Control.Size = new Size(panel.Width - (this.HorizontalItemPadding * 2), controlHeight); renderer.Control.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right; renderer.Control.Name = prop.Name; if (i == properties.Length - 1) + { lastControl = renderer.Control; + } - if ( this.LabelConfiguration.ShowLables) + if (this.LabelConfiguration.ShowLables) { - bool setInternalLabelResult = renderer.SetLabel(rendererAttr.DisplayText, this.LabelConfiguration); + string text = LocalizationManager.Get($"VisualItem.{propClass.LocalizationPrefix}.{prop.Name}"); + + bool setInternalLabelResult = renderer.SetLabel(text, this.LabelConfiguration); if (!setInternalLabelResult) { - var label = this.CreateLabel(rendererAttr.DisplayText); + var label = this.CreateLabel(text); label.Location = new Point(this.HorizontalItemPadding, initTop); label.Height = controlHeight; @@ -121,7 +139,9 @@ private Control CreateGroup(IVisualProviderObject propClass, string groupName, I renderer.SetValue(prop.GetValue(propClass)); if (renderer is IDependentStateProvider dependentStateProvider) + { this._dependentProvidersCache.Add(dependentStateProvider); + } void ApplyRendererValue() { @@ -140,8 +160,10 @@ void ApplyRendererValue() mainGroupBoxContainer.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; mainGroupBoxContainer.Top = this._currentTopCoord; - if (lastControl != null && this.FillLastControl) + if (lastControl != null && this.FillLastControl) + { lastControl.Anchor |= AnchorStyles.Bottom; + } if (isLastGroup && this._currentTopCoord + initTop < this._mainPanel.Height) { @@ -161,13 +183,16 @@ private void UpdateDependentControlsState(string controlName, bool isChecked) this.SuspendLayout(); var dependentControlNames = this._processor.FindDependentControls(controlName); - foreach (string depenentControlName in dependentControlNames) + foreach (var dependentAttribute in dependentControlNames) { - var control = this.Controls.Find(depenentControlName, true); + string dependentControlName = dependentAttribute.PropertyName; + var control = this.Controls.Find(dependentControlName, true); if (control.Length != 1) + { continue; + } - control.First().Enabled = isChecked; + control.First().Enabled = dependentAttribute.IsReversed ? !isChecked : isChecked; } this.ResumeLayout(); @@ -180,13 +205,15 @@ private void InitDependentControls() dependencyControl.StateChanged += this.StateProvider_OnStateChanged; if (!(dependencyControl is VisualItemRenderer visualItem) || visualItem.Control == null) + { return; + } this.UpdateDependentControlsState(visualItem.Control.Name, dependencyControl.CurrentState); } } - private void StateProvider_OnStateChanged(string controlName, bool isChecked) + private void StateProvider_OnStateChanged(string controlName, bool isChecked) => this.UpdateDependentControlsState(controlName, isChecked); private Label CreateLabel(string text) @@ -196,7 +223,7 @@ private Label CreateLabel(string text) TextAlign = ContentAlignment.MiddleLeft, Anchor = AnchorStyles.Left | AnchorStyles.Top, Width = this.LabelWidth, - Text = $"{text}" + this.LabelConfiguration.LabelPostfix, + Text = $"{text}{this.LabelConfiguration.LabelPostfix}", AutoEllipsis = true, Font = this.LabelFont }; @@ -219,14 +246,12 @@ protected override void OnPaint(PaintEventArgs e) using (var brush = new SolidBrush(Color.Black)) { e.Graphics.DrawString(this.Name, titleFont, brush, 0, 0); - e.Graphics.DrawString("Dynamic configurator", DefaultFont, brush, 0, 20); - e.Graphics.DrawString("Use FillSettings method in your code to fill this screen", DefaultFont, - brush, 0, 40); + e.Graphics.DrawString("Use FillSettings method in your code to fill this screen", DefaultFont, brush, 0, 40); } return; } base.OnPaint(e); } } -} +} \ No newline at end of file diff --git a/WTManager/src/Forms/AddEditServiceForm.resx b/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorControl.resx similarity index 100% rename from WTManager/src/Forms/AddEditServiceForm.resx rename to WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorControl.resx diff --git a/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorProperties.cs b/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorProperties.cs index d012872..78751d8 100644 --- a/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorProperties.cs +++ b/WTManager/src/Controls/WtStyle/WtConfigurator/WtConfiguratorProperties.cs @@ -1,9 +1,9 @@ using System.ComponentModel; using System.Drawing; -namespace WTManager.Controls.WtStyle.WtConfigurator +namespace WtManager.Controls.WtStyle.WtConfigurator { - public partial class WtConfigurator + public partial class WtConfiguratorControl { [Category("WT Controls")] [DisplayName("ControlFont")] @@ -42,13 +42,20 @@ public partial class WtConfigurator [DisplayName("FillLastControl")] public bool FillLastControl { get; set; } = false; - [Category("WT Controls")] - [DisplayName("BoldGroupNames")] - public bool BoldGroupNames { get; set; } = false; - [Category("WT Controls")] [DisplayName("LabelConfiguration")] [TypeConverter(typeof(ExpandableObjectConverter))] public LabelRendererConfiguration LabelConfiguration { get; set; } = new LabelRendererConfiguration(); } + + public class LabelRendererConfiguration + { + [Category("WT Controls")] + [DisplayName("ShowExternalLables")] + public bool ShowLables { get; set; } = true; + + [Category("WT Controls")] + [DisplayName("LabelPostfix")] + public string LabelPostfix { get; set; } = ":"; + } } diff --git a/WTManager/src/Controls/WtStyle/WtDialog.Designer.cs b/WTManager/src/Controls/WtStyle/WtDialog.Designer.cs new file mode 100644 index 0000000..66efbde --- /dev/null +++ b/WTManager/src/Controls/WtStyle/WtDialog.Designer.cs @@ -0,0 +1,71 @@ +namespace WtManager.Controls.WtStyle +{ + partial class WtDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (this.components != null)) + { + this.components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.ContentPanel = new System.Windows.Forms.Panel(); + this.ButtonsPanel = new System.Windows.Forms.Panel(); + this.SuspendLayout(); + // + // ContentPanel + // + this.ContentPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ContentPanel.Location = new System.Drawing.Point(12, 12); + this.ContentPanel.Name = "ContentPanel"; + this.ContentPanel.Size = new System.Drawing.Size(689, 508); + this.ContentPanel.TabIndex = 0; + // + // ButtonsPanel + // + this.ButtonsPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.ButtonsPanel.Location = new System.Drawing.Point(12, 526); + this.ButtonsPanel.Name = "ButtonsPanel"; + this.ButtonsPanel.Size = new System.Drawing.Size(689, 30); + this.ButtonsPanel.TabIndex = 1; + // + // WtDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(713, 568); + this.Controls.Add(this.ButtonsPanel); + this.Controls.Add(this.ContentPanel); + this.Name = "WtDialog"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Panel ContentPanel; + private System.Windows.Forms.Panel ButtonsPanel; + } +} diff --git a/WTManager/src/Controls/WtStyle/WtDialog.cs b/WTManager/src/Controls/WtStyle/WtDialog.cs new file mode 100644 index 0000000..706b922 --- /dev/null +++ b/WTManager/src/Controls/WtStyle/WtDialog.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using WtManager.Config; +using WtManager.Controls.WtStyle.WtConfigurator; +using WtManager.Resources; +using WtManager.Helpers; + +namespace WtManager.Controls.WtStyle +{ + [System.ComponentModel.DesignerCategory("Form")] + public partial class WtDialog : WtManagerForm + { + private const int BUTTON_WIDTH = 130; + private const int BUTTON_PADDING = 10; + private const int BETWEEN_CONIFGURATORS_PADDING = 10; + + private Button _okButton; + private Button _applyButton; + private Button _cancelButton; + + private readonly List _visualSourceObjects; + + public WtDialog() + { + this.InitializeComponent(); + this._visualSourceObjects = new List(); + } + + public void AddVisualSourceObject(DialogItem parameters) + { + this._visualSourceObjects.Add(parameters); + } + + public T GetSourceObject() where T : IVisualSourceObject + { + foreach (var visualSource in this._visualSourceObjects) + { + if (visualSource.VisualObject is T) + return (T)(visualSource.VisualObject); + } + return default(T); + } + + private void PrepareForm() + { + if (this._visualSourceObjects.Count < 1) + return; + + int paddingsTotalWidth = (this._visualSourceObjects.Count - 1) * BETWEEN_CONIFGURATORS_PADDING; + + // configurator width + int currentLeft = 0; + + float totalScale = this._visualSourceObjects.Sum(s => s.Scale); + if (totalScale > 1.0f) + throw new InvalidOperationException("Total scale should be less then 1"); + float dynamicScaleCount = this._visualSourceObjects.Count(s => Math.Abs(s.Scale) < 0.00001); + + for (int i = 0; i < this._visualSourceObjects.Count; i++) + { + var visualObj = this._visualSourceObjects[i]; + + var scale = visualObj.Scale > 0 ? visualObj.Scale : (1.0f - totalScale) / dynamicScaleCount; + + int confWidth = (int)((this.ContentPanel.Width - paddingsTotalWidth) * scale); + + var configurator = this.CreateConfiguratorControl(currentLeft, confWidth); + + visualObj.CofiguratorCusomizer?.Invoke(configurator); + + configurator.FillSettings(visualObj.VisualObject, visualObj.Groups.ToArray()); + + if (this._visualSourceObjects.IsLastIndex(i)) + configurator.Anchor |= AnchorStyles.Right; + + this.ContentPanel.Controls.Add(configurator); + currentLeft += confWidth + BETWEEN_CONIFGURATORS_PADDING; + } + + this.CreateButtons(); + } + + private WtConfiguratorControl CreateConfiguratorControl(int currentLeft, int width) + { + return new WtConfiguratorControl + { + GroupTitleFont = new Font(SystemFonts.MessageBoxFont, FontStyle.Bold), + ControlFont = SystemFonts.MessageBoxFont, + LabelFont = SystemFonts.MessageBoxFont, + Location = new Point(currentLeft, 0), + Size = new Size(width, this.ContentPanel.Height), + Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom + }; + } + + public DialogResult ShowModal() + { + this.PrepareForm(); + this.ShowDialog(); + + return this.DialogResult; + } + + private void CreateButtons() + { + int buttonRightCoord = this.ButtonsPanel.Width - BUTTON_WIDTH - BUTTON_PADDING; + + this._cancelButton = this.CreateButton("DialogButtons.Cancel", "dialog.cancel"); + this._cancelButton.Left = buttonRightCoord; + this._cancelButton.Click += this.Cancel_OnClick; + this.ButtonsPanel.Controls.Add(this._cancelButton); + buttonRightCoord -= BUTTON_WIDTH + BUTTON_PADDING; + + this._applyButton = this.CreateButton("DialogButtons.Apply", "dialog.apply"); + this._applyButton.Left = buttonRightCoord; + this._applyButton.Click += this.Apply_OnClick; + this.ButtonsPanel.Controls.Add(this._applyButton); + buttonRightCoord -= BUTTON_WIDTH + BUTTON_PADDING; + + this._okButton = this.CreateButton("DialogButtons.Ok", "dialog.ok"); + this._okButton.Left = buttonRightCoord; + this._okButton.Click += this.Ok_OnClick; + this.ButtonsPanel.Controls.Add(this._okButton); + } + + private void Ok_OnClick(object sender, EventArgs eventArgs) + { + this.DialogResult = DialogResult.OK; + this.ApplyChanges(); + this.Close(); + } + + private void Apply_OnClick(object sender, EventArgs eventArgs) + { + this.ApplyChanges(); + } + + private void Cancel_OnClick(object sender, EventArgs eventArgs) + { + this.DialogResult = DialogResult.Cancel; + this.Close(); + } + + private void ApplyChanges() + { + var configControls = this.GetAllChildren().OfType(); + foreach(var configControl in configControls) + configControl.ApplySettings(); + + this.Enabled = false; + ConfigManager.Instance.SaveConfig(); + this.Enabled = true; + } + + private Button CreateButton(string localizationKey, string imageKey) + { + var button = new Button + { + Width = BUTTON_WIDTH, + Height = this.ButtonsPanel.Height, + Text = LocalizationManager.Get(localizationKey), + Image = ResourcesProcessor.GetImage(imageKey), + Anchor = AnchorStyles.Bottom | AnchorStyles.Right, + ImageAlign = ContentAlignment.MiddleLeft, + Padding = new Padding(8, 3, 3, 3), + Font = SystemFonts.MessageBoxFont + }; + return button; + } + } + + public class DialogItem + { + public IVisualSourceObject VisualObject { get; private set; } + public List Groups { get; private set; } + public Action CofiguratorCusomizer { get; private set; } + + public float Scale { get; set; } + + public DialogItem(IVisualSourceObject visualObject, Action customizer = null) + { + this.VisualObject = visualObject; + this.Groups = new List(); + this.CofiguratorCusomizer = customizer; + } + + public void AddGroup(string groupName) + { + this.Groups.Add(groupName); + } + } + + +} diff --git a/WTManager/src/Forms/ConfigurationForm.resx b/WTManager/src/Controls/WtStyle/WtDialog.resx similarity index 100% rename from WTManager/src/Forms/ConfigurationForm.resx rename to WTManager/src/Controls/WtStyle/WtDialog.resx diff --git a/WTManager/src/Controls/WtStyle/WtGroupSeparator.cs b/WTManager/src/Controls/WtStyle/WtGroupSeparator.cs index 42f08d4..1ae7368 100644 --- a/WTManager/src/Controls/WtStyle/WtGroupSeparator.cs +++ b/WTManager/src/Controls/WtStyle/WtGroupSeparator.cs @@ -5,7 +5,7 @@ // ReSharper disable MemberCanBePrivate.Global -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { public class WtGroupSeparator : Panel { @@ -34,12 +34,14 @@ public override Rectangle DisplayRectangle { return new Rectangle( this.Padding.Left, - this.Font.Height + this.Padding.Top, + this.TopPadding + this.Padding.Top, Math.Max(this.ClientSize.Width - this.Padding.Horizontal, 0), - Math.Max(this.ClientSize.Height - this.Font.Height - this.Padding.Vertical, 0)); + Math.Max(this.ClientSize.Height - this.TopPadding - this.Padding.Vertical, 0)); } } + private int TopPadding => this.Font.Height + 5; + protected override void OnFontChanged(EventArgs e) { base.OnFontChanged(e); diff --git a/WTManager/src/Controls/WtStyle/WtItemEditor.Designer.cs b/WTManager/src/Controls/WtStyle/WtItemEditor.Designer.cs index 863dbbd..535d3c9 100644 --- a/WTManager/src/Controls/WtStyle/WtItemEditor.Designer.cs +++ b/WTManager/src/Controls/WtStyle/WtItemEditor.Designer.cs @@ -1,4 +1,4 @@ -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { partial class WtItemEditor { diff --git a/WTManager/src/Controls/WtStyle/WtItemEditor.cs b/WTManager/src/Controls/WtStyle/WtItemEditor.cs index a8cdae4..e3cadba 100644 --- a/WTManager/src/Controls/WtStyle/WtItemEditor.cs +++ b/WTManager/src/Controls/WtStyle/WtItemEditor.cs @@ -4,9 +4,9 @@ using System.Drawing; using System.Linq; using System.Windows.Forms; -using WTManager.Resources; +using WtManager.Resources; -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { public partial class WtItemEditor : WtUserControl { @@ -21,7 +21,7 @@ public partial class WtItemEditor : WtUserControl private int _verticalPaddingBetweenButtons = 5; private int _buttonSize = 30; - #endregion + #endregion Private fields #region Designer properties @@ -44,7 +44,7 @@ public int ButtonSize get { return this._buttonSize; } set { - this._buttonSize = value; + this._buttonSize = value; this.UpdateInterface(); } } @@ -60,7 +60,7 @@ public bool ShowAddButton get { return this._showAddButton; } set { - this._showAddButton = value; + this._showAddButton = value; this.UpdateInterface(); } } @@ -127,20 +127,20 @@ public bool ShowDownButton [DisplayName("RemoveItemOnDeleteKeyPress")] public bool RemoveItemOnDeleteKeyPress { get; set; } = true; - #endregion + #endregion Designer properties #region Add/edit functions public Func AddRequest = null; public Func EditRequest = null; - #endregion + #endregion Add/edit functions #region Constructors public WtItemEditor() => this.InitializeComponent(); - #endregion + #endregion Constructors #region Form control event handlers @@ -150,31 +150,35 @@ private void AddItemButton_OnClick(object sender, EventArgs eventArgs) private void EditItemButton_OnClick(object sender, EventArgs eventArgs) => this.EditSelectedItem(); - private void RemoveItemButton_OnClick(object sender, EventArgs eventArgs) + private void RemoveItemButton_OnClick(object sender, EventArgs eventArgs) => this.RemoveSelectedItems(); - private void DownItemButton_OnClick(object sender, EventArgs eventArgs) + private void DownItemButton_OnClick(object sender, EventArgs eventArgs) => this.MoveSelectedItem(1); - private void UpItemButton_OnClick(object sender, EventArgs eventArgs) + private void UpItemButton_OnClick(object sender, EventArgs eventArgs) => this.MoveSelectedItem(-1); - private void ItemsListBox_OnSelectedIndexChanged(object sender, EventArgs eventArgs) + private void ItemsListBox_OnSelectedIndexChanged(object sender, EventArgs eventArgs) => this.UpdateButtonEnability(); private void ItemsListBox_OnMouseDoubleClick(object sender, MouseEventArgs mouseEventArgs) { if (this.EditOnDoubleClick) + { this.EditSelectedItem(); + } } private void ItemsListBox_OnKeyUp(object sender, KeyEventArgs keyEventArgs) { if (this.RemoveItemOnDeleteKeyPress && keyEventArgs.KeyCode == Keys.Delete) + { this.RemoveSelectedItems(); + } } - #endregion + #endregion Form control event handlers #region Get/set items logic @@ -189,7 +193,7 @@ public void SetItems(IEnumerable items) this.UpdateButtonEnability(); } - #endregion + #endregion Get/set items logic #region Interface update logic @@ -214,7 +218,9 @@ private void RelocateUpButton(Control btn, bool isVisible, ref int topCoord) btn.Size = new Size(this.ButtonSize, this.ButtonSize); if (!isVisible) + { return; + } int btnLeftCoord = this.Width - btn.Width; btn.Location = new Point(btnLeftCoord, topCoord); @@ -226,7 +232,9 @@ private void RelocateDownButton(Control btn, bool isVisible, ref int bottomCoord btn.Visible = isVisible; btn.Size = new Size(this.ButtonSize, this.ButtonSize); if (!isVisible) + { return; + } int btnLeftCoord = this.Width - btn.Width; int btnTopCoord = bottomCoord - btn.Height; @@ -255,7 +263,7 @@ bool IsLastIndexSelected() => this.DownItemButton.Enabled = IsOneItemSelected() && !IsLastIndexSelected(); } - #endregion + #endregion Interface update logic #region Base form override @@ -271,7 +279,7 @@ protected override void OnLoad(EventArgs e) this.UpdateButtonEnability(); } - #endregion + #endregion Base form override #region Add/edit/remove/up/down logic @@ -279,7 +287,9 @@ private void AddNewItem() { var newItem = this.AddRequest?.Invoke(); if (newItem != null) + { this.ItemsListBox.Items.Add(newItem); + } } private void EditSelectedItem() @@ -287,43 +297,57 @@ private void EditSelectedItem() int index = this.ItemsListBox.SelectedIndex; if (index == -1) + { return; + } var item = this.EditRequest?.Invoke(this.ItemsListBox.SelectedItem); if (item != null) + { this.ItemsListBox.Items[index] = item; + } } private void RemoveSelectedItems() { if (this.ItemsListBox.SelectedItems.Count == 0) + { return; + } if (this.UseRemoveConfirmation) { - string text = String.IsNullOrEmpty(this.RemoveConfirmationText) + string text = String.IsNullOrEmpty(this.RemoveConfirmationText) ? "Do you really want to delete selected item(s)?" : this.RemoveConfirmationText; string title = "Remove item confirmation"; if (MessageBox.Show(this, text, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) + { return; + } } var selectedItems = this.ItemsListBox.SelectedItems.OfType().ToList(); foreach (var service in selectedItems) + { this.ItemsListBox.Items.Remove(service); + } } private void MoveSelectedItem(int direction) { if (this.ItemsListBox.SelectedItem == null || this.ItemsListBox.SelectedIndex < 0) + { return; - + } + int newIndex = this.ItemsListBox.SelectedIndex + direction; if (newIndex < 0 || newIndex >= this.ItemsListBox.Items.Count) + { return; + } var selected = this.ItemsListBox.SelectedItem; @@ -332,7 +356,7 @@ private void MoveSelectedItem(int direction) this.ItemsListBox.SetSelected(newIndex, true); } - #endregion + #endregion Add/edit/remove/up/down logic #region Themes support @@ -346,6 +370,6 @@ protected override void ApplyTheme() this.DownItemButton.Image = ResourcesProcessor.GetImage("dialog.down"); } - #endregion + #endregion Themes support } } \ No newline at end of file diff --git a/WTManager/src/Controls/WtStyle/WtSelector.Designer.cs b/WTManager/src/Controls/WtStyle/WtSelector.Designer.cs index b72dd55..4482cdb 100644 --- a/WTManager/src/Controls/WtStyle/WtSelector.Designer.cs +++ b/WTManager/src/Controls/WtStyle/WtSelector.Designer.cs @@ -1,4 +1,4 @@ -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { partial class MetaSelector { diff --git a/WTManager/src/Controls/WtStyle/WtSelector.cs b/WTManager/src/Controls/WtStyle/WtSelector.cs index 53796bd..6724bd8 100644 --- a/WTManager/src/Controls/WtStyle/WtSelector.cs +++ b/WTManager/src/Controls/WtStyle/WtSelector.cs @@ -4,7 +4,7 @@ using System.IO; using System.Windows.Forms; -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { public partial class MetaSelector : WtUserControl where T : class { diff --git a/WTManager/src/Controls/WtStyle/WtTextBox.cs b/WTManager/src/Controls/WtStyle/WtTextBox.cs index 629cfd8..75e7b12 100644 --- a/WTManager/src/Controls/WtStyle/WtTextBox.cs +++ b/WTManager/src/Controls/WtStyle/WtTextBox.cs @@ -1,7 +1,7 @@ using System.ComponentModel; using System.Windows.Forms; -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { public class WtTextBox : TextBox { diff --git a/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.Designer.cs b/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.Designer.cs new file mode 100644 index 0000000..d25d657 --- /dev/null +++ b/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.Designer.cs @@ -0,0 +1,94 @@ +namespace WtManager.Controls.WtStyle +{ + partial class WtTimeSpanSelector + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (this.components != null)) + { + this.components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.NumberSelector = new System.Windows.Forms.NumericUpDown(); + this.UnitSelector = new WtComboBox(); + ((System.ComponentModel.ISupportInitialize)(this.NumberSelector)).BeginInit(); + this.SuspendLayout(); + // + // NumberSelector + // + this.NumberSelector.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.NumberSelector.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.NumberSelector.Location = new System.Drawing.Point(0, 0); + this.NumberSelector.Margin = new System.Windows.Forms.Padding(0); + this.NumberSelector.Maximum = new decimal(new int[] { + 10000, + 0, + 0, + 0}); + this.NumberSelector.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.NumberSelector.Name = "NumberSelector"; + this.NumberSelector.Size = new System.Drawing.Size(199, 20); + this.NumberSelector.TabIndex = 0; + this.NumberSelector.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // UnitSelector + // + this.UnitSelector.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Right))); + this.UnitSelector.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.UnitSelector.FormattingEnabled = true; + this.UnitSelector.Location = new System.Drawing.Point(205, 0); + this.UnitSelector.Margin = new System.Windows.Forms.Padding(0); + this.UnitSelector.Name = "UnitSelector"; + this.UnitSelector.Size = new System.Drawing.Size(171, 21); + this.UnitSelector.TabIndex = 1; + // + // WtTimeSpanSelector + // + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; + this.AutoSize = true; + this.Controls.Add(this.UnitSelector); + this.Controls.Add(this.NumberSelector); + this.Margin = new System.Windows.Forms.Padding(0); + this.Name = "WtTimeSpanSelector"; + this.Size = new System.Drawing.Size(376, 21); + ((System.ComponentModel.ISupportInitialize)(this.NumberSelector)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.NumericUpDown NumberSelector; + private WtComboBox UnitSelector; + } +} diff --git a/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.cs b/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.cs new file mode 100644 index 0000000..914ebc0 --- /dev/null +++ b/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.cs @@ -0,0 +1,35 @@ +using System; + +namespace WtManager.Controls.WtStyle +{ + public partial class WtTimeSpanSelector : WtUserControl + { + public WtTimeSpanSelector() + { + this.InitializeComponent(); + this.UnitSelector.SetEnumItems(); + } + + public TimeSpan ToTimeSpan() + { + int unitNumber = 0; + + var selectedValue = this.UnitSelector.GetSelectedValue(); + if (selectedValue is TimeUnit timeUnit) + unitNumber = (int)timeUnit; + + decimal seconds = this.NumberSelector.Value * unitNumber; + var timeSpan = TimeSpan.FromSeconds((double)seconds); + + return timeSpan; + } + } + + public enum TimeUnit + { + Minute = 60, + Hour = Minute * 60, + Day = Hour * 24, + Week = Day * 7 + } +} diff --git a/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.resx b/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/WTManager/src/Controls/WtStyle/WtTimeSpanSelector.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/WTManager/src/Controls/WtStyle/WtUserControl.cs b/WTManager/src/Controls/WtStyle/WtUserControl.cs index 3530aa6..7e6b7e0 100644 --- a/WTManager/src/Controls/WtStyle/WtUserControl.cs +++ b/WTManager/src/Controls/WtStyle/WtUserControl.cs @@ -1,8 +1,8 @@ using System; using System.Windows.Forms; -using WTManager.Resources; +using WtManager.Resources; -namespace WTManager.Controls.WtStyle +namespace WtManager.Controls.WtStyle { public class WtUserControl : UserControl { diff --git a/WTManager/src/Controls/WtToolStripMenuItem.cs b/WTManager/src/Controls/WtToolStripMenuItem.cs index 5f00fe1..d80dfb4 100644 --- a/WTManager/src/Controls/WtToolStripMenuItem.cs +++ b/WTManager/src/Controls/WtToolStripMenuItem.cs @@ -1,6 +1,6 @@ using System.Windows.Forms; -namespace WTManager.Controls +namespace WtManager.Controls { [System.ComponentModel.DesignerCategory("")] public sealed class WtToolStripMenuItem : ToolStripMenuItem diff --git a/WTManager/src/Controls/WtToolStripMenuRenderer.cs b/WTManager/src/Controls/WtToolStripMenuRenderer.cs index a6aaa65..436e08c 100644 --- a/WTManager/src/Controls/WtToolStripMenuRenderer.cs +++ b/WTManager/src/Controls/WtToolStripMenuRenderer.cs @@ -1,30 +1,32 @@ using System.Drawing; using System.Windows.Forms; -namespace WTManager.Controls +namespace WtManager.Controls { internal class WtToolStripMenuRenderer : ToolStripProfessionalRenderer { - public WtToolStripMenuRenderer() + public WtToolStripMenuRenderer() : base(new MyColorTable()) { } protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) - { - if (e.Item.Enabled) - base.OnRenderMenuItemBackground(e); - } + => this.DrawBackground(e); protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) + => this.DrawBackground(e); + + private void DrawBackground(ToolStripItemRenderEventArgs e) { if (e.Item.Enabled) + { base.OnRenderMenuItemBackground(e); + } } private class MyColorTable : ProfessionalColorTable { - public override Color ImageMarginGradientBegin => Color.White; + public override Color ImageMarginGradientBegin => Color.White; public override Color ImageMarginGradientMiddle => Color.White; - public override Color ImageMarginGradientEnd => Color.White; + public override Color ImageMarginGradientEnd => Color.White; } } } \ No newline at end of file diff --git a/WTManager/src/Converters/FontConverter.cs b/WTManager/src/Converters/FontConverter.cs index c87e69f..094a206 100644 --- a/WTManager/src/Converters/FontConverter.cs +++ b/WTManager/src/Converters/FontConverter.cs @@ -2,7 +2,7 @@ using System.Drawing; using Newtonsoft.Json; -namespace WTManager.Converters +namespace WtManager.Converters { public class FontConverter : JsonConverter { @@ -15,9 +15,7 @@ public FontConverter() public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - var fontObject = value as Font; - - if (fontObject == null) + if (!(value is Font fontObject)) return; writer.WriteValue(this._converter.ConvertToString(fontObject)); @@ -25,9 +23,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - string serializedData = reader.Value as string; - - if (serializedData == null) + if (!(reader.Value is string serializedData)) return null; return this._converter.ConvertFromString(serializedData); diff --git a/WTManager/src/Forms/AddEditServiceForm.Designer.cs b/WTManager/src/Forms/AddEditServiceForm.Designer.cs deleted file mode 100644 index fa272b5..0000000 --- a/WTManager/src/Forms/AddEditServiceForm.Designer.cs +++ /dev/null @@ -1,106 +0,0 @@ -using WTManager.Controls.WtStyle.WtConfigurator; - -namespace WTManager.Forms -{ - partial class AddEditServiceForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if (disposing && (this.components != null)) { - this.components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - WTManager.Controls.WtStyle.WtConfigurator.LabelRendererConfiguration labelRendererConfiguration1 = new WTManager.Controls.WtStyle.WtConfigurator.LabelRendererConfiguration(); - this.cancelBtn = new System.Windows.Forms.Button(); - this.applyBtn = new System.Windows.Forms.Button(); - this.serviceItemConfiguration = new WTManager.Controls.WtStyle.WtConfigurator.WtConfigurator(); - this.SuspendLayout(); - // - // cancelBtn - // - this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.cancelBtn.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.cancelBtn.Location = new System.Drawing.Point(434, 471); - this.cancelBtn.Name = "cancelBtn"; - this.cancelBtn.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.cancelBtn.Size = new System.Drawing.Size(138, 36); - this.cancelBtn.TabIndex = 7; - this.cancelBtn.Text = "Cancel"; - this.cancelBtn.UseVisualStyleBackColor = true; - this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click); - // - // applyBtn - // - this.applyBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.applyBtn.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.applyBtn.Location = new System.Drawing.Point(301, 471); - this.applyBtn.Name = "applyBtn"; - this.applyBtn.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.applyBtn.Size = new System.Drawing.Size(127, 36); - this.applyBtn.TabIndex = 7; - this.applyBtn.Text = "OK"; - this.applyBtn.UseVisualStyleBackColor = true; - this.applyBtn.Click += new System.EventHandler(this.OkBtn_Click); - // - // serviceItemConfiguration - // - this.serviceItemConfiguration.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.serviceItemConfiguration.BoldGroupNames = true; - this.serviceItemConfiguration.ControlFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.serviceItemConfiguration.FillLastControl = false; - this.serviceItemConfiguration.FillLastGroup = false; - this.serviceItemConfiguration.GroupTitleFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.serviceItemConfiguration.HorizontalItemPadding = 5; - this.serviceItemConfiguration.ItemHeight = 22; - labelRendererConfiguration1.LabelPostfix = ":"; - labelRendererConfiguration1.ShowLables = true; - this.serviceItemConfiguration.LabelConfiguration = labelRendererConfiguration1; - this.serviceItemConfiguration.LabelFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.serviceItemConfiguration.LabelWidth = 180; - this.serviceItemConfiguration.Location = new System.Drawing.Point(13, 16); - this.serviceItemConfiguration.Name = "serviceItemConfiguration"; - this.serviceItemConfiguration.PaddingBetweenItems = 12; - this.serviceItemConfiguration.Size = new System.Drawing.Size(559, 449); - this.serviceItemConfiguration.TabIndex = 8; - // - // AddEditServiceForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(585, 519); - this.Controls.Add(this.serviceItemConfiguration); - this.Controls.Add(this.cancelBtn); - this.Controls.Add(this.applyBtn); - this.Name = "AddEditServiceForm"; - this.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Add/Edit Service"; - this.ResumeLayout(false); - - } - - #endregion - private System.Windows.Forms.Button applyBtn; - private System.Windows.Forms.Button cancelBtn; - private WtConfigurator serviceItemConfiguration; - } -} \ No newline at end of file diff --git a/WTManager/src/Forms/AddEditServiceForm.cs b/WTManager/src/Forms/AddEditServiceForm.cs deleted file mode 100644 index 7a9aa92..0000000 --- a/WTManager/src/Forms/AddEditServiceForm.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Windows.Forms; -using WTManager.Config; -using WTManager.Controls; -using WTManager.Resources; - -namespace WTManager.Forms -{ - [System.ComponentModel.DesignerCategory("Form")] - public partial class AddEditServiceForm : WtManagerForm - { - public Service Service { get; private set; } - - private void InitForm(Service service) - { - this.Service = service; - this.serviceItemConfiguration.FillSettings(service); - } - - public AddEditServiceForm() - { - this.InitializeComponent(); - } - - private AddEditServiceForm(Service s) : this() - { - this.InitForm(s); - } - - public static Service AddItem() - { - var addDialog = new AddEditServiceForm(new Service()); - if (addDialog.ShowDialog() == DialogResult.OK) - return addDialog.Service; - - return null; - } - - public static Service EditItem(Service serviceToEdit) - { - if (serviceToEdit == null) - return null; - - var addDialog = new AddEditServiceForm(serviceToEdit); - if (addDialog.ShowDialog() == DialogResult.OK) - return addDialog.Service; - - return null; - } - - - private void cancelBtn_Click(object sender, EventArgs e) - { - this.Close(); - } - - private void OkBtn_Click(object sender, EventArgs e) - { - this.serviceItemConfiguration.ApplySettings(); - this.DialogResult = DialogResult.OK; - this.Close(); - } - - protected override void ApplyTheme() - { - base.ApplyTheme(); - - this.applyBtn.Image = ResourcesProcessor.GetImage("dialog.ok"); - this.cancelBtn.Image = ResourcesProcessor.GetImage("dialog.cancel"); - } - } -} diff --git a/WTManager/src/Forms/ConfigurationForm.Designer.cs b/WTManager/src/Forms/ConfigurationForm.Designer.cs deleted file mode 100644 index 314eba8..0000000 --- a/WTManager/src/Forms/ConfigurationForm.Designer.cs +++ /dev/null @@ -1,132 +0,0 @@ -using WTManager.Controls.WtStyle.WtConfigurator; - -namespace WTManager.Forms -{ - partial class ConfigurationForm - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if (disposing && (this.components != null)) { - this.components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - WTManager.Controls.WtStyle.WtConfigurator.LabelRendererConfiguration labelRendererConfiguration1 = new WTManager.Controls.WtStyle.WtConfigurator.LabelRendererConfiguration(); - WTManager.Controls.WtStyle.WtConfigurator.LabelRendererConfiguration labelRendererConfiguration2 = new WTManager.Controls.WtStyle.WtConfigurator.LabelRendererConfiguration(); - this.applyBtn = new System.Windows.Forms.Button(); - this.cancelBtn = new System.Windows.Forms.Button(); - this.basicConfigurationEditor = new WTManager.Controls.WtStyle.WtConfigurator.WtConfigurator(); - this.servicesConfigurationEditor = new WTManager.Controls.WtStyle.WtConfigurator.WtConfigurator(); - this.SuspendLayout(); - // - // applyBtn - // - this.applyBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.applyBtn.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.applyBtn.Location = new System.Drawing.Point(464, 519); - this.applyBtn.Name = "applyBtn"; - this.applyBtn.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.applyBtn.Size = new System.Drawing.Size(151, 30); - this.applyBtn.TabIndex = 1; - this.applyBtn.Text = "OK"; - this.applyBtn.UseVisualStyleBackColor = true; - this.applyBtn.Click += new System.EventHandler(this.okBtn_Click); - // - // cancelBtn - // - this.cancelBtn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.cancelBtn.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.cancelBtn.Location = new System.Drawing.Point(621, 519); - this.cancelBtn.Name = "cancelBtn"; - this.cancelBtn.Padding = new System.Windows.Forms.Padding(10, 0, 10, 0); - this.cancelBtn.Size = new System.Drawing.Size(151, 30); - this.cancelBtn.TabIndex = 1; - this.cancelBtn.Text = "Cancel"; - this.cancelBtn.UseVisualStyleBackColor = true; - this.cancelBtn.Click += new System.EventHandler(this.cancelBtn_Click); - // - // basicConfigurationEditor - // - this.basicConfigurationEditor.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left))); - this.basicConfigurationEditor.BoldGroupNames = false; - this.basicConfigurationEditor.ControlFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.basicConfigurationEditor.FillLastControl = false; - this.basicConfigurationEditor.FillLastGroup = true; - this.basicConfigurationEditor.GroupTitleFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.basicConfigurationEditor.HorizontalItemPadding = 5; - this.basicConfigurationEditor.ItemHeight = 22; - labelRendererConfiguration1.LabelPostfix = ":"; - labelRendererConfiguration1.ShowLables = true; - this.basicConfigurationEditor.LabelConfiguration = labelRendererConfiguration1; - this.basicConfigurationEditor.LabelFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.basicConfigurationEditor.LabelWidth = 140; - this.basicConfigurationEditor.Location = new System.Drawing.Point(12, 12); - this.basicConfigurationEditor.Name = "basicConfigurationEditor"; - this.basicConfigurationEditor.PaddingBetweenItems = 12; - this.basicConfigurationEditor.Size = new System.Drawing.Size(428, 501); - this.basicConfigurationEditor.TabIndex = 1; - // - // servicesConfigurationEditor - // - this.servicesConfigurationEditor.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.servicesConfigurationEditor.BoldGroupNames = false; - this.servicesConfigurationEditor.ControlFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.servicesConfigurationEditor.FillLastControl = true; - this.servicesConfigurationEditor.FillLastGroup = true; - this.servicesConfigurationEditor.GroupTitleFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.servicesConfigurationEditor.HorizontalItemPadding = 5; - this.servicesConfigurationEditor.ItemHeight = 22; - labelRendererConfiguration2.LabelPostfix = ":"; - labelRendererConfiguration2.ShowLables = false; - this.servicesConfigurationEditor.LabelConfiguration = labelRendererConfiguration2; - this.servicesConfigurationEditor.LabelFont = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204))); - this.servicesConfigurationEditor.LabelWidth = 120; - this.servicesConfigurationEditor.Location = new System.Drawing.Point(446, 12); - this.servicesConfigurationEditor.Name = "servicesConfigurationEditor"; - this.servicesConfigurationEditor.PaddingBetweenItems = 12; - this.servicesConfigurationEditor.Size = new System.Drawing.Size(326, 501); - this.servicesConfigurationEditor.TabIndex = 2; - // - // ConfigurationForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(784, 561); - this.Controls.Add(this.servicesConfigurationEditor); - this.Controls.Add(this.basicConfigurationEditor); - this.Controls.Add(this.applyBtn); - this.Controls.Add(this.cancelBtn); - this.MinimumSize = new System.Drawing.Size(800, 600); - this.Name = "ConfigurationForm"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "WTManager Configuration"; - this.ResumeLayout(false); - - } - - #endregion - private System.Windows.Forms.Button cancelBtn; - private System.Windows.Forms.Button applyBtn; - private WtConfigurator basicConfigurationEditor; - private WtConfigurator servicesConfigurationEditor; - } -} \ No newline at end of file diff --git a/WTManager/src/Forms/ConfigurationForm.cs b/WTManager/src/Forms/ConfigurationForm.cs deleted file mode 100644 index a6192e1..0000000 --- a/WTManager/src/Forms/ConfigurationForm.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Windows.Forms; -using WTManager.Config; -using WTManager.Controls; -using WTManager.Resources; - -namespace WTManager.Forms -{ - [System.ComponentModel.DesignerCategory("Form")] - public partial class ConfigurationForm : WtManagerForm - { - public ConfigurationForm() - { - this.InitializeComponent(); - - this.basicConfigurationEditor.FillSettings(ConfigManager.Instance.Config, Configuration.GROUP_GENERAL, Configuration.GROUP_SYSTEM, Configuration.GROUP_UI); - this.servicesConfigurationEditor.FillSettings(ConfigManager.Instance.Config, Configuration.GROUP_SERVICES); - } - - #region Window-related buttons - - private void okBtn_Click(object sender, EventArgs e) - { - this.DialogResult = DialogResult.OK; - - this.basicConfigurationEditor.ApplySettings(); - this.servicesConfigurationEditor.ApplySettings(); - - this.SaveConfiguration(); - this.Close(); - } - - private void cancelBtn_Click(object sender, EventArgs e) - { - this.Close(); - } - - protected override void ApplyTheme() - { - base.ApplyTheme(); - this.applyBtn.Image = ResourcesProcessor.GetImage("dialog.ok"); - this.cancelBtn.Image = ResourcesProcessor.GetImage("dialog.cancel"); - } - - #endregion - } -} diff --git a/WTManager/src/Forms/LogFileViewerForm.Designer.cs b/WTManager/src/Forms/LogFileViewerForm.Designer.cs index 2ec546a..135d669 100644 --- a/WTManager/src/Forms/LogFileViewerForm.Designer.cs +++ b/WTManager/src/Forms/LogFileViewerForm.Designer.cs @@ -1,4 +1,4 @@ -namespace WTManager.Forms +namespace WtManager.Forms { partial class LogFileViewerForm { @@ -7,17 +7,6 @@ partial class LogFileViewerForm /// private System.ComponentModel.IContainer components = null; - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if (disposing && (this.components != null)) { - this.components.Dispose(); - } - base.Dispose(disposing); - } - #region Windows Form Designer generated code /// @@ -63,7 +52,6 @@ private void InitializeComponent() { this.Name = "LogFileViewerForm"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "LogFileViewer"; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.LogFileViewer_FormClosing); this.logFileContentWrapper.ResumeLayout(false); this.ResumeLayout(false); diff --git a/WTManager/src/Forms/LogFileViewerForm.cs b/WTManager/src/Forms/LogFileViewerForm.cs index 258a084..25ce186 100644 --- a/WTManager/src/Forms/LogFileViewerForm.cs +++ b/WTManager/src/Forms/LogFileViewerForm.cs @@ -4,12 +4,11 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using System.Windows.Forms; -using WTManager.Controls; -using WTManager.Helpers; -using WTManager.Lib; +using WtManager.Controls; +using WtManager.Lib; +using WtManager.Helpers; -namespace WTManager.Forms +namespace WtManager.Forms { [System.ComponentModel.DesignerCategory("Form")] public partial class LogFileViewerForm : WtManagerForm @@ -31,6 +30,16 @@ public LogFileViewerForm(string fileName) : this() Task.Factory.StartNew(this.Watcher.StartWatch); } + protected override void Dispose(bool disposing) + { + if (disposing) + this.components?.Dispose(); + base.Dispose(disposing); + + this.Watcher.FileChanged -= this.Watcher_FileChanged; + this.Watcher.Dispose(); + } + private void Watcher_FileChanged(object sender, FileWatcherEventArgs e) { this.logFileContent.InvokeIfRequired(() => @@ -40,12 +49,6 @@ private void Watcher_FileChanged(object sender, FileWatcherEventArgs e) }); } - private void LogFileViewer_FormClosing(object sender, FormClosingEventArgs e) - { - this.Watcher.FileChanged -= this.Watcher_FileChanged; - this.Watcher.Dispose(); - } - public sealed override string Text { get => base.Text; diff --git a/WTManager/src/Forms/MainForm.Designer.cs b/WTManager/src/Forms/MainForm.Designer.cs index 1228015..8b648b0 100644 --- a/WTManager/src/Forms/MainForm.Designer.cs +++ b/WTManager/src/Forms/MainForm.Designer.cs @@ -1,6 +1,6 @@ -using WTManager.Tray; +using WtManager.Tray; -namespace WTManager.Forms +namespace WtManager.Forms { partial class MainForm { diff --git a/WTManager/src/Forms/MainForm.cs b/WTManager/src/Forms/MainForm.cs index 91f36f0..334c835 100644 --- a/WTManager/src/Forms/MainForm.cs +++ b/WTManager/src/Forms/MainForm.cs @@ -1,11 +1,9 @@ using System.ComponentModel; using System.Windows.Forms; -using WTManager.Config; -using WTManager.Controls; -using WTManager.Resources; -using WTManager.Tray; +using WtManager.Controls; +using WtManager.Tray; -namespace WTManager.Forms +namespace WtManager.Forms { [DesignerCategory("Form")] public partial class MainForm : WtManagerMainForm @@ -17,13 +15,6 @@ public MainForm() this.InitializeComponent(); this._uiTray = new TrayMenu(this.trayIcon); - - ConfigManager.Instance.ConfigSaved += this.Instance_OnConfigSaved; - } - - private void Instance_OnConfigSaved(Configuration config) - { - ResourcesProcessor.ThemeName = config.ThemeName; } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) diff --git a/WTManager/src/Helpers/Extensions.cs b/WTManager/src/Helpers/Extensions.cs index 8f61347..991126d 100644 --- a/WTManager/src/Helpers/Extensions.cs +++ b/WTManager/src/Helpers/Extensions.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Windows.Forms; -namespace WTManager.Helpers +namespace WtManager.Helpers { public static class Extensions { @@ -85,5 +85,20 @@ public static IEnumerable RecursiveSelect(this IEnumerable(this TEnum enumVal) where T : Attribute where TEnum : struct + { + if (!(enumVal is Enum)) + return null; + + var type = enumVal.GetType(); + var memInfo = type.GetMember(enumVal.ToString()); + var attributes = memInfo[0].GetCustomAttributes(typeof(T), false); + return attributes.Length > 0 ? (T)attributes[0] : null; + } + + public static bool IsLastIndex(this List list, int index) + => index == list.Count - 1; + } + } diff --git a/WTManager/src/Helpers/SchedulerHelpers.cs b/WTManager/src/Helpers/SchedulerHelpers.cs index 2e60645..f656a8e 100644 --- a/WTManager/src/Helpers/SchedulerHelpers.cs +++ b/WTManager/src/Helpers/SchedulerHelpers.cs @@ -2,7 +2,7 @@ using System; using System.Linq; -namespace WTManager.Helpers +namespace WtManager.Helpers { public static class SchedulerHelpers { diff --git a/WTManager/src/Helpers/ServiceHelpers.cs b/WTManager/src/Helpers/ServiceHelpers.cs index 70971c0..32ae3d3 100644 --- a/WTManager/src/Helpers/ServiceHelpers.cs +++ b/WTManager/src/Helpers/ServiceHelpers.cs @@ -1,36 +1,45 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; +using System.Management; using System.ServiceProcess; -using WTManager.Config; +using WtManager.Config; -namespace WTManager.Helpers +namespace WtManager.Helpers { public static class ServiceHelpers { - public static IEnumerable GetAllServices() + public static IEnumerable GetAllServices() => ServiceController.GetServices(); - private static readonly Dictionary ControllerCache = - new Dictionary(); + private static readonly Dictionary ControllerCache = + new Dictionary(); - public static ServiceControllerStatus Status(this Service service) - => service.GetController().Status; + public static ServiceController GetServiceController(string serviceName) + { + try + { + if (!DoesServiceExist(serviceName)) + { + return null; + } - public static bool IsStarted(this Service service) - => service.Status() == ServiceControllerStatus.Running; + if (!ControllerCache.ContainsKey(serviceName)) + ControllerCache[serviceName] = new ServiceController(serviceName); - public static bool IsStopped(this Service service) - => service.Status() == ServiceControllerStatus.Stopped; + return ControllerCache[serviceName]; + } + catch + { + return null; + } + } - public static void StartService(this Service s) - { - var controller = s.GetController(); - if (s.IsStarted()) + public static void StartService(this ServiceController controller) + { + if (controller.Status == ServiceControllerStatus.Running) return; - try { controller.Start(); @@ -38,11 +47,9 @@ public static void StartService(this Service s) } catch { /* ... TODO ... */ } } - public static void StopService(this Service s) + public static void StopService(this ServiceController controller) { - var controller = s.GetController(); - - if (s.IsStopped()) + if (controller.Status == ServiceControllerStatus.Stopped) return; try @@ -52,13 +59,11 @@ public static void StopService(this Service s) } catch { /* ... TODO ... */ } } - public static void RestartService(this Service s) + public static void RestartService(this ServiceController controller) { - var controller = s.GetController(); - try { - if (s.IsStarted()) + if (controller.Status == ServiceControllerStatus.Running) { controller.Stop(); controller.WaitForStatus(ServiceControllerStatus.Stopped); @@ -76,39 +81,24 @@ public static IEnumerable GetServicesByGroupName(string groupName) public static void StartServiceGroup(string groupName) { foreach (var service in GetServicesByGroupName(groupName)) - service.StartService(); + service.Controller.StartService(); } public static void StopServiceGroup(string groupName) { foreach (var service in GetServicesByGroupName(groupName)) - service.StopService(); + service.Controller.StopService(); } public static void RestartServiceGroup(string groupName) { foreach (var service in GetServicesByGroupName(groupName)) - service.RestartService(); - } - - public static ServiceController GetController(this Service s) - { - try - { - if (!ControllerCache.ContainsKey(s)) - ControllerCache[s] = new ServiceController(s.ServiceName); - - return ControllerCache[s]; - } - catch (Exception) - { - return null; - } + service.Controller.RestartService(); } - public static bool IsInPendingState(this Service service) + public static bool IsInPendingState(this ServiceController controller) { - switch (service.GetController().Status) + switch (controller?.Status) { case ServiceControllerStatus.StopPending: case ServiceControllerStatus.ContinuePending: @@ -119,5 +109,25 @@ public static bool IsInPendingState(this Service service) return false; } } + + public static bool IsEnabled(this ServiceController controller) + { + return !IsInPendingState(controller) && GetStartupType(controller.ServiceName) != "Disabled"; + } + + public static bool DoesServiceExist(string serviceName) + { + return GetAllServices().FirstOrDefault(s => s.ServiceName == serviceName) != null; + } + + public static string GetStartupType(string serviceName) + { + //construct the management path + string path = "Win32_Service.Name='" + serviceName + "'"; + ManagementPath p = new ManagementPath(path); + //construct the management object + ManagementObject ManagementObj = new ManagementObject(p); + return ManagementObj["StartMode"].ToString(); + } } } diff --git a/WTManager/src/Lib/ComboBoxItem.cs b/WTManager/src/Lib/ComboBoxItem.cs index 4e1ab9b..6966d37 100644 --- a/WTManager/src/Lib/ComboBoxItem.cs +++ b/WTManager/src/Lib/ComboBoxItem.cs @@ -1,4 +1,8 @@ -namespace WTManager.Lib +using System; +using System.Collections.Generic; +using WtManager.Resources; + +namespace WtManager.Lib { public class ComboBoxItem { @@ -28,5 +32,25 @@ public override string ToString() { return this.Key; } + + public static IEnumerable FromEnum() where T : struct + { + foreach (T enumItem in Enum.GetValues(typeof(T))) + { + string name =$"Enums.{typeof(T).Name}.{enumItem.ToString()}"; + string localizedDescription = LocalizationManager.Get(name); + yield return new ComboBoxItem(localizedDescription, enumItem); + + //var attr = enumItem.GetAttribute(); + + //if (attr?.Description == null) + // yield return new ComboBoxItem(enumItem.ToString(), enumItem); + + //if (localizedDescription != null) + // yield return new ComboBoxItem(enumItem.ToString(), enumItem); + //else + // yield return new ComboBoxItem(attr?.Description, enumItem); + } + } } } diff --git a/WTManager/src/Lib/FileWatcher.cs b/WTManager/src/Lib/FileWatcher.cs index 011905c..fee127f 100644 --- a/WTManager/src/Lib/FileWatcher.cs +++ b/WTManager/src/Lib/FileWatcher.cs @@ -2,7 +2,7 @@ using System.IO; using System.Threading; -namespace WTManager.Lib +namespace WtManager.Lib { public class FileWatcher : IDisposable { diff --git a/WTManager/src/Lib/LimitedQueue.cs b/WTManager/src/Lib/LimitedQueue.cs index f9afe69..45e3b5e 100644 --- a/WTManager/src/Lib/LimitedQueue.cs +++ b/WTManager/src/Lib/LimitedQueue.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace WTManager.Lib +namespace WtManager.Lib { public class LimitedQueue : Queue { diff --git a/WTManager/src/Lib/ServiceTasksManager.cs b/WTManager/src/Lib/ServiceTasksManager.cs new file mode 100644 index 0000000..e347f4f --- /dev/null +++ b/WTManager/src/Lib/ServiceTasksManager.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Windows.Forms; +using WtManager.Config; +using WtManager.Helpers; +using WtManager.Tray; + +namespace WtManager.Lib +{ + public class ServiceTaskProcessor + { + private readonly ServiceTask _task; + private readonly ITrayController _trayController; + + private bool _isExpired; + + public ServiceTaskProcessor(ServiceTask task, ITrayController trayController) + { + this._task = task; + this._trayController = trayController; + this._isExpired = task.ExecuteTime < DateTime.Now; + } + + public bool IsNeedToExecute + => !this._isExpired && this._task.ExecuteTime < DateTime.Now; + + private void ExecuteTask() + { + var controller = ServiceHelpers.GetServiceController(this._task.ServiceName); + if (controller == null) + return; + + switch (this._task.OperationType) + { + case ServiceGroupOperationType.Start: + controller.StartService(); + break; + + case ServiceGroupOperationType.Stop: + controller.StopService(); + break; + + case ServiceGroupOperationType.Restart: + controller.RestartService(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + this._trayController.ShowBaloon("Executed", $"Task was executed", ToolTipIcon.Info); + } + + public void ExecuteTaskAsync() + { + this._isExpired = true; + + Task.Factory.StartNew(this.ExecuteTask); + } + } + + public class ServiceTasksManager + { + private readonly ITrayController _trayController; + private readonly Dictionary _processorCache; + + public ServiceTasksManager(ITrayController trayController) + { + this._trayController = trayController; + this._processorCache = new Dictionary(); + } + + public void Process() + { + if (ConfigManager.Instance.Config.Tasks == null) + return; + + foreach (var serviceTask in ConfigManager.Instance.Config.Tasks) + { + if (!this._processorCache.TryGetValue(serviceTask, out var processor)) + { + this._processorCache[serviceTask] = new ServiceTaskProcessor(serviceTask, this._trayController); + processor = this._processorCache[serviceTask]; + } + + if (processor == null) + return; + + if (processor.IsNeedToExecute) + processor.ExecuteTaskAsync(); + } + } + } +} diff --git a/WTManager/src/Lib/Taskbar.cs b/WTManager/src/Lib/Taskbar.cs index 2f4eaff..09a7139 100644 --- a/WTManager/src/Lib/Taskbar.cs +++ b/WTManager/src/Lib/Taskbar.cs @@ -16,7 +16,7 @@ // ReSharper disable All -namespace WTManager.Lib +namespace WtManager.Lib { public enum TaskbarPosition { diff --git a/WTManager/src/Tray/MenuGenerator.cs b/WTManager/src/Tray/MenuGenerator.cs index 1c0be46..d998051 100644 --- a/WTManager/src/Tray/MenuGenerator.cs +++ b/WTManager/src/Tray/MenuGenerator.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using WTManager.Config; +using WtManager.Config; -namespace WTManager.Tray +namespace WtManager.Tray { /// /// Tray menu generator @@ -35,7 +35,9 @@ public IEnumerable GenerateMenu() var groupMenuItem = new ServiceGroupMenuItem(this._controller, group.Key); foreach (var service in group) + { groupMenuItem.AddSubItem(this.CreateServiceMenu(service)); + } if (ConfigManager.Instance.Config.ShowServiceGroupOperations) { @@ -49,18 +51,25 @@ public IEnumerable GenerateMenu() else { if (!String.IsNullOrEmpty(group.Key)) + { menuItems.Add(new TitleMenuItem(this._controller, group.Key)); + } foreach (var service in group) + { menuItems.Add(this.CreateServiceMenu(service)); - + } + menuItems.Add(new SeparatorMenuItem(this._controller)); } } if (ConfigManager.Instance.Config.UseNestedServiceGroups) + { menuItems.Add(new SeparatorMenuItem(this._controller)); + } + menuItems.Add(new ServiceTasksManagerMenuItem(this._controller)); menuItems.Add(new SystemServicesManagerMenuItem(this._controller)); menuItems.Add(new SeparatorMenuItem(this._controller)); @@ -84,7 +93,9 @@ private WtMenuItem CreateServiceMenu(Service service) { topServiceMenuItem.AddSubItem(new TitleMenuItem(this._controller, "Config files")); foreach (string file in service.ConfigFiles.Where(File.Exists)) + { topServiceMenuItem.AddSubItem(new ServiceConfigMenuItem(this._controller, file)); + } topServiceMenuItem.AddSubItem(new SeparatorMenuItem(this._controller)); } @@ -92,7 +103,9 @@ private WtMenuItem CreateServiceMenu(Service service) { topServiceMenuItem.AddSubItem(new TitleMenuItem(this._controller, "Log files")); foreach (string file in service.LogFiles.Where(File.Exists)) + { topServiceMenuItem.AddSubItem(new ServiceLogMenuItem(this._controller, file)); + } topServiceMenuItem.AddSubItem(new SeparatorMenuItem(this._controller)); } @@ -115,5 +128,5 @@ public interface IMenuGenerator IEnumerable GenerateMenu(); } - #endregion + #endregion Utils } \ No newline at end of file diff --git a/WTManager/src/Tray/MenuHandlers.cs b/WTManager/src/Tray/MenuHandlers.cs index f64cd93..26a8243 100644 --- a/WTManager/src/Tray/MenuHandlers.cs +++ b/WTManager/src/Tray/MenuHandlers.cs @@ -3,13 +3,16 @@ using System.Drawing; using System.IO; using System.Linq; +using System.ServiceProcess; using System.Threading.Tasks; using System.Windows.Forms; -using WTManager.Config; -using WTManager.Forms; -using WTManager.Helpers; +using WtManager.Config; +using WtManager.Controls.WtStyle; +using WtManager.Forms; +using WtManager.Helpers; +using WtManager.Resources; -namespace WTManager.Tray +namespace WtManager.Tray { #region Base abstract specialized menu items @@ -49,7 +52,7 @@ protected ServiceGroupOperationMenuItem(ITrayController controller, string group } } - #endregion + #endregion Base abstract specialized menu items #region Service related menu items @@ -63,18 +66,31 @@ public ServiceTopMenuItem(ITrayController controller, Service service) protected override string DisplayText => this.Service.DisplayName; - protected override bool IsEnabled => !this.Service.IsInPendingState(); + protected override bool IsEnabled => !this.Service.Controller.IsInPendingState(); protected override string ImageKey { get { - if (this.Service.IsStarted()) + if (this.Service.Controller == null) + { + return "service-status-na"; + } + + if (this.Service.Controller.Status == ServiceControllerStatus.Running) + { return "service-status-started"; - if (this.Service.IsStopped()) + } + + if (this.Service.Controller.Status == ServiceControllerStatus.Stopped) + { return "service-status-stopped"; - if (this.Service.IsInPendingState()) + } + + if (this.Service.Controller.IsInPendingState()) + { return "service-status-pending"; + } return base.ImageKey; } @@ -86,10 +102,10 @@ protected override string ImageKey /// public class ServiceConfigMenuItem : FileOperationMenuItem { - public ServiceConfigMenuItem(ITrayController controller, string fileName) + public ServiceConfigMenuItem(ITrayController controller, string fileName) : base(controller, fileName) { } - protected override string DisplayText + protected override string DisplayText => $"Edit {Path.GetFileName(this.FileName)}"; protected override string ImageKey => "service-edit-config"; @@ -99,8 +115,8 @@ protected override void Action() bool isValidEditor = File.Exists(ConfigManager.Instance.Config.ConfigEditorPath); // if config editor wasn't set we will just use default notepad application - string editorPath = !isValidEditor - ? "notepad.exe" + string editorPath = !isValidEditor + ? "notepad.exe" : ConfigManager.Instance.Config.ConfigEditorPath; Process.Start(editorPath, this.FileName); @@ -112,10 +128,10 @@ protected override void Action() /// public class ServiceDirectoryMenuItem : ServiceMenuItem { - public ServiceDirectoryMenuItem(ITrayController controller, Service service) + public ServiceDirectoryMenuItem(ITrayController controller, Service service) : base(controller, service) { } - protected override string DisplayText => "Open data directory…"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceOpenDataDirectory"); protected override string ImageKey => "service-open-data-directory"; @@ -132,10 +148,10 @@ protected override void Action() /// public class ServiceBrowserMenuItem : ServiceMenuItem { - public ServiceBrowserMenuItem(ITrayController controller, Service service) + public ServiceBrowserMenuItem(ITrayController controller, Service service) : base(controller, service) { } - protected override string DisplayText => "Open in browser…"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceOpenInBrower"); protected override string ImageKey => "service-open-browser"; @@ -152,10 +168,10 @@ protected override void Action() /// public class ServiceLogMenuItem : FileOperationMenuItem { - public ServiceLogMenuItem(ITrayController controller, string fileName) + public ServiceLogMenuItem(ITrayController controller, string fileName) : base(controller, fileName) { } - protected override string DisplayText + protected override string DisplayText => $"Show {Path.GetFileName(this.FileName)}"; protected override string ImageKey => "service-show-log"; @@ -171,9 +187,13 @@ protected override void Action() } if (File.Exists(viewer)) + { Process.Start(viewer, this.FileName); + } else + { MessageBox.Show($"Can't use selected log viewer ({viewer}), check your configuration"); + } } } @@ -182,72 +202,75 @@ public class ServiceEditMenuItem : ServiceMenuItem public ServiceEditMenuItem(ITrayController controller, Service service) : base(controller, service) { } - protected override string DisplayText { get; } = "Edit configuration"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceEditConfiguration"); protected override string ImageKey => "service-config"; protected override void Action() { - if (AddEditServiceForm.EditItem(this.Service) != null) - ConfigManager.Instance.SaveConfig(); + //if (AddEditServiceForm.EditItem(this.Service) != null) + // ConfigManager.Instance.SaveConfig(); } } public class ServiceRestartMenuItem : ServiceMenuItem { - public ServiceRestartMenuItem(ITrayController controller, Service service) + public ServiceRestartMenuItem(ITrayController controller, Service service) : base(controller, service) { } - protected override string DisplayText => "Restart service"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceRestart"); protected override string ImageKey => "service-restart"; - protected override bool IsVisible => this.Service.IsStarted(); + protected override bool IsVisible + => this.Service.Controller?.Status == ServiceControllerStatus.Running; protected override async void Action() { - await Task.Factory.StartNew(this.Service.RestartService); + await Task.Factory.StartNew(this.Service.Controller.RestartService); this.Controller.ShowBaloon("Started", $"Service {this.Service.DisplayName} was restarted", ToolTipIcon.Info); } } public class ServiceStartMenuItem : ServiceMenuItem { - public ServiceStartMenuItem(ITrayController controller, Service service) + public ServiceStartMenuItem(ITrayController controller, Service service) : base(controller, service) { } - protected override string DisplayText => "Start service"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceStart"); protected override string ImageKey => "service-start"; - protected override bool IsVisible => this.Service.IsStopped(); + protected override bool IsVisible + => this.Service.Controller?.Status == ServiceControllerStatus.Stopped; protected override async void Action() { - await Task.Factory.StartNew(this.Service.StartService); + await Task.Factory.StartNew(this.Service.Controller.StartService); this.Controller.ShowBaloon("Started", $"Service {this.Service.DisplayName} was started", ToolTipIcon.Info); } } public class ServiceStopMenuItem : ServiceMenuItem { - public ServiceStopMenuItem(ITrayController controller, Service service) + public ServiceStopMenuItem(ITrayController controller, Service service) : base(controller, service) { } - protected override string DisplayText => "Stop service"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceStop"); protected override string ImageKey => "service-stop"; - protected override bool IsVisible => this.Service.IsStarted(); + protected override bool IsVisible + => this.Service.Controller != null && this.Service.Controller.Status == ServiceControllerStatus.Running; protected override async void Action() { - await Task.Factory.StartNew(this.Service.StopService); + await Task.Factory.StartNew(this.Service.Controller.StopService); this.Controller.ShowBaloon("Started", $"Service {this.Service.DisplayName} was stopped", ToolTipIcon.Info); } } - #endregion + #endregion Service related menu items #region Service group related menu items @@ -264,23 +287,24 @@ public ServiceGroupMenuItem(ITrayController controller, string groupName) } private string DisplayGroupName - => String.IsNullOrEmpty(this.GroupName) ? "" : this.GroupName; + => String.IsNullOrEmpty(this.GroupName) ? "<" + LocalizationManager.Get("TrayMenu.ServiceGroup.Ungrouped") + ">" : this.GroupName; protected override string DisplayText => $"{this.DisplayGroupName} ({this.GetStartedServicesInfo()} started)"; private string GetStartedServicesInfo() { var services = ServiceHelpers.GetServicesByGroupName(this.GroupName).ToList(); - return $"{services.Count(service => service.IsStarted())} of {services.Count}"; + int startedCount = services.Count(s => s.Controller.Status == ServiceControllerStatus.Running); + return $"{startedCount} of {services.Count}"; } } public class ServiceGroupStartMenuItem : ServiceGroupOperationMenuItem { - public ServiceGroupStartMenuItem(ITrayController controller, string groupName) + public ServiceGroupStartMenuItem(ITrayController controller, string groupName) : base(controller, groupName) { } - protected override string DisplayText => "Start group"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceGroupStart"); protected override string ImageKey => "service-start"; @@ -293,10 +317,10 @@ protected override async void Action() public class ServiceGroupStopMenuItem : ServiceGroupOperationMenuItem { - public ServiceGroupStopMenuItem(ITrayController controller, string groupName) + public ServiceGroupStopMenuItem(ITrayController controller, string groupName) : base(controller, groupName) { } - protected override string DisplayText => "Stop group"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceGroupStop"); protected override string ImageKey => "service-stop"; @@ -309,10 +333,10 @@ protected override async void Action() public class ServiceGroupRestartMenuItem : ServiceGroupOperationMenuItem { - public ServiceGroupRestartMenuItem(ITrayController controller, string groupName) + public ServiceGroupRestartMenuItem(ITrayController controller, string groupName) : base(controller, groupName) { } - protected override string DisplayText => "Restart group"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceGroupRestart"); protected override string ImageKey => "service-restart"; @@ -323,16 +347,44 @@ protected override async void Action() } } - #endregion + #endregion Service group related menu items #region Root menu items + public class ServiceTasksManagerMenuItem : WtMenuItem + { + public ServiceTasksManagerMenuItem(ITrayController controller) + : base(controller) { } + + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ServiceScheduler"); + + protected override string ImageKey => "services-scheduler"; + + protected override void Action() + { + var dialog = new WtDialog(); + + var parameters = new DialogItem(ConfigManager.Instance.Config, control => + { + control.FillLastControl = true; + control.FillLastGroup = true; + control.LabelConfiguration.ShowLables = false; + }); + parameters.AddGroup(Configuration.GROUP_TASKS); + dialog.AddVisualSourceObject(parameters); + + dialog.ShowModal(); + } + } + public class SystemServicesManagerMenuItem : WtMenuItem { - public SystemServicesManagerMenuItem(ITrayController controller) + public SystemServicesManagerMenuItem(ITrayController controller) : base(controller) { } - protected override string DisplayText => "System services manager"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.SystemServiceManager"); + + protected override string ImageKey => "system-services-manager"; protected override void Action() { @@ -342,25 +394,43 @@ protected override void Action() public class ApplicationConfigMenuItem : WtMenuItem { - public ApplicationConfigMenuItem(ITrayController controller) + public ApplicationConfigMenuItem(ITrayController controller) : base(controller) { } - protected override string DisplayText => "Program configuration"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.ProgramConfiguration"); protected override string ImageKey => "settings-manager"; protected override void Action() { - new ConfigurationForm().ShowDialog(); + var dialog = new WtDialog(); + + var basicPart = new DialogItem(ConfigManager.Instance.Config); + basicPart.AddGroup(Configuration.GROUP_GENERAL); + basicPart.AddGroup(Configuration.GROUP_SYSTEM); + basicPart.AddGroup(Configuration.GROUP_UI); + basicPart.Scale = 0.6f; + dialog.AddVisualSourceObject(basicPart); + + var servicesPart = new DialogItem(ConfigManager.Instance.Config, control => + { + control.FillLastControl = true; + control.FillLastGroup = true; + control.LabelConfiguration.ShowLables = false; + }); + servicesPart.AddGroup(Configuration.GROUP_SERVICES); + dialog.AddVisualSourceObject(servicesPart); + + dialog.ShowModal(); } } public class ApplicationExitMenuItem : WtMenuItem { - public ApplicationExitMenuItem(ITrayController controller) + public ApplicationExitMenuItem(ITrayController controller) : base(controller) { } - protected override string DisplayText => "Exit"; + protected override string DisplayText => LocalizationManager.Get("TrayMenu.AppExit"); protected override string ImageKey => "app-exit"; @@ -370,7 +440,7 @@ protected override void Action() } } - #endregion + #endregion Root menu items #region Menu handlers @@ -400,5 +470,5 @@ protected override ToolStripItem ToMenuItem() } } - #endregion + #endregion Menu handlers } \ No newline at end of file diff --git a/WTManager/src/Tray/WtMenuItem.cs b/WTManager/src/Tray/WtMenuItem.cs index 44545b6..412fa42 100644 --- a/WTManager/src/Tray/WtMenuItem.cs +++ b/WTManager/src/Tray/WtMenuItem.cs @@ -3,11 +3,11 @@ using System.Drawing; using System.Linq; using System.Windows.Forms; -using WTManager.Config; -using WTManager.Controls; -using WTManager.Resources; +using WtManager.Config; +using WtManager.Controls; +using WtManager.Resources; -namespace WTManager.Tray +namespace WtManager.Tray { public abstract class WtMenuItem : IDisposable { @@ -34,7 +34,6 @@ protected WtMenuItem(ITrayController controller) { this.Controller = controller; this.SubItems = new List(); - this._internalMenuStripItem = null; } @@ -50,7 +49,9 @@ protected virtual void Action() public void UpdateState() { if (this._internalMenuStripItem == null) + { return; + } // Update item enability this._internalMenuStripItem.Enabled = this.IsEnabled; @@ -59,19 +60,25 @@ public void UpdateState() this._internalMenuStripItem.Visible = this.IsVisible; // Update display text - this._internalMenuStripItem.Text = this.DisplayText; + this._internalMenuStripItem.Text = this.IsVisible ? this.DisplayText : String.Empty; // Update image if (this.ImageKey == null) + { return; + } var icon = ResourcesProcessor.GetImage($"menu.{this.ImageKey}"); if (icon == null) + { return; - + } + if (this._internalMenuStripItem.Image != icon) + { this._internalMenuStripItem.Image = icon; + } } protected virtual ToolStripItem ToMenuItem() @@ -86,7 +93,9 @@ protected virtual ToolStripItem ToMenuItem() } if (this.SubItems == null) + { return this._internalMenuStripItem; + } var subItems = this.SubItems.Select(si => si.ToMenuItem()).ToArray(); this._internalMenuStripItem.DropDownItems.AddRange(subItems); @@ -106,11 +115,13 @@ public static implicit operator ToolStripItem(WtMenuItem item) public void Dispose() { - if (this._internalMenuStripItem != null) + if (this._internalMenuStripItem == null) { - this._internalMenuStripItem.Click -= this.InternalMenuStripItem_OnClick; - this._internalMenuStripItem.Dispose(); + return; } + + this._internalMenuStripItem.Click -= this.InternalMenuStripItem_OnClick; + this._internalMenuStripItem.Dispose(); } } } \ No newline at end of file diff --git a/WTManager/src/Tray/WtTrayMenu.cs b/WTManager/src/Tray/WtTrayMenu.cs index 0e3494d..ec8259f 100644 --- a/WTManager/src/Tray/WtTrayMenu.cs +++ b/WTManager/src/Tray/WtTrayMenu.cs @@ -5,13 +5,13 @@ using System.Drawing; using System.Reflection; using System.Windows.Forms; -using WTManager.Config; -using WTManager.Controls; -using WTManager.Helpers; -using WTManager.Lib; -using WTManager.Resources; +using WtManager.Config; +using WtManager.Controls; +using WtManager.Helpers; +using WtManager.Lib; +using WtManager.Resources; -namespace WTManager.Tray +namespace WtManager.Tray { public class TrayMenu : ITrayController, IEnumerable, IDisposable { @@ -24,6 +24,8 @@ public class TrayMenu : ITrayController, IEnumerable, IDisposable private readonly NotifyIcon _notifyIcon; private readonly Timer _updateTimer; + private readonly ServiceTasksManager _taskProcessor; + private ContextMenuStrip ContextMenu => this._notifyIcon.ContextMenuStrip; public TrayMenu(NotifyIcon uiTrayIcon) @@ -37,10 +39,12 @@ public TrayMenu(NotifyIcon uiTrayIcon) this._notifyIcon.ContextMenuStrip.Renderer = new WtToolStripMenuRenderer(); // Update menu items state timer - this._updateTimer = new Timer {Interval = 1000}; + this._updateTimer = new Timer { Interval = 1000 }; this._updateTimer.Tick += this.UpdateTimer_OnTick; this._updateTimer.Start(); + this._taskProcessor = new ServiceTasksManager(this); + this._menuGenerator = new MenuGenerator(this); this._showContextMenuMethod = typeof(NotifyIcon).GetMethod("ShowContextMenu", FLAGS); @@ -61,8 +65,10 @@ private void UpdateTrayIcon() public void Dispose() { foreach (var menuItem in this) + { menuItem.Dispose(); - + } + this._updateTimer.Tick -= this.UpdateTimer_OnTick; this._updateTimer.Stop(); this._updateTimer.Dispose(); @@ -90,15 +96,20 @@ private void ResourcesProcessor_OnThemeChanged() private void UpdateTimer_OnTick(object sender, EventArgs eventArgs) { this.UpdateTrayMenu(); + this._taskProcessor.Process(); } private void NotifyIcon_OnMouseUp(object o, MouseEventArgs e) { if (e.Button != MouseButtons.Left && e.Button != MouseButtons.Right) + { return; + } if (e.Button == MouseButtons.Left && !ConfigManager.Instance.Config.OpenTrayMenuOnLeftClick) + { return; + } this._showContextMenuMethod?.Invoke(this._notifyIcon, null); } @@ -108,7 +119,7 @@ private void ContextMenuStrip_OnOpening(object o, CancelEventArgs cancelEventArg this.ShowContextMenu(this.ContextMenu); } - #endregion + #endregion Event handlers private void ShowContextMenu(ContextMenuStrip menu) { @@ -123,23 +134,26 @@ private void ShowContextMenu(ContextMenuStrip menu) dropDownDirection = ToolStripDropDownDirection.Left; int rightXPos = beyondTaskbar ? Taskbar.CurrentBounds.Left : Cursor.Position.X; position = new Point(rightXPos, Cursor.Position.Y); - break; + break; + case TaskbarPosition.Left: dropDownDirection = ToolStripDropDownDirection.Right; int leftXPos = beyondTaskbar ? Taskbar.CurrentBounds.Right : Cursor.Position.X; position = new Point(leftXPos, Cursor.Position.Y); break; + case TaskbarPosition.Top: dropDownDirection = ToolStripDropDownDirection.Right; int topYPos = beyondTaskbar ? Taskbar.CurrentBounds.Bottom : Cursor.Position.Y; position = new Point(Cursor.Position.X, topYPos); break; + case TaskbarPosition.Bottom: dropDownDirection = ToolStripDropDownDirection.Default; int bottomYPos = beyondTaskbar ? Taskbar.CurrentBounds.Top : Cursor.Position.Y; position = new Point(Cursor.Position.X, bottomYPos - this.ContextMenu.Height); break; - } + } menu.Show(position, dropDownDirection); } @@ -147,9 +161,11 @@ private void RecreateMenu() { this.ClearMenu(); - foreach(var menuItem in this._menuGenerator.GenerateMenu()) + foreach (var menuItem in this._menuGenerator.GenerateMenu()) + { this.AddMenuItem(menuItem); - + } + this.UpdateTrayMenu(); } @@ -168,21 +184,27 @@ public void ClearMenu() public void UpdateTrayMenu() { foreach (var menuItem in this) + { menuItem.UpdateState(); + } } public void ShowBaloon(string title, string message, ToolTipIcon icon) { if (!ConfigManager.Instance.Config.ShowPopup) + { return; + } if (!Enum.IsDefined(typeof(ToolTipIcon), icon)) + { throw new ArgumentOutOfRangeException(nameof(icon)); + } this._notifyIcon.ShowBalloonTip(BALOON_SHOW_TIME, title, message, ToolTipIcon.Info); } - #endregion + #endregion ITrayController #region IEnumerable implementation @@ -193,7 +215,9 @@ public IEnumerator GetEnumerator() var wtMenuItem = tsItem.Tag as WtMenuItem; if (wtMenuItem == null) + { continue; + } // yield root item yield return wtMenuItem; @@ -211,7 +235,7 @@ IEnumerator IEnumerable.GetEnumerator() return this.GetEnumerator(); } - #endregion + #endregion IEnumerable implementation } #region Utils @@ -246,5 +270,5 @@ public interface ITrayController void UpdateTrayMenu(); } - #endregion + #endregion Utils } \ No newline at end of file diff --git a/WTManager/src/VisualItemRenderers/VisualCheckboxRenderer.cs b/WTManager/src/VisualItemRenderers/VisualCheckboxRenderer.cs index 7c530d3..fcf38c2 100644 --- a/WTManager/src/VisualItemRenderers/VisualCheckboxRenderer.cs +++ b/WTManager/src/VisualItemRenderers/VisualCheckboxRenderer.cs @@ -1,15 +1,14 @@ using System; using System.Windows.Forms; -using WTManager.Controls.WtStyle; -using WTManager.Controls.WtStyle.WtConfigurator; -using WTManager.Lib; +using WtManager.Controls.WtStyle; +using WtManager.Controls.WtStyle.WtConfigurator; -namespace WTManager.VisualItemRenderers +namespace WtManager.VisualItemRenderers { public class VisualCheckboxRenderer : VisualItemRenderer, IDependentStateProvider { - public VisualCheckboxRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualCheckboxRenderer(IVisualSourceObject source) + : base(source) { } protected override Control CreateControl() { @@ -20,10 +19,8 @@ protected override Control CreateControl() public override void SetValue(object value) { - if (!(value is bool)) - return; - - ((WtCheckBox)this.Control).Checked = (bool)value; + if (value is bool boolValue) + ((WtCheckBox)this.Control).Checked = boolValue; } public override object GetValue() diff --git a/WTManager/src/VisualItemRenderers/VisualDateTimeRenderer.cs b/WTManager/src/VisualItemRenderers/VisualDateTimeRenderer.cs new file mode 100644 index 0000000..90c2500 --- /dev/null +++ b/WTManager/src/VisualItemRenderers/VisualDateTimeRenderer.cs @@ -0,0 +1,37 @@ +using System; +using System.Windows.Forms; +using WtManager.Controls.WtStyle.WtConfigurator; + +namespace WtManager.VisualItemRenderers +{ + public class VisualDateTimeRenderer : VisualItemRenderer + { + public VisualDateTimeRenderer(IVisualSourceObject source) + : base(source) { } + + protected override Control CreateControl() + { + var picker = new DateTimePicker + { + Format = DateTimePickerFormat.Custom, + CustomFormat = "MM/dd/yyyy hh:mm:ss" + }; + return picker; + } + + public override void SetValue(object value) + { + if (value is DateTime dt) + { + if (dt <= DateTime.MinValue || dt >= DateTime.MaxValue) + dt = DateTime.Now; + ((DateTimePicker) this.Control).Value = dt; + } + } + + public override object GetValue() + { + return ((DateTimePicker) this.Control).Value; + } + } +} \ No newline at end of file diff --git a/WTManager/src/VisualItemRenderers/VisualFileSelectorRenderer.cs b/WTManager/src/VisualItemRenderers/VisualFileSelectorRenderer.cs index f778372..393ac56 100644 --- a/WTManager/src/VisualItemRenderers/VisualFileSelectorRenderer.cs +++ b/WTManager/src/VisualItemRenderers/VisualFileSelectorRenderer.cs @@ -1,14 +1,13 @@ using System.Windows.Forms; -using WTManager.Controls.WtStyle; -using WTManager.Controls.WtStyle.WtConfigurator; -using WTManager.Lib; +using WtManager.Controls.WtStyle; +using WtManager.Controls.WtStyle.WtConfigurator; -namespace WTManager.VisualItemRenderers +namespace WtManager.VisualItemRenderers { public class VisualFileSelectorRenderer : VisualItemRenderer { - public VisualFileSelectorRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualFileSelectorRenderer(IVisualSourceObject source) + : base(source) { } protected override Control CreateControl() { @@ -28,8 +27,8 @@ public override object GetValue() public class VisualDirectorySelectorRenderer : VisualItemRenderer { - public VisualDirectorySelectorRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualDirectorySelectorRenderer(IVisualSourceObject source) + : base(source) { } protected override Control CreateControl() { diff --git a/WTManager/src/VisualItemRenderers/VisualFontSelectorRenderer.cs b/WTManager/src/VisualItemRenderers/VisualFontSelectorRenderer.cs index 70a5cf6..28a06f9 100644 --- a/WTManager/src/VisualItemRenderers/VisualFontSelectorRenderer.cs +++ b/WTManager/src/VisualItemRenderers/VisualFontSelectorRenderer.cs @@ -1,15 +1,14 @@ using System.Drawing; using System.Windows.Forms; -using WTManager.Controls.WtStyle; -using WTManager.Controls.WtStyle.WtConfigurator; -using WTManager.Lib; +using WtManager.Controls.WtStyle; +using WtManager.Controls.WtStyle.WtConfigurator; -namespace WTManager.VisualItemRenderers +namespace WtManager.VisualItemRenderers { public class VisualFontSelectorRenderer : VisualItemRenderer { - public VisualFontSelectorRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualFontSelectorRenderer(IVisualSourceObject source) + : base(source) { } protected override Control CreateControl() { diff --git a/WTManager/src/Lib/VisualItemRenderer.cs b/WTManager/src/VisualItemRenderers/VisualItemRenderer.cs similarity index 57% rename from WTManager/src/Lib/VisualItemRenderer.cs rename to WTManager/src/VisualItemRenderers/VisualItemRenderer.cs index 0fb513c..9b2dbaf 100644 --- a/WTManager/src/Lib/VisualItemRenderer.cs +++ b/WTManager/src/VisualItemRenderers/VisualItemRenderer.cs @@ -1,17 +1,19 @@ +using System.Diagnostics.CodeAnalysis; using System.Windows.Forms; -using WTManager.Controls.WtStyle.WtConfigurator; +using WtManager.Controls.WtStyle.WtConfigurator; -namespace WTManager.Lib +namespace WtManager.VisualItemRenderers { public abstract class VisualItemRenderer { public Control Control { get; private set; } - protected IVisualProviderObject VisualProvider { get; private set; } + protected IVisualSourceObject VisualSource { get; private set; } - protected VisualItemRenderer(IVisualProviderObject provider) + [SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")] + protected VisualItemRenderer(IVisualSourceObject source) { - this.VisualProvider = provider; + this.VisualSource = source; this.Control = this.CreateControl(); } diff --git a/WTManager/src/VisualItemRenderers/VisualItemsEditorRenderer.cs b/WTManager/src/VisualItemRenderers/VisualItemsEditorRenderer.cs index 30aef78..08fe53f 100644 --- a/WTManager/src/VisualItemRenderers/VisualItemsEditorRenderer.cs +++ b/WTManager/src/VisualItemRenderers/VisualItemsEditorRenderer.cs @@ -1,18 +1,15 @@ using System.Collections; using System.Linq; using System.Windows.Forms; -using WTManager.Config; -using WTManager.Controls.WtStyle; -using WTManager.Controls.WtStyle.WtConfigurator; -using WTManager.Forms; -using WTManager.Lib; +using WtManager.Controls.WtStyle; +using WtManager.Controls.WtStyle.WtConfigurator; -namespace WTManager.VisualItemRenderers +namespace WtManager.VisualItemRenderers { public abstract class VisualItemsEditorRenderer : VisualItemRenderer { - protected VisualItemsEditorRenderer(IVisualProviderObject provider) - : base(provider) { } + protected VisualItemsEditorRenderer(IVisualSourceObject source) + : base(source) { } protected override Control CreateControl() { @@ -44,22 +41,41 @@ public override object GetValue() protected virtual object EditHandler(object arg) => null; } - public class VisualServicesItemsEditorRenderer : VisualItemsEditorRenderer + public class VisualDialogItemsEditorRenderer : VisualItemsEditorRenderer where T : IVisualSourceObject, new() { - public VisualServicesItemsEditorRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualDialogItemsEditorRenderer(IVisualSourceObject source) + : base(source) { } - protected override object CreateHandler() - => AddEditServiceForm.AddItem(); + protected override object CreateHandler() + { + var dialog = new WtDialog(); - protected override object EditHandler(object arg) - => AddEditServiceForm.EditItem(arg as Service); - } + dialog.AddVisualSourceObject(new DialogItem(new T())); + + if (dialog.ShowModal() == DialogResult.OK) + return dialog.GetSourceObject(); + + return null; + } + protected override object EditHandler(object arg) + { + var dialog = new WtDialog(); + var visualObject = (T)arg; + + dialog.AddVisualSourceObject(new DialogItem(visualObject)); + + if (dialog.ShowModal() == DialogResult.OK) + return dialog.GetSourceObject(); + + return null; + } + } + public class VisualFilesItemsEditorRenderer : VisualItemsEditorRenderer { - public VisualFilesItemsEditorRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualFilesItemsEditorRenderer(IVisualSourceObject source) + : base(source) { } protected override void ConfigureControl(WtItemEditor control) { diff --git a/WTManager/src/VisualItemRenderers/VisualSelectorRenderer.cs b/WTManager/src/VisualItemRenderers/VisualSelectorRenderer.cs index 74145e7..fe05b2b 100644 --- a/WTManager/src/VisualItemRenderers/VisualSelectorRenderer.cs +++ b/WTManager/src/VisualItemRenderers/VisualSelectorRenderer.cs @@ -2,19 +2,19 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Forms; -using WTManager.Config; -using WTManager.Controls.WtStyle; -using WTManager.Controls.WtStyle.WtConfigurator; -using WTManager.Helpers; -using WTManager.Lib; -using WTManager.Resources; - -namespace WTManager.VisualItemRenderers +using WtManager.Config; +using WtManager.Controls.WtStyle; +using WtManager.Controls.WtStyle.WtConfigurator; +using WtManager.Helpers; +using WtManager.Lib; +using WtManager.Resources; + +namespace WtManager.VisualItemRenderers { public abstract class VisualSelectorRenderer : VisualItemRenderer { - protected VisualSelectorRenderer(IVisualProviderObject provider) - : base(provider) { } + protected VisualSelectorRenderer(IVisualSourceObject source) + : base(source) { } protected override Control CreateControl() { @@ -40,10 +40,19 @@ public override object GetValue() } } + public class VisualEnumSelectorType : VisualSelectorRenderer where T : struct + { + public VisualEnumSelectorType(IVisualSourceObject source) + : base(source) { } + + protected override IEnumerable GetItems() + => ComboBoxItem.FromEnum(); + } + public class VisualThemeSelectorRenderer : VisualSelectorRenderer { - public VisualThemeSelectorRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualThemeSelectorRenderer(IVisualSourceObject source) + : base(source) { } protected override IEnumerable GetItems() { @@ -53,10 +62,19 @@ protected override IEnumerable GetItems() } } + public class VisualLanguageSelectorRenderer : VisualSelectorRenderer + { + public VisualLanguageSelectorRenderer(IVisualSourceObject source) + : base(source) { } + + protected override IEnumerable GetItems() + => LocalizationManager.LocalesList.Select(l => new ComboBoxItem(l)); + } + public class VisualServiceSelectorRenderer : VisualSelectorRenderer { - public VisualServiceSelectorRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualServiceSelectorRenderer(IVisualSourceObject source) + : base(source) { } protected override IEnumerable GetItems() => ServiceHelpers.GetAllServices().Select(s => s.ServiceName).Select(s => new ComboBoxItem(s)); @@ -64,8 +82,8 @@ protected override IEnumerable GetItems() public class VisualServiceGroupSelectorRenderer : VisualSelectorRenderer { - public VisualServiceGroupSelectorRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualServiceGroupSelectorRenderer(IVisualSourceObject source) + : base(source) { } protected override IEnumerable GetItems() { diff --git a/WTManager/src/VisualItemRenderers/VisualTextRenderer.cs b/WTManager/src/VisualItemRenderers/VisualTextRenderer.cs index efad92d..e71a8b8 100644 --- a/WTManager/src/VisualItemRenderers/VisualTextRenderer.cs +++ b/WTManager/src/VisualItemRenderers/VisualTextRenderer.cs @@ -1,14 +1,13 @@ using System.Windows.Forms; -using WTManager.Controls.WtStyle; -using WTManager.Controls.WtStyle.WtConfigurator; -using WTManager.Lib; +using WtManager.Controls.WtStyle; +using WtManager.Controls.WtStyle.WtConfigurator; -namespace WTManager.VisualItemRenderers +namespace WtManager.VisualItemRenderers { public class VisualTextRenderer : VisualItemRenderer { - public VisualTextRenderer(IVisualProviderObject provider) - : base(provider) { } + public VisualTextRenderer(IVisualSourceObject source) + : base(source) { } protected override Control CreateControl() { diff --git a/WTManager/src/VisualItemRenderers/VisualTimeSpanSelector.cs b/WTManager/src/VisualItemRenderers/VisualTimeSpanSelector.cs new file mode 100644 index 0000000..906ae58 --- /dev/null +++ b/WTManager/src/VisualItemRenderers/VisualTimeSpanSelector.cs @@ -0,0 +1,27 @@ +using System.Windows.Forms; +using WtManager.Controls.WtStyle; +using WtManager.Controls.WtStyle.WtConfigurator; + +namespace WtManager.VisualItemRenderers +{ + public class VisualTimeSpanSelector : VisualItemRenderer + { + public VisualTimeSpanSelector(IVisualSourceObject source) + : base(source) { } + + protected override Control CreateControl() + { + return new WtTimeSpanSelector(); + } + + public override void SetValue(object value) + { + ((WtTimeSpanSelector) this.Control).Text = value.ToString(); + } + + public override object GetValue() + { + return ((WtTimeSpanSelector) this.Control).ToTimeSpan(); + } + } +} \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index d697493..52ffbe6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.0.{build} +version: 0.2.{build} configuration: Release platform: Any CPU os: Visual Studio 2017 @@ -17,4 +17,21 @@ artifacts: build: project: WTManager.sln parallel: true - verbosity: minimal \ No newline at end of file + verbosity: minimal +assembly_info: + patch: true + file: WTManager.Resources\AssemblyInfo.cs + assembly_version: '{version}' + assembly_file_version: '{version}' + assembly_informational_version: '{version}-rc1' +deploy: + description: '' + provider: GitHub + auth_token: + secure: 2bc9569893765949648ebfe3c80fbaa3b7281ddf + artifact: /Installer\\Target\\setup-.*\.exe/ + draft: false + prerelease: false + on: + branch: master + APPVEYOR_REPO_TAG: true