1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Finished CM support

Reimplemented task bar icon
This commit is contained in:
SpoinkyNL 2016-11-12 00:00:38 +01:00
parent 6f7e24611a
commit c172ec4c6a
17 changed files with 281 additions and 292 deletions

View File

@ -318,7 +318,7 @@
<Compile Include="DAL\ProfileProvider.cs" />
<Compile Include="DAL\SettingsProvider.cs" />
<Compile Include="DeviceProviders\CoolerMaster\MasterkeysProL.cs" />
<Compile Include="DeviceProviders\CoolerMaster\Utilities\CMSDK.cs" />
<Compile Include="DeviceProviders\CoolerMaster\Utilities\CmSdk.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairMice.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairHeadsets.cs" />
<Compile Include="DeviceProviders\Corsair\CorsairMousemats.cs" />
@ -611,7 +611,6 @@
<Compile Include="Modules\Overlays\VolumeDisplay\VolumeDisplayViewModel.cs" />
<Compile Include="ViewModels\Profiles\ProfileEditorViewModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="ViewModels\SystemTrayViewModel.cs" />
<Compile Include="ViewModels\WelcomeViewModel.cs" />
<Compile Include="Views\DebugView.xaml.cs">
<DependentUpon>DebugView.xaml</DependentUpon>
@ -687,6 +686,7 @@
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<None Include="Resources\Keyboards\masterkeys-pro-l.png" />
<Resource Include="Resources\Kottke Silkscreen License.txt" />
<None Include="Resources\lua-placeholder.lua" />
<None Include="NLog.xsd">

View File

