using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using Artemis.Core.Events; using Artemis.Core.Services.Interfaces; using Artemis.UI.Events; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.Home; using Artemis.UI.Screens.News; using Artemis.UI.Screens.Settings; using Artemis.UI.Screens.SurfaceEditor; using Artemis.UI.Screens.Workshop; using Artemis.UI.Utilities; using MaterialDesignThemes.Wpf; using Stylet; namespace Artemis.UI.Screens { public class RootViewModel : Conductor { private readonly ICollection _artemisViewModels; private readonly IEventAggregator _eventAggregator; private readonly IModuleViewModelFactory _moduleViewModelFactory; private readonly IPluginService _pluginService; private bool _lostFocus; public RootViewModel(ICollection artemisViewModels, IPluginService pluginService, IModuleViewModelFactory moduleViewModelFactory, IEventAggregator eventAggregator) { _artemisViewModels = artemisViewModels; _pluginService = pluginService; _moduleViewModelFactory = moduleViewModelFactory; _eventAggregator = eventAggregator; // Activate the home item ActiveItem = _artemisViewModels.First(v => v.GetType() == typeof(HomeViewModel)); ActiveItemReady = true; // Sync up with the plugin service Modules = new BindableCollection(); Modules.AddRange(_pluginService.GetPluginsOfType()); _pluginService.PluginEnabled += PluginServiceOnPluginEnabled; _pluginService.PluginDisabled += PluginServiceOnPluginDisabled; PropertyChanged += OnSelectedModuleChanged; PropertyChanged += OnSelectedPageChanged; var themeWatcher = new ThemeWatcher(); themeWatcher.ThemeChanged += (sender, args) => ApplyWindowsTheme(args.Theme); ApplyWindowsTheme(themeWatcher.GetWindowsTheme()); } private void ApplyWindowsTheme(ThemeWatcher.WindowsTheme windowsTheme) { var paletteHelper = new PaletteHelper(); var theme = paletteHelper.GetTheme(); theme.SetBaseTheme(windowsTheme == ThemeWatcher.WindowsTheme.Dark ? Theme.Dark : Theme.Light); paletteHelper.SetTheme(theme); } public IObservableCollection Modules { get; set; } public bool MenuOpen { get; set; } public ListBoxItem SelectedPage { get; set; } public Core.Plugins.Abstract.Module SelectedModule { get; set; } public bool ActiveItemReady { get; set; } public async Task NavigateToSelectedModule() { if (SelectedModule == null) return; MenuOpen = false; SelectedPage = null; // Create a view model for the given plugin info (which will be a module) var viewModel = await Task.Run(() => _moduleViewModelFactory.Create(SelectedModule)); ActivateItem(viewModel); } private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e) { var existing = Modules.FirstOrDefault(m => _pluginService.GetPluginInfo(m)?.Guid == e.PluginInfo.Guid); if (existing != null) { if (SelectedModule == existing && SelectedModule != null) SelectedModule = null; Modules.Remove(existing); } if (e.PluginInfo.Instance is Core.Plugins.Abstract.Module module) Modules.Add(module); } private void PluginServiceOnPluginDisabled(object sender, PluginEventArgs e) { var existing = Modules.FirstOrDefault(m => _pluginService.GetPluginInfo(m)?.Guid == e.PluginInfo.Guid); if (existing != null) { if (SelectedModule == existing && SelectedModule != null) SelectedModule = null; Modules.Remove(existing); } } private async void OnSelectedModuleChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(SelectedModule)) await NavigateToSelectedModule(); } private async void OnSelectedPageChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName != "SelectedPage" || SelectedPage == null) return; SelectedModule = null; MenuOpen = false; ActiveItemReady = false; // Let the menu close smoothly to avoid a sluggish feeling await Task.Delay(400); switch (SelectedPage.Name) { case "Home": ActivateItem(_artemisViewModels.First(v => v is HomeViewModel)); break; case "News": ActivateItem(_artemisViewModels.First(v => v is NewsViewModel)); break; case "Workshop": ActivateItem(_artemisViewModels.First(v => v is WorkshopViewModel)); break; case "SurfaceEditor": ActivateItem(_artemisViewModels.First(v => v is SurfaceEditorViewModel)); break; case "Settings": ActivateItem(_artemisViewModels.First(v => v is SettingsViewModel)); break; } ActiveItemReady = true; } public void WindowDeactivated() { var windowState = ((Window) View).WindowState; if (windowState == WindowState.Minimized) return; _lostFocus = true; _eventAggregator.Publish(new MainWindowFocusChangedEvent(false)); } public void WindowActivated() { if (!_lostFocus) return; _lostFocus = false; _eventAggregator.Publish(new MainWindowFocusChangedEvent(true)); } } }