1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-01-01 02:03:32 +00:00

Updated view models and views to work a lot smoother in combination with previewing

This commit is contained in:
SpoinkyNL 2017-01-05 23:28:08 +01:00
parent 9ddde37333
commit b936908274
20 changed files with 462 additions and 459 deletions

View File

@ -12,7 +12,6 @@ namespace Artemis.Managers
{ {
private readonly DeviceManager _deviceManager; private readonly DeviceManager _deviceManager;
private readonly ILogger _logger; private readonly ILogger _logger;
private ModuleModel _activeModule;
private LoopManager _waitLoopManager; private LoopManager _waitLoopManager;
private ModuleModel _waitEffect; private ModuleModel _waitEffect;
private readonly GeneralSettings _generalSettings; private readonly GeneralSettings _generalSettings;
@ -36,16 +35,7 @@ namespace Artemis.Managers
public List<ModuleModel> Modules { get; set; } public List<ModuleModel> Modules { get; set; }
public List<ModuleModel> ProcessModules { get; set; } public List<ModuleModel> ProcessModules { get; set; }
public List<ModuleModel> OverlayModules { get; set; } public List<ModuleModel> OverlayModules { get; set; }
public ModuleModel ActiveModule { get; private set; }
public ModuleModel ActiveModule
{
get { return _activeModule; }
private set
{
_activeModule = value;
RaiseEffectChangedEvent(new ModuleChangedEventArgs(value));
}
}
public event EventHandler<ModuleChangedEventArgs> EffectChanged; public event EventHandler<ModuleChangedEventArgs> EffectChanged;
@ -130,14 +120,15 @@ namespace Artemis.Managers
_logger.Debug("Starting LoopManager for module change"); _logger.Debug("Starting LoopManager for module change");
loopManager.StartAsync(); loopManager.StartAsync();
} }
if (!ActiveModule.IsBoundToProcess && !ActiveModule.IsOverlay && storeAsLast)
{
_generalSettings.LastModule = ActiveModule?.Name;
_generalSettings.Save();
}
_logger.Debug("Changed active module to: {0}", moduleModel.Name); _logger.Debug("Changed active module to: {0}", moduleModel.Name);
RaiseEffectChangedEvent(new ModuleChangedEventArgs(moduleModel));
if (ActiveModule.IsBoundToProcess || ActiveModule.IsOverlay || !storeAsLast)
return;
// Regular modules are stored as the last active module
_generalSettings.LastModule = ActiveModule?.Name;
_generalSettings.Save();
} }
private void DeviceManagerOnOnKeyboardChanged(object sender, KeyboardChangedEventArgs e) private void DeviceManagerOnOnKeyboardChanged(object sender, KeyboardChangedEventArgs e)

View File

@ -46,7 +46,8 @@ namespace Artemis.Managers
if (string.IsNullOrEmpty(_generalSettings.LastKeyboard) || _deviceManager.ChangingKeyboard) if (string.IsNullOrEmpty(_generalSettings.LastKeyboard) || _deviceManager.ChangingKeyboard)
return; return;
var activePreview = PreviewViewModules.FirstOrDefault(vm => vm.IsActive && vm.UsesProfileEditor); var activePreview = PreviewViewModules.FirstOrDefault(
vm => vm.IsActive && vm.UsesProfileEditor && vm.ModuleModel.Settings.IsEnabled);
if (activePreview != null) if (activePreview != null)
EnsurePreviewActive(activePreview); EnsurePreviewActive(activePreview);
else else

View File