@ -1,9 +1,10 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using Artemis.DeviceProviders.CoolerMaster.Utilities;
using Artemis.DeviceProviders.Logitech.Utilities;
using Artemis.Properties;
using Artemis.Utilities;
@ -11,6 +12,8 @@ namespace Artemis.DeviceProviders.CoolerMaster
{
public class MasterkeysProL : KeyboardProvider
{
private bool _hasControl;
public MasterkeysProL()
{
Name = "CM Masterkeys Pro L";
@ -22,76 +25,62 @@ namespace Artemis.DeviceProviders.CoolerMaster
Height = 6;
Width = 22;
// TODO
PreviewSettings = new PreviewSettings(665, 175, new Thickness(0, -15, 0, 0), Resources.blackwidow);
PreviewSettings = new PreviewSettings(670, 189, new Thickness(-2, -5, 0, 0), Resources.masterkeys_pro_l);
}
public override void Disable()
{
CmSdk.EnableLedControl(false);
if (_hasControl)
{
CmSdk.EnableLedControl(false);
Thread.Sleep(500);
}
_hasControl = false;
}
public override bool CanEnable()
{
return true;
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
// Doesn't seem reliable but better than nothing I suppose
return CmSdk.IsDevicePlug();
}
public override void Enable()
{
CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
_hasControl = true;
CmSdk.EnableLedControl(true);
}
public override void DrawBitmap(Bitmap bitmap)
{
// Resize the bitmap
using (var b = ImageUtilities.ResizeImage(bitmap, Width, Height))
{
// Create an empty matrix
var matrix = new COLOR_MATRIX {KeyColor = new KEY_COLOR[Height, Width]};
// Map the bytes to the matix
for (var x = 0; x < Width; x++)
{
for (var y = 0; y < Height; y++)
{
var color = b.GetPixel(x, y);
matrix.KeyColor[y, x] = new KEY_COLOR(color.R, color.G, color.B);
var c = b.GetPixel(x, y);
matrix.KeyColor[y, x] = new KEY_COLOR(c.R, c.G, c.B);
}
}
// Send the matrix to the keyboard
CmSdk.SetAllLedColor(matrix);
}
}
public override KeyMatch? GetKeyPosition(Keys keyCode)
{
return null;
}
private static byte[,,] BitmapToBytes(Bitmap bitmap)
{
BitmapData bitmapData =
bitmap.LockBits(new Rectangle(new System.Drawing.Point(), bitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
byte[] bitmapBytes;
var stride = bitmapData.Stride;
try
{
int byteCount = bitmapData.Stride * bitmap.Height;
bitmapBytes = new byte[byteCount];
Marshal.Copy(bitmapData.Scan0, bitmapBytes, 0, byteCount);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
byte[,,] result = new byte[3, bitmap.Width, bitmap.Height];
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < bitmap.Width; i++)
{
for (int j = 0; j < bitmap.Height; j++)
{
result[k, i, j] = bitmapBytes[j * stride + i * 3 + k];
}
}
}
return result;
return KeyMap.QwertyLayout.FirstOrDefault(k => k.KeyCode == keyCode);
}
}
}

View File

@ -2,7 +2,6 @@
namespace Artemis.DeviceProviders.CoolerMaster.Utilities
{
public struct KEY_COLOR
{
public byte r;
@ -17,12 +16,9 @@ namespace Artemis.DeviceProviders.CoolerMaster.Utilities
}
}
// set up/save the whole LED color structure
public struct COLOR_MATRIX
{
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 132)]
public KEY_COLOR[,] KeyColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 132)] public KEY_COLOR[,] KeyColor;
}
//Enumeration of device list
@ -45,15 +41,52 @@ namespace Artemis.DeviceProviders.CoolerMaster.Utilities
public static class CmSdk
{
/// <summary>
/// Sets the control device which all following actions are targetted to
/// </summary>
/// <param name="devIndex"></param>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern void SetControlDevice(DEVICE_INDEX devIndex);
/// <summary>
/// Obtain current device layout
/// </summary>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern LAYOUT_KEYBOARD GetDeviceLayout();
/// <summary>
/// Verify if the currently conrolled device is plugged in
/// </summary>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool IsDevicePlug();
/// <summary>
/// Enables led control on the currently controlled device
/// </summary>
/// <param name="bEnable"></param>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool EnableLedControl(bool bEnable);
/// <summary>
/// Sets the LED of the currently controlled device
/// </summary>
/// <param name="iRow"></param>
/// <param name="iColumn"></param>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SetLedColor(int iRow, int iColumn, byte r, byte g, byte b);
/// <summary>
/// Sets all LEDS using the given color matrix
/// </summary>
/// <param name="colorMatrix"></param>
/// <returns></returns>
[DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SetAllLedColor(COLOR_MATRIX colorMatrix);
}

View File

@ -2,6 +2,7 @@
using System.Threading;
using System.Windows;
using Artemis.DeviceProviders.Logitech.Utilities;
using Artemis.Utilities;
using Artemis.Utilities.DataReaders;
using Microsoft.Win32;

View File

@ -153,7 +153,7 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
{
if (b.Width > 21 || b.Height > 6)
b = ResizeImage(b, 21, 6);
var rect = new Rectangle(0, 0, b.Width, b.Height);
var bitmapData = b.LockBits(rect, ImageLockMode.ReadWrite, b.PixelFormat);
@ -202,10 +202,16 @@ namespace Artemis.DeviceProviders.Logitech.Utilities
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
// TODO: Make configurable
// Prevents light bleed
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
// Soft/semi-transparent keys
//graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);

View File

@ -10,19 +10,21 @@ namespace Artemis.DeviceProviders.Razer.Utilities
public static Custom BitmapColorArray(Bitmap b, int height, int width)
{
var keyboardGrid = Custom.Create();
if (b.Width > width || b.Height > height)
b = ImageUtilities.ResizeImage(b, width, height);
for (var y = 0; y < b.Height; y++)
// Resize the bitmap
using (b = ImageUtilities.ResizeImage(b, width, height))
{
// Map the bytes to the grid
for (var x = 0; x < b.Width; x++)
{
var pixel = b.GetPixel(x, y);
keyboardGrid[y, x] = new Color(pixel.R, pixel.G, pixel.B);
for (var y = 0; y < b.Height; y++)
{
var c = b.GetPixel(x, y);
keyboardGrid[y, x] = new Color(c.R, c.G, c.B);
}
}
}
return keyboardGrid;
return keyboardGrid;
}
}
}
}

View File