@ -1,6 +1,7 @@
using Artemis.Events; using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Services; using Artemis.Services;
using Artemis.Settings;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
using Caliburn.Micro; using Caliburn.Micro;
using Ninject; using Ninject;
@ -15,14 +16,17 @@ namespace Artemis.Modules.Abstract
private readonly MainManager _mainManager; private readonly MainManager _mainManager;
private readonly IKernel _kernel; private readonly IKernel _kernel;
private ModuleSettings _settings; private ModuleSettings _settings;
private GeneralSettings _generalSettings;
public ModuleViewModel(MainManager mainManager, ModuleModel moduleModel, IKernel kernel) public ModuleViewModel(MainManager mainManager, ModuleModel moduleModel, IKernel kernel)
{ {
_mainManager = mainManager; _mainManager = mainManager;
_kernel = kernel; _kernel = kernel;
_moduleManager = mainManager.ModuleManager; _moduleManager = mainManager.ModuleManager;
_generalSettings = DAL.SettingsProvider.Load<GeneralSettings>();
ModuleModel = moduleModel; ModuleModel = moduleModel;
Settings = moduleModel.Settings; Settings = moduleModel.Settings;
_mainManager.EnabledChanged += MainManagerOnEnabledChanged; _mainManager.EnabledChanged += MainManagerOnEnabledChanged;
_moduleManager.EffectChanged += ModuleManagerOnModuleChanged; _moduleManager.EffectChanged += ModuleManagerOnModuleChanged;
@ -49,21 +53,33 @@ namespace Artemis.Modules.Abstract
} }
public virtual bool IsModuleActive => _moduleManager.ActiveModule == ModuleModel; public virtual bool IsModuleActive => _moduleManager.ActiveModule == ModuleModel;
public virtual bool IsModuleEnabled
{
get
{
if (ModuleModel.IsBoundToProcess || ModuleModel.IsBoundToProcess)
return Settings.IsEnabled;
return _generalSettings.LastModule == ModuleModel.Name;
}
}
public abstract bool UsesProfileEditor { get; } public abstract bool UsesProfileEditor { get; }
private void MainManagerOnEnabledChanged(object sender, EnabledChangedEventArgs e) private void MainManagerOnEnabledChanged(object sender, EnabledChangedEventArgs e)
{ {
UpdatedEnabledSetting();
NotifyOfPropertyChange(() => IsModuleActive); NotifyOfPropertyChange(() => IsModuleActive);
UpdateIsEnabled();
} }
private void ModuleManagerOnModuleChanged(object sender, ModuleChangedEventArgs e) private void ModuleManagerOnModuleChanged(object sender, ModuleChangedEventArgs e)
{ {
UpdatedEnabledSetting();
NotifyOfPropertyChange(() => IsModuleActive); NotifyOfPropertyChange(() => IsModuleActive);
UpdateIsEnabled(); NotifyOfPropertyChange(() => IsModuleEnabled);
} }
private void UpdateIsEnabled() private void UpdatedEnabledSetting()
{ {
if (ModuleModel.IsBoundToProcess || ModuleModel.IsOverlay) if (ModuleModel.IsBoundToProcess || ModuleModel.IsOverlay)
return; return;
@ -81,13 +97,20 @@ namespace Artemis.Modules.Abstract
// On process-bound modules, only set the module model // On process-bound modules, only set the module model
if (ModuleModel.IsBoundToProcess || ModuleModel.IsOverlay) if (ModuleModel.IsBoundToProcess || ModuleModel.IsOverlay)
{
NotifyOfPropertyChange(() => IsModuleActive);
NotifyOfPropertyChange(() => IsModuleEnabled);
return; return;
}
// On other modules, activate them if necessary // On other modules, activate them if necessary
if (IsModuleActive && !Settings.IsEnabled) if (IsModuleActive && !Settings.IsEnabled)
_moduleManager.ClearActiveModule(); _moduleManager.ClearActiveModule();
else if (!IsModuleActive && Settings.IsEnabled) else if (!IsModuleActive && Settings.IsEnabled)
_moduleManager.ChangeActiveModule(ModuleModel, _mainManager.LoopManager); _moduleManager.ChangeActiveModule(ModuleModel, _mainManager.LoopManager);
NotifyOfPropertyChange(() => IsModuleActive);
NotifyOfPropertyChange(() => IsModuleEnabled);
} }
public virtual void SaveSettings() public virtual void SaveSettings()

View File

@ -32,7 +32,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -32,7 +32,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -51,7 +51,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</Grid> </Grid>

View File

@ -34,7 +34,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -36,11 +36,11 @@
</Label> </Label>
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right">
<Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" /> <Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</Grid> </Grid>

View File

@ -45,11 +45,11 @@
</Hyperlink> </Hyperlink>
</TextBlock> </TextBlock>
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right">
<Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" /> <Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</Grid> </Grid>

View File

@ -46,11 +46,11 @@
project by MikeyTT project by MikeyTT
</TextBlock> </TextBlock>
<StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right">
<Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" /> <Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</Grid> </Grid>

View File