@ -15,7 +15,6 @@ namespace Artemis.InjectionModules
{
// ViewModels
Bind<ShellViewModel>().ToSelf().InSingletonScope();
Bind<SystemTrayViewModel>().ToSelf().InSingletonScope();
Bind<ProfileViewModel>().ToSelf();
Bind<ProfileEditorViewModel>().ToSelf();
Bind<DebugViewModel>().ToSelf().InSingletonScope();

View File

@ -73,7 +73,7 @@ namespace Artemis.Managers
public async void EnableKeyboard(KeyboardProvider keyboardProvider)
{
if (keyboardProvider == null)
throw new ArgumentNullException(nameof(keyboardProvider));
return;
if (ChangingKeyboard || (ActiveKeyboard?.Name == keyboardProvider.Name))
return;

View File

@ -177,6 +177,9 @@ namespace Artemis.Managers
{
public RenderFrame(KeyboardProvider keyboard)
{
if (keyboard == null)
return;
KeyboardBitmap = keyboard.KeyboardBitmap(4);
KeyboardBitmap.SetResolution(96, 96);
@ -222,10 +225,10 @@ namespace Artemis.Managers
public void Dispose()
{
KeyboardBitmap.Dispose();
MouseBitmap.Dispose();
HeadsetBitmap.Dispose();
GenericBitmap.Dispose();
KeyboardBitmap?.Dispose();
MouseBitmap?.Dispose();
HeadsetBitmap?.Dispose();
GenericBitmap?.Dispose();
}
}
}

View File

@ -328,6 +328,16 @@ namespace Artemis.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap masterkeys_pro_l {
get {
object obj = ResourceManager.GetObject("masterkeys_pro_l", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View File

@ -214,4 +214,7 @@
<data name="ambilight" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ambilight.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="masterkeys_pro_l" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Keyboards\masterkeys-pro-l.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View File

@ -40,8 +40,8 @@ namespace Artemis.Services
Execute.OnUIThread(() =>
{
window = Application.Current.Windows.OfType<MetroWindow>().FirstOrDefault(w => w.IsActive) ??
Application.Current.Windows.OfType<MetroWindow>().FirstOrDefault();
window = Application.Current.Windows.OfType<MetroWindow>()
.FirstOrDefault(w => w.IsActive && w.IsVisible);
});
return window;

View File

@ -1,9 +1,12 @@
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
using Point = System.Drawing.Point;
namespace Artemis.Utilities
{

View File

@ -56,7 +56,7 @@ namespace Artemis.Utilities
/// </summary>
/// <param name="dialogService">The dialog service to use for progress and result dialogs</param>
/// <returns></returns>
public static async Task CheckChangelog(MetroDialogService dialogService)
public static async void CheckChangelog(MetroDialogService dialogService)
{
var settings = SettingsProvider.Load<GeneralSettings>();
var currentVersion = Assembly.GetExecutingAssembly().GetName().Version;

View File

@ -1,11 +1,18 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Artemis.DAL;
using Artemis.Events;
using Artemis.Managers;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Artemis.ViewModels.Abstract;
using Artemis.ViewModels.Flyouts;
using Caliburn.Micro;
using Hardcodet.Wpf.TaskbarNotification;
using MahApps.Metro.Controls;
using Ninject;
@ -14,52 +21,130 @@ namespace Artemis.ViewModels
public sealed class ShellViewModel : Conductor<IScreen>.Collection.OneActive
{
private readonly IKernel _kernel;
private string _activeIcon;
private bool _checked;
private bool _enabled;
private string _toggleText;
private bool _exiting;
public ShellViewModel(IKernel kernel, MainManager mainManager, MetroDialogService metroDialogService,
FlyoutSettingsViewModel flyoutSettings)
{
_kernel = kernel;
MainManager = mainManager;
MetroDialogService = metroDialogService;
// Setup UI
DisplayName = "Artemis";
GeneralSettings = SettingsProvider.Load<GeneralSettings>();
Flyouts = new BindableCollection<FlyoutBaseViewModel>
{
flyoutSettings
};
MainManager.OnEnabledChangedEvent += (sender, args) => Enabled = args.Enabled;
MainManager = mainManager;
MetroDialogService = metroDialogService;
MainManager.EnableProgram();
// This gets updated automatically but during startup lets quickly preset it
Enabled = GeneralSettings.Suspended;
}
public SystemTrayViewModel SystemTrayViewModel { get; set; }
protected override void OnViewReady(object view)
{
base.OnViewReady(view);
Task.Run(() => StartupHide());
}
private void StartupHide()
{
// TODO: This is probably an awful idea. I can't reliably hook into the view being ready to be hidden
Thread.Sleep(500);
if (GeneralSettings.ShowOnStartup)
ShowWindow();
else
HideWindow();
if (!GeneralSettings.Suspended)
MainManager.EnableProgram();
}
public Mutex Mutex { get; set; }
public MainManager MainManager { get; set; }
public MetroDialogService MetroDialogService { get; set; }
public IObservableCollection<FlyoutBaseViewModel> Flyouts { get; set; }
public GeneralSettings GeneralSettings { get; set; }
private MetroWindow Window => (MetroWindow) GetView();
public bool CanShowWindow => Window != null && (Window != null || !Window.IsVisible);
public bool CanHideWindow => Window != null && Window.IsVisible;
public bool Enabled
{
get { return _enabled; }
set
{
if (value == _enabled) return;
_enabled = value;
ToggleText = _enabled ? "Disable Artemis" : "Enable Artemis";
ActiveIcon = _enabled ? "../Resources/logo.ico" : "../Resources/logo-disabled.ico";
NotifyOfPropertyChange(() => Enabled);
}
}
public string ActiveIcon
{
get { return _activeIcon; }
set
{
_activeIcon = value;
NotifyOfPropertyChange();
}
}
public string ToggleText
{
get { return _toggleText; }
set
{
if (value == _toggleText) return;
_toggleText = value;
NotifyOfPropertyChange(() => ToggleText);
}
}
public override void CanClose(Action<bool> callback)
{
if (Window.IsVisible)
if (CanHideWindow)
HideWindow();
else
else if (!_exiting)
ShowWindow();
// ShellView is a strong and independent view who won't let herself get closed by the likes of anyone!
callback(false);
// Only close if ExitApplication was called
callback(_exiting);
}
public bool CanShowWindow => !Window.IsVisible;
public bool CanHideWindow => Window.IsVisible;
public void ShowWindow()
{
if (!Window.IsVisible)
Window.Show();
if (CanShowWindow)
Window?.Dispatcher.Invoke(() =>
{
Window.Show();
Window.Activate();
});
GeneralSettings.ApplyTheme();
// Show certain dialogs if needed
CheckKeyboardState();
CheckDuplicateInstances();
Updater.CheckChangelog(MetroDialogService);
var vms = _kernel.GetAll<BaseViewModel>().ToList();
Items.Clear();
Items.AddRange(vms);
ActivateItem(vms.FirstOrDefault());
NotifyOfPropertyChange(() => CanShowWindow);
NotifyOfPropertyChange(() => CanHideWindow);
@ -67,26 +152,44 @@ namespace Artemis.ViewModels
public void HideWindow()
{
if (Window.IsVisible)
Window.Hide();
if (CanHideWindow)
Window?.Dispatcher.Invoke(() => { Window.Hide(); });
Items.Clear();
NotifyOfPropertyChange(() => CanShowWindow);
NotifyOfPropertyChange(() => CanHideWindow);
// Force a GC since the UI releases a lot of resources
GC.Collect();
}
protected override void OnActivate()
public void ToggleEnabled()
{
base.OnActivate();
Items.Clear();
var vms = _kernel.GetAll<BaseViewModel>();
Items.AddRange(vms);
if (Enabled)
MainManager.DisableProgram();
else
MainManager.EnableProgram();
}
protected override void OnDeactivate(bool close)
public void ExitApplication()
{
base.OnDeactivate(close);
Items.Clear();
MainManager.Dispose();
try
{
var icon = (TaskbarIcon) Window.FindResource("SystemTrayIcon");
icon.Dispose();
}
catch (Exception)
{
//ignored
}
_exiting = true;
// TODO: CoolerMaster SDK is freezing Artemis on shutdown, dunno what to do about it yet
System.Diagnostics.Process.GetCurrentProcess().Kill();
// Application.Current.Shutdown();
}
public void Settings()
@ -98,5 +201,42 @@ namespace Artemis.ViewModels
{
Flyouts.First().IsOpen = false;
}
private async void CheckKeyboardState()
{
var dialog = await MetroDialogService.ShowProgressDialog("Enabling keyboard",
"Artemis is still busy trying to enable your last used keyboard. " +
"Please wait while the process completes");
dialog.SetIndeterminate();
while (MainManager.DeviceManager.ChangingKeyboard)
await Task.Delay(10);
try
{
await dialog.CloseAsync();
}
catch (InvalidOperationException)
{
// Occurs when window is closed again, can't find a proper check for this
}
}
private void CheckDuplicateInstances()
{
if (_checked)
return;
_checked = true;
bool aIsNewInstance;
Mutex = new Mutex(true, "ArtemisMutex", out aIsNewInstance);
if (aIsNewInstance)
return;
MetroDialogService.ShowMessageBox("Multiple instances found",
"It looks like there are multiple running instances of Artemis. " +
"This can cause issues, especially with CS:GO and Dota2. " +
"If so, please make sure Artemis isn't already running");
}
}
}

View File

@ -1,200 +0,0 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Artemis.DAL;
using Artemis.Events;
using Artemis.Managers;
using Artemis.Services;
using Artemis.Settings;
using Artemis.Utilities;
using Caliburn.Micro;
namespace Artemis.ViewModels
{
public class SystemTrayViewModel : Screen
{
private readonly WindowService _windowService;
private ShellViewModel _shellViewModel;
private string _activeIcon;
private bool _checked;
private bool _enabled;
private string _toggleText;
public SystemTrayViewModel(WindowService windowService, MetroDialogService dialogService, MainManager mainManager)
{
_windowService = windowService;
DialogService = dialogService;
MainManager = mainManager;
MainManager.EnableProgram();
MainManager.OnEnabledChangedEvent += MainManagerOnOnEnabledChangedEvent;
var generalSettings = SettingsProvider.Load<GeneralSettings>();
Enabled = !generalSettings.Suspended;
if (generalSettings.ShowOnStartup)
ShowWindow();
}
public MetroDialogService DialogService { get; set; }
public MainManager MainManager { get; set; }
public bool CanShowWindow
{
get
{
if (_shellViewModel == null)
return true;
return !_shellViewModel.IsActive;
}
}
public bool CanHideWindow => (_shellViewModel?.IsActive == true) && !MainManager.DeviceManager.ChangingKeyboard;
public bool CanToggleEnabled => !MainManager.DeviceManager.ChangingKeyboard;
public bool Enabled
{
get { return _enabled; }
set
{
if (value == _enabled) return;
_enabled = value;
ToggleText = _enabled ? "Disable Artemis" : "Enable Artemis";
ActiveIcon = _enabled ? "../Resources/logo.ico" : "../Resources/logo-disabled.ico";
NotifyOfPropertyChange(() => Enabled);
}
}
public string ActiveIcon
{
get { return _activeIcon; }
set
{
_activeIcon = value;
NotifyOfPropertyChange();
}
}
public string ToggleText
{
get { return _toggleText; }
set
{
if (value == _toggleText) return;
_toggleText = value;
NotifyOfPropertyChange(() => ToggleText);
}
}
public Mutex Mutex { get; set; }
private void MainManagerOnOnEnabledChangedEvent(object sender, EnabledChangedEventArgs e)
{
Enabled = e.Enabled;
}
public void ToggleEnabled()
{
if (Enabled)
MainManager.DisableProgram();
else
MainManager.EnableProgram();
}
protected override void OnActivate()
{
base.OnActivate();
NotifyOfPropertyChange(() => CanShowWindow);
NotifyOfPropertyChange(() => CanHideWindow);
}
public void ShowWindow()
{
if (!CanShowWindow)
return;
// manually show the next window view-model
_shellViewModel = _windowService.ShowWindow<ShellViewModel>();
NotifyOfPropertyChange(() => CanShowWindow);
NotifyOfPropertyChange(() => CanHideWindow);
SettingsProvider.Load<GeneralSettings>().ApplyTheme();
// Show certain dialogs if needed
CheckKeyboardState();
CheckDuplicateInstances();
Updater.CheckChangelog(DialogService);
}
private void CheckDuplicateInstances()
{
if (_checked)
return;
_checked = true;
bool aIsNewInstance;
Mutex = new Mutex(true, "ArtemisMutex", out aIsNewInstance);
if (aIsNewInstance)
return;
DialogService.ShowMessageBox("Multiple instances found",
"It looks like there are multiple running instances of Artemis. " +
"This can cause issues, especially with CS:GO and Dota2. " +
"If so, please make sure Artemis isn't already running");
}
private async void CheckKeyboardState()
{
while (!_shellViewModel.IsActive)
await Task.Delay(200);
NotifyOfPropertyChange(() => CanHideWindow);
NotifyOfPropertyChange(() => CanToggleEnabled);
var dialog = await DialogService.ShowProgressDialog("Enabling keyboard",
"Artemis is still busy trying to enable your last used keyboard. " +
"Please wait while the process completes");
dialog.SetIndeterminate();
while (MainManager.DeviceManager.ChangingKeyboard)
await Task.Delay(10);
NotifyOfPropertyChange(() => CanHideWindow);
NotifyOfPropertyChange(() => CanToggleEnabled);
try
{
await dialog.CloseAsync();
}
catch (InvalidOperationException)
{
// Occurs when window is closed again, can't find a proper check for this
}
}
public void HideWindow()
{
if (!CanHideWindow)
return;
_shellViewModel.TryClose();
NotifyOfPropertyChange(() => CanShowWindow);
NotifyOfPropertyChange(() => CanHideWindow);
// Force a GC since the UI releases a lot of resources
GC.Collect();
}
public void ExitApplication()
{
MainManager.Dispose();
Application.Current.Shutdown();
}
}
}