@ -32,7 +32,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -33,7 +33,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -29,11 +29,11 @@
</Label.Content> </Label.Content>
</Label> </Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" /> <Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -27,11 +27,11 @@
</Label.Content> </Label.Content>
</Label> </Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" /> <Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -32,11 +32,11 @@
</Label.Content> </Label.Content>
</Label> </Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" /> <Label Content="Enable module" Margin="0 3 0 0" HorizontalAlignment="Right" />
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -39,7 +39,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -33,7 +33,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -33,7 +33,7 @@
<ToggleButton Margin="0 3 0 0" Width="25" Height="25" <ToggleButton Margin="0 3 0 0" Width="25" Height="25"
Style="{DynamicResource MetroCircleToggleButtonStyle}" Style="{DynamicResource MetroCircleToggleButtonStyle}"
ToolTip="Note: You can't enable an module when Artemis is disabled" ToolTip="Note: You can't enable an module when Artemis is disabled"
IsChecked="{Binding Path=Settings.Enabled, Mode=OneWay}" IsChecked="{Binding Path=IsModuleEnabled, Mode=OneWay}"
cal:Message.Attach="[Event Click] = [Action ToggleModule]" /> cal:Message.Attach="[Event Click] = [Action ToggleModule]" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>

View File

@ -69,7 +69,6 @@ namespace Artemis.ViewModels.Profiles
_deviceManager.OnKeyboardChanged += DeviceManagerOnOnKeyboardChanged; _deviceManager.OnKeyboardChanged += DeviceManagerOnOnKeyboardChanged;
_moduleModel.ProfileChanged += ModuleModelOnProfileChanged; _moduleModel.ProfileChanged += ModuleModelOnProfileChanged;
LoadProfiles(); LoadProfiles();
ProfileViewModel.Activate();
_saveTimer = new Timer(5000); _saveTimer = new Timer(5000);
_saveTimer.Elapsed += ProfileSaveHandler; _saveTimer.Elapsed += ProfileSaveHandler;
@ -780,8 +779,7 @@ namespace Artemis.ViewModels.Profiles
public void Dispose() public void Dispose()
{ {
ProfileViewModel.Deactivate(); ProfileViewModel.Dispose();
_saveTimer?.Stop(); _saveTimer?.Stop();
_saveTimer?.Dispose(); _saveTimer?.Dispose();
_watcher?.Dispose(); _watcher?.Dispose();

View File

@ -1,400 +1,390 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Artemis.Events; using Artemis.Events;
using Artemis.Managers; using Artemis.Managers;
using Artemis.Modules.Abstract; using Artemis.Modules.Abstract;
using Artemis.Profiles; using Artemis.Profiles;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Models;
using Artemis.Profiles.Layers.Types.Folder; using Artemis.Profiles.Layers.Types.Folder;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
using Caliburn.Micro; using Caliburn.Micro;
using Castle.Components.DictionaryAdapter; using Castle.Components.DictionaryAdapter;
using MahApps.Metro; using MahApps.Metro;
namespace Artemis.ViewModels.Profiles namespace Artemis.ViewModels.Profiles
{ {
public class ProfileViewModel : PropertyChangedBase public class ProfileViewModel : PropertyChangedBase, IDisposable
{ {
private readonly DeviceManager _deviceManager; private readonly DeviceManager _deviceManager;
private double _blurProgress; private readonly LoopManager _loopManager;
private double _blurRadius; private double _blurProgress;
private DateTime _downTime; private double _blurRadius;
private LayerModel _draggingLayer; private DateTime _downTime;
private Point? _draggingLayerOffset; private LayerModel _draggingLayer;
private DrawingImage _keyboardPreview; private Point? _draggingLayerOffset;
private Cursor _keyboardPreviewCursor; private DrawingImage _keyboardPreview;
private bool _resizing; private Cursor _keyboardPreviewCursor;
private LayerModel _selectedLayer; private bool _resizing;
private bool _showAll; private LayerModel _selectedLayer;
private bool _showAll;
public ProfileViewModel(DeviceManager deviceManager, LoopManager loopManager)
{ public ProfileViewModel(DeviceManager deviceManager, LoopManager loopManager)
_deviceManager = deviceManager; {
_deviceManager = deviceManager;
ShowAll = false; _loopManager = loopManager;
loopManager.RenderCompleted += LoopManagerOnRenderCompleted; ShowAll = false;
deviceManager.OnKeyboardChanged += DeviceManagerOnOnKeyboardChanged;
} _loopManager.RenderCompleted += LoopManagerOnRenderCompleted;
_deviceManager.OnKeyboardChanged += DeviceManagerOnOnKeyboardChanged;
public ModuleModel ModuleModel { get; set; } }
public ProfileModel SelectedProfile => ModuleModel?.ProfileModel;
public ModuleModel ModuleModel { get; set; }
public LayerModel SelectedLayer public ProfileModel SelectedProfile => ModuleModel?.ProfileModel;
{
get { return _selectedLayer; } public LayerModel SelectedLayer
set {
{ get { return _selectedLayer; }
if (Equals(value, _selectedLayer)) return; set
_selectedLayer = value; {
NotifyOfPropertyChange(() => SelectedLayer); if (Equals(value, _selectedLayer)) return;
} _selectedLayer = value;
} NotifyOfPropertyChange(() => SelectedLayer);
}
public DrawingImage KeyboardPreview }
{
get { return _keyboardPreview; } public DrawingImage KeyboardPreview
set {
{ get { return _keyboardPreview; }
if (Equals(value, _keyboardPreview)) return; set
_keyboardPreview = value; {
NotifyOfPropertyChange(() => KeyboardPreview); if (Equals(value, _keyboardPreview)) return;
} _keyboardPreview = value;
} NotifyOfPropertyChange(() => KeyboardPreview);
}
public double BlurRadius }
{
get { return _blurRadius; } public double BlurRadius
set {
{ get { return _blurRadius; }
if (value.Equals(_blurRadius)) return; set
_blurRadius = value; {
NotifyOfPropertyChange(() => BlurRadius); if (value.Equals(_blurRadius)) return;
} _blurRadius = value;
} NotifyOfPropertyChange(() => BlurRadius);
}
public bool ShowAll }
{
get { return _showAll; } public bool ShowAll
set {
{ get { return _showAll; }
if (value == _showAll) return; set
_showAll = value; {
NotifyOfPropertyChange(() => ShowAll); if (value == _showAll) return;
} _showAll = value;
} NotifyOfPropertyChange(() => ShowAll);
}
public ImageSource KeyboardImage => ImageUtilities }
.BitmapToBitmapImage(_deviceManager.ActiveKeyboard?.PreviewSettings.Image ?? Resources.none);
public ImageSource KeyboardImage => ImageUtilities
public bool Activated { get; set; } .BitmapToBitmapImage(_deviceManager.ActiveKeyboard?.PreviewSettings.Image ?? Resources.none);
private void LoopManagerOnRenderCompleted(object sender, EventArgs eventArgs) private void LoopManagerOnRenderCompleted(object sender, EventArgs eventArgs)
{ {
if (!Activated) // Update the glowing effect around the keyboard
return; if (_blurProgress > 2)
_blurProgress = 0;
// Update the glowing effect around the keyboard _blurProgress = _blurProgress + 0.025;
if (_blurProgress > 2) BlurRadius = (Math.Sin(_blurProgress * Math.PI) + 1) * 10 + 10;
_blurProgress = 0;
_blurProgress = _blurProgress + 0.025; // Besides the usual checks, also check if the ActiveKeyboard isn't the NoneKeyboard
BlurRadius = (Math.Sin(_blurProgress * Math.PI) + 1) * 10 + 10; if (SelectedProfile == null || _deviceManager.ActiveKeyboard == null || _deviceManager.ActiveKeyboard.Slug == "none")
{
// Besides the usual checks, also check if the ActiveKeyboard isn't the NoneKeyboard KeyboardPreview = null;
if (SelectedProfile == null || _deviceManager.ActiveKeyboard == null ||
_deviceManager.ActiveKeyboard.Slug == "none")
{
var preview = new DrawingImage();
preview.Freeze();
KeyboardPreview = preview;
// Setup layers for the next frame // Setup layers for the next frame
if (ModuleModel.IsInitialized) if (ModuleModel.IsInitialized)
ModuleModel.PreviewLayers = new List<LayerModel>(); ModuleModel.PreviewLayers = new List<LayerModel>();
return; return;
} }
var renderLayers = GetRenderLayers(); var renderLayers = GetRenderLayers();
// Draw the current frame to the preview // Draw the current frame to the preview
var keyboardRect = _deviceManager.ActiveKeyboard.KeyboardRectangle(4); var keyboardRect = _deviceManager.ActiveKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual(); var visual = new DrawingVisual();
using (var drawingContext = visual.RenderOpen()) using (var drawingContext = visual.RenderOpen())
{ {
// Setup the DrawingVisual's size // Setup the DrawingVisual's size
drawingContext.PushClip(new RectangleGeometry(keyboardRect)); drawingContext.PushClip(new RectangleGeometry(keyboardRect));
drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect); drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect);
// Draw the layers // Draw the layers
foreach (var layer in renderLayers) foreach (var layer in renderLayers)
{ {
layer.Update(null, true, false); layer.Update(null, true, false);
if (layer.LayerType.ShowInEdtor) if (layer.LayerType.ShowInEdtor)
layer.Draw(null, drawingContext, true, false); layer.Draw(null, drawingContext, true, false);
} }
// Get the selection color // Get the selection color
var accentColor = ThemeManager.DetectAppStyle(Application.Current)?.Item2?.Resources["AccentColor"]; var accentColor = ThemeManager.DetectAppStyle(Application.Current)?.Item2?.Resources["AccentColor"];
if (accentColor == null) if (accentColor == null)
{ {
var preview = new DrawingImage(); var preview = new DrawingImage();
preview.Freeze(); preview.Freeze();
KeyboardPreview = preview; KeyboardPreview = preview;
return; return;
} }
var pen = new Pen(new SolidColorBrush((Color) accentColor), 0.4); var pen = new Pen(new SolidColorBrush((Color) accentColor), 0.4);
// Draw the selection outline and resize indicator // Draw the selection outline and resize indicator
if (SelectedLayer != null && SelectedLayer.MustDraw()) if (SelectedLayer != null && SelectedLayer.MustDraw())
{ {
var layerRect = SelectedLayer.Properties.PropertiesRect(); var layerRect = SelectedLayer.Properties.PropertiesRect();
// Deflate the rect so that the border is drawn on the inside // Deflate the rect so that the border is drawn on the inside
layerRect.Inflate(-0.2, -0.2); layerRect.Inflate(-0.2, -0.2);
// Draw an outline around the selected layer // Draw an outline around the selected layer
drawingContext.DrawRectangle(null, pen, layerRect); drawingContext.DrawRectangle(null, pen, layerRect);
// Draw a resize indicator in the bottom-right // Draw a resize indicator in the bottom-right
drawingContext.DrawLine(pen, drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 1, layerRect.BottomRight.Y - 0.5), new Point(layerRect.BottomRight.X - 1, layerRect.BottomRight.Y - 0.5),
new Point(layerRect.BottomRight.X - 1.2, layerRect.BottomRight.Y - 0.7)); new Point(layerRect.BottomRight.X - 1.2, layerRect.BottomRight.Y - 0.7));
drawingContext.DrawLine(pen, drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 0.5, layerRect.BottomRight.Y - 1), new Point(layerRect.BottomRight.X - 0.5, layerRect.BottomRight.Y - 1),
new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 1.2)); new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 1.2));
drawingContext.DrawLine(pen, drawingContext.DrawLine(pen,
new Point(layerRect.BottomRight.X - 0.5, layerRect.BottomRight.Y - 0.5), new Point(layerRect.BottomRight.X - 0.5, layerRect.BottomRight.Y - 0.5),
new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 0.7)); new Point(layerRect.BottomRight.X - 0.7, layerRect.BottomRight.Y - 0.7));
} }
SelectedProfile.RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(DrawType.Preview, null, true, drawingContext)); SelectedProfile.RaiseDeviceDrawnEvent(new ProfileDeviceEventsArg(DrawType.Preview, null, true, drawingContext));
// Remove the clip // Remove the clip
drawingContext.Pop(); drawingContext.Pop();
} }
var drawnPreview = new DrawingImage(visual.Drawing); var drawnPreview = new DrawingImage(visual.Drawing);
drawnPreview.Freeze(); drawnPreview.Freeze();
KeyboardPreview = drawnPreview; KeyboardPreview = drawnPreview;
// Setup layers for the next frame // Setup layers for the next frame
if (ModuleModel.IsInitialized) if (ModuleModel.IsInitialized)
ModuleModel.PreviewLayers = renderLayers; ModuleModel.PreviewLayers = renderLayers;
} }
private void DeviceManagerOnOnKeyboardChanged(object sender, KeyboardChangedEventArgs e) private void DeviceManagerOnOnKeyboardChanged(object sender, KeyboardChangedEventArgs e)
{ {
NotifyOfPropertyChange(() => KeyboardImage); NotifyOfPropertyChange(() => KeyboardImage);
} }
#region Processing
public void Activate()
{ /// <summary>
Activated = true; /// Handler for clicking
} /// </summary>
/// <param name="e"></param>
public void Deactivate() public void MouseDownKeyboardPreview(MouseButtonEventArgs e)
{ {
Activated = false; if (e.LeftButton == MouseButtonState.Pressed)
} _downTime = DateTime.Now;
}
#region Processing
/// <summary>
/// <summary> /// Second handler for clicking, selects a the layer the user clicked on.
/// Handler for clicking /// </summary>
/// </summary> /// <param name="e"></param>
/// <param name="e"></param> public void MouseUpKeyboardPreview(MouseButtonEventArgs e)
public void MouseDownKeyboardPreview(MouseButtonEventArgs e) {
{ if (SelectedProfile == null || SelectedProfile.IsDefault)
if (e.LeftButton == MouseButtonState.Pressed) return;
_downTime = DateTime.Now;
} var timeSinceDown = DateTime.Now - _downTime;
if (!(timeSinceDown.TotalMilliseconds < 500))
/// <summary> return;
/// Second handler for clicking, selects a the layer the user clicked on. if (_draggingLayer != null)
/// </summary> return;
/// <param name="e"></param>
public void MouseUpKeyboardPreview(MouseButtonEventArgs e) var keyboard = _deviceManager.ActiveKeyboard;
{ var pos = e.GetPosition((Image) e.OriginalSource);
if (SelectedProfile == null || SelectedProfile.IsDefault) var x = pos.X / ((double) keyboard.PreviewSettings.Width / keyboard.Width);
return; var y = pos.Y / ((double) keyboard.PreviewSettings.Height / keyboard.Height);
var timeSinceDown = DateTime.Now - _downTime; var hoverLayer = GetLayers().Where(l => l.MustDraw())
if (!(timeSinceDown.TotalMilliseconds < 500)) .FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(x, y));
return;
if (_draggingLayer != null) if (hoverLayer != null)
return; SelectedLayer = hoverLayer;
}
var keyboard = _deviceManager.ActiveKeyboard;
var pos = e.GetPosition((Image) e.OriginalSource); /// <summary>
var x = pos.X / ((double) keyboard.PreviewSettings.Width / keyboard.Width); /// Handler for resizing and moving the currently selected layer
var y = pos.Y / ((double) keyboard.PreviewSettings.Height / keyboard.Height); /// </summary>
/// <param name="e"></param>
var hoverLayer = GetLayers().Where(l => l.MustDraw()) public void MouseMoveKeyboardPreview(MouseEventArgs e)
.FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(x, y)); {
if (SelectedProfile == null)
if (hoverLayer != null) return;
SelectedLayer = hoverLayer;
} var pos = e.GetPosition((Image) e.OriginalSource);
var keyboard = _deviceManager.ActiveKeyboard;
/// <summary> var x = pos.X / ((double) keyboard.PreviewSettings.Width / keyboard.Width);
/// Handler for resizing and moving the currently selected layer var y = pos.Y / ((double) keyboard.PreviewSettings.Height / keyboard.Height);
/// </summary> var hoverLayer = GetLayers().Where(l => l.MustDraw())
/// <param name="e"></param> .FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(x, y));
public void MouseMoveKeyboardPreview(MouseEventArgs e)
{ HandleDragging(e, x, y, hoverLayer);
if (SelectedProfile == null)
return; if (hoverLayer == null)
{
var pos = e.GetPosition((Image) e.OriginalSource); KeyboardPreviewCursor = Cursors.Arrow;
var keyboard = _deviceManager.ActiveKeyboard; return;
var x = pos.X / ((double) keyboard.PreviewSettings.Width / keyboard.Width); }
var y = pos.Y / ((double) keyboard.PreviewSettings.Height / keyboard.Height);
var hoverLayer = GetLayers().Where(l => l.MustDraw()) // Turn the mouse pointer into a hand if hovering over an active layer
.FirstOrDefault(l => l.Properties.PropertiesRect(1).Contains(x, y)); if (hoverLayer == SelectedLayer)
{
HandleDragging(e, x, y, hoverLayer); var rect = hoverLayer.Properties.PropertiesRect(1);
KeyboardPreviewCursor =
if (hoverLayer == null) Math.Sqrt(Math.Pow(x - rect.BottomRight.X, 2) + Math.Pow(y - rect.BottomRight.Y, 2)) < 0.6
{ ? Cursors.SizeNWSE
KeyboardPreviewCursor = Cursors.Arrow; : Cursors.SizeAll;
return; }
} else
{
// Turn the mouse pointer into a hand if hovering over an active layer KeyboardPreviewCursor = Cursors.Hand;
if (hoverLayer == SelectedLayer) }
{ }
var rect = hoverLayer.Properties.PropertiesRect(1);
KeyboardPreviewCursor = public Cursor KeyboardPreviewCursor
Math.Sqrt(Math.Pow(x - rect.BottomRight.X, 2) + Math.Pow(y - rect.BottomRight.Y, 2)) < 0.6 {
? Cursors.SizeNWSE get { return _keyboardPreviewCursor; }
: Cursors.SizeAll; set
} {
else if (Equals(value, _keyboardPreviewCursor)) return;
{ _keyboardPreviewCursor = value;
KeyboardPreviewCursor = Cursors.Hand; NotifyOfPropertyChange(() => KeyboardPreviewCursor);
} }
} }
public Cursor KeyboardPreviewCursor /// <summary>
{ /// Handles dragging the given layer
get { return _keyboardPreviewCursor; } /// </summary>
set /// <param name="e"></param>
{ /// <param name="x"></param>
if (Equals(value, _keyboardPreviewCursor)) return; /// <param name="y"></param>
_keyboardPreviewCursor = value; /// <param name="hoverLayer"></param>
NotifyOfPropertyChange(() => KeyboardPreviewCursor); private void HandleDragging(MouseEventArgs e, double x, double y, LayerModel hoverLayer)
} {
} // Reset the dragging state on mouse release
if (e.LeftButton == MouseButtonState.Released ||
/// <summary> _draggingLayer != null && SelectedLayer != _draggingLayer)
/// Handles dragging the given layer {
/// </summary> _draggingLayerOffset = null;
/// <param name="e"></param> _draggingLayer = null;
/// <param name="x"></param> return;
/// <param name="y"></param> }
/// <param name="hoverLayer"></param>
private void HandleDragging(MouseEventArgs e, double x, double y, LayerModel hoverLayer) if (SelectedLayer == null || SelectedLayer.LayerType != null && !SelectedLayer.LayerType.ShowInEdtor)
{ return;
// Reset the dragging state on mouse release
if (e.LeftButton == MouseButtonState.Released || // Setup the dragging state on mouse press
_draggingLayer != null && SelectedLayer != _draggingLayer) if (_draggingLayerOffset == null && hoverLayer != null && e.LeftButton == MouseButtonState.Pressed)
{ {
_draggingLayerOffset = null; var layerRect = hoverLayer.Properties.PropertiesRect(1);
_draggingLayer = null;
return; _draggingLayerOffset = new Point(x - SelectedLayer.Properties.X, y - SelectedLayer.Properties.Y);
} _draggingLayer = hoverLayer;
// Detect dragging if cursor is in the bottom right
if (SelectedLayer == null || SelectedLayer.LayerType != null && !SelectedLayer.LayerType.ShowInEdtor) _resizing = Math.Sqrt(Math.Pow(x - layerRect.BottomRight.X, 2) +
return; Math.Pow(y - layerRect.BottomRight.Y, 2)) < 0.6;
}
// Setup the dragging state on mouse press
if (_draggingLayerOffset == null && hoverLayer != null && e.LeftButton == MouseButtonState.Pressed) if (_draggingLayerOffset == null || _draggingLayer == null || _draggingLayer != SelectedLayer)
{ return;
var layerRect = hoverLayer.Properties.PropertiesRect(1);
var draggingProps = _draggingLayer.Properties;
_draggingLayerOffset = new Point(x - SelectedLayer.Properties.X, y - SelectedLayer.Properties.Y); // If no setup or reset was done, handle the actual dragging action
_draggingLayer = hoverLayer; if (_resizing)
// Detect dragging if cursor is in the bottom right {
_resizing = Math.Sqrt(Math.Pow(x - layerRect.BottomRight.X, 2) + var newWidth = Math.Round(x - draggingProps.X);
Math.Pow(y - layerRect.BottomRight.Y, 2)) < 0.6; var newHeight = Math.Round(y - draggingProps.Y);
}
// Ensure the layer doesn't leave the canvas
if (_draggingLayerOffset == null || _draggingLayer == null || _draggingLayer != SelectedLayer) if (newWidth < 1 || draggingProps.X + newWidth <= 0)
return; newWidth = draggingProps.Width;
if (newHeight < 1 || draggingProps.Y + newHeight <= 0)
var draggingProps = _draggingLayer.Properties; newHeight = draggingProps.Height;
// If no setup or reset was done, handle the actual dragging action
if (_resizing) draggingProps.Width = newWidth;
{ draggingProps.Height = newHeight;
var newWidth = Math.Round(x - draggingProps.X); }
var newHeight = Math.Round(y - draggingProps.Y); else
{
// Ensure the layer doesn't leave the canvas var newX = Math.Round(x - _draggingLayerOffset.Value.X);
if (newWidth < 1 || draggingProps.X + newWidth <= 0) var newY = Math.Round(y - _draggingLayerOffset.Value.Y);
newWidth = draggingProps.Width;
if (newHeight < 1 || draggingProps.Y + newHeight <= 0) // Ensure the layer doesn't leave the canvas
newHeight = draggingProps.Height; if (newX >= SelectedProfile.Width || newX + draggingProps.Width <= 0)
newX = draggingProps.X;
draggingProps.Width = newWidth; if (newY >= SelectedProfile.Height || newY + draggingProps.Height <= 0)
draggingProps.Height = newHeight; newY = draggingProps.Y;
}
else draggingProps.X = newX;
{ draggingProps.Y = newY;
var newX = Math.Round(x - _draggingLayerOffset.Value.X); }
var newY = Math.Round(y - _draggingLayerOffset.Value.Y); }
// Ensure the layer doesn't leave the canvas public List<LayerModel> GetRenderLayers()
if (newX >= SelectedProfile.Width || newX + draggingProps.Width <= 0) {
newX = draggingProps.X; // Get the layers that must be drawn
if (newY >= SelectedProfile.Height || newY + draggingProps.Height <= 0) List<LayerModel> drawLayers;
newY = draggingProps.Y; if (ShowAll)
return SelectedProfile.GetRenderLayers(null, false, true);
draggingProps.X = newX;
draggingProps.Y = newY; if (SelectedLayer == null || !SelectedLayer.Enabled)
} return new EditableList<LayerModel>();
}
if (SelectedLayer.LayerType is FolderType)
public List<LayerModel> GetRenderLayers() drawLayers = SelectedLayer.GetRenderLayers(null, false, true);
{ else
// Get the layers that must be drawn drawLayers = new List<LayerModel> {SelectedLayer};
List<LayerModel> drawLayers;
if (ShowAll) return drawLayers;
return SelectedProfile.GetRenderLayers(null, false, true); }
if (SelectedLayer == null || !SelectedLayer.Enabled)
return new EditableList<LayerModel>(); private List<LayerModel> GetLayers()
{
if (SelectedLayer.LayerType is FolderType) if (ShowAll)
drawLayers = SelectedLayer.GetRenderLayers(null, false, true); return SelectedProfile.GetLayers();
else if (SelectedLayer == null)
drawLayers = new List<LayerModel> {SelectedLayer}; return new List<LayerModel>();
return drawLayers; lock (SelectedLayer)
} {
// Get the layers that must be drawn
if (SelectedLayer.LayerType is FolderType)
private List<LayerModel> GetLayers() return SelectedLayer.GetLayers().ToList();
{ return new List<LayerModel> {SelectedLayer};
if (ShowAll) }
return SelectedProfile.GetLayers(); }
if (SelectedLayer == null)
return new List<LayerModel>(); public void Dispose()
{
lock (SelectedLayer) _keyboardPreviewCursor?.Dispose();
{ _loopManager.RenderCompleted -= LoopManagerOnRenderCompleted;
// Get the layers that must be drawn _deviceManager.OnKeyboardChanged -= DeviceManagerOnOnKeyboardChanged;
if (SelectedLayer.LayerType is FolderType) }
return SelectedLayer.GetLayers().ToList();
return new List<LayerModel> {SelectedLayer}; #endregion
} }
}
#endregion
}
} }