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

Devices no longer dispose the bitmap they are rendering since this is done at the end of the frame.

Fixed Generic type not applying it's brush property, this fixes #224
Added a display of what is drawn to each device to the debug window
This commit is contained in:
SpoinkyNL 2016-12-15 14:21:05 +01:00
parent 9e7ddfc51c
commit 60b89cc88d
18 changed files with 260 additions and 115 deletions

View File

@ -46,20 +46,19 @@ namespace Artemis.DeviceProviders.Corsair
var leds = CueSDK.HeadsetSDK.Leds.Count(); var leds = CueSDK.HeadsetSDK.Leds.Count();
var step = (double) bitmap.Width/leds; var step = (double) bitmap.Width/leds;
using (bitmap)
{
var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.HeadsetSDK.Leds)
{
var col = ledIndex == 0
? bitmap.GetPixel(0, 0)
: bitmap.GetPixel((int) ((ledIndex + 1)*step - 1), (int) ((ledIndex + 1)*step - 1));
corsairLed.Color = col; var ledIndex = 0;
ledIndex++; // Color each LED according to one of the pixels
} foreach (var corsairLed in CueSDK.HeadsetSDK.Leds)
{
var col = ledIndex == 0
? bitmap.GetPixel(0, 0)
: bitmap.GetPixel((int) ((ledIndex + 1)*step - 1), (int) ((ledIndex + 1)*step - 1));
corsairLed.Color = col;
ledIndex++;
} }
CueSDK.HeadsetSDK.Update(); CueSDK.HeadsetSDK.Update();
} }

View File

@ -46,20 +46,19 @@ namespace Artemis.DeviceProviders.Corsair
var leds = CueSDK.MouseSDK.Leds.Count(); var leds = CueSDK.MouseSDK.Leds.Count();
var step = (double) bitmap.Width/leds; var step = (double) bitmap.Width/leds;
using (bitmap)
{
var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.MouseSDK.Leds)
{
var col = ledIndex == 0
? bitmap.GetPixel(0, 0)
: bitmap.GetPixel((int) ((ledIndex + 1)*step - 1), (int) ((ledIndex + 1)*step - 1));
corsairLed.Color = col; var ledIndex = 0;
ledIndex++; // Color each LED according to one of the pixels
} foreach (var corsairLed in CueSDK.MouseSDK.Leds)
{
var col = ledIndex == 0
? bitmap.GetPixel(0, 0)
: bitmap.GetPixel((int) ((ledIndex + 1)*step - 1), (int) ((ledIndex + 1)*step - 1));
corsairLed.Color = col;
ledIndex++;
} }
CueSDK.MouseSDK.Update(); CueSDK.MouseSDK.Update();
} }

View File

@ -48,39 +48,36 @@ namespace Artemis.DeviceProviders.Corsair
var xStep = (double) bitmap.Width/6; var xStep = (double) bitmap.Width/6;
// This approach will break if any mousemats with different LED amounts are released, for now it will do. // This approach will break if any mousemats with different LED amounts are released, for now it will do.
using (bitmap) var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.MousematSDK.Leds.OrderBy(l => l.ToString()))
{ {
var ledIndex = 0; Color col;
// Color each LED according to one of the pixels // Left side
foreach (var corsairLed in CueSDK.MousematSDK.Leds.OrderBy(l => l.ToString())) if (ledIndex < 5)
{ {
Color col; col = ledIndex == 0
// Left side ? bitmap.GetPixel(0, (int) (ledIndex*yStep))
if (ledIndex < 5) : bitmap.GetPixel(0, (int) (ledIndex*yStep) - 1);
{
col = ledIndex == 0
? bitmap.GetPixel(0, (int) (ledIndex*yStep))
: bitmap.GetPixel(0, (int) (ledIndex*yStep) - 1);
}
// Bottom
else if (ledIndex < 10)
{
// Start at index 1 because the corner belongs to the left side
var zoneIndex = ledIndex - 4;
col = bitmap.GetPixel((int) (zoneIndex*xStep), bitmap.Height - 1);
}
// Right side
else
{
var zoneIndex = ledIndex - 10;
col = zoneIndex == 4
? bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - (int) (zoneIndex*yStep))
: bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - 1 - (int) (zoneIndex*yStep));
}
corsairLed.Color = col;
ledIndex++;
} }
// Bottom
else if (ledIndex < 10)
{
// Start at index 1 because the corner belongs to the left side
var zoneIndex = ledIndex - 4;
col = bitmap.GetPixel((int) (zoneIndex*xStep), bitmap.Height - 1);
}
// Right side
else
{
var zoneIndex = ledIndex - 10;
col = zoneIndex == 4
? bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - (int) (zoneIndex*yStep))
: bitmap.GetPixel(bitmap.Height - 1, bitmap.Height - 1 - (int) (zoneIndex*yStep));
}
corsairLed.Color = col;
ledIndex++;
} }
CueSDK.MousematSDK.Update(); CueSDK.MousematSDK.Update();
} }

View File

@ -25,12 +25,9 @@ namespace Artemis.DeviceProviders.Logitech
if (!CanUse || bitmap == null) if (!CanUse || bitmap == null)
return; return;
using (bitmap) var col = bitmap.GetPixel(bitmap.Width/2, bitmap.Height/2);
{ LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_RGB);
var col = bitmap.GetPixel(bitmap.Width/2, bitmap.Height/2); LogitechGSDK.LogiLedSetLighting((int) (col.R/2.55), (int) (col.G/2.55), (int) (col.B/2.55));
LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_RGB);
LogitechGSDK.LogiLedSetLighting((int) (col.R/2.55), (int) (col.G/2.55), (int) (col.B/2.55));
}
} }
public override bool TryEnable() public override bool TryEnable()

View File

@ -4,9 +4,9 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers; using System.Timers;
using System.Windows;
using System.Windows.Threading;
using Artemis.DeviceProviders; using Artemis.DeviceProviders;
using Artemis.ViewModels;
using Caliburn.Micro;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
@ -17,17 +17,20 @@ namespace Artemis.Managers
/// </summary> /// </summary>
public class LoopManager : IDisposable public class LoopManager : IDisposable
{ {
private readonly DebugViewModel _debugViewModel;
private readonly DeviceManager _deviceManager; private readonly DeviceManager _deviceManager;
private readonly EffectManager _effectManager; private readonly EffectManager _effectManager;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly Timer _loopTimer; private readonly Timer _loopTimer;
private bool _canShowException; private bool _canShowException;
public LoopManager(ILogger logger, EffectManager effectManager, DeviceManager deviceManager) public LoopManager(ILogger logger, EffectManager effectManager, DeviceManager deviceManager,
DebugViewModel debugViewModel)
{ {
_logger = logger; _logger = logger;
_effectManager = effectManager; _effectManager = effectManager;
_deviceManager = deviceManager; _deviceManager = deviceManager;
_debugViewModel = debugViewModel;
_canShowException = true; _canShowException = true;
// Setup timers // Setup timers
@ -38,6 +41,19 @@ namespace Artemis.Managers
_logger.Info("Intialized LoopManager"); _logger.Info("Intialized LoopManager");
} }
public DebugViewModel DebugViewModel { get; set; }
/// <summary>
/// Gets whether the loop is running
/// </summary>
public bool Running { get; private set; }
public void Dispose()
{
_loopTimer.Stop();
_loopTimer.Dispose();
}
private void LoopTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs) private void LoopTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs)
{ {
try try
@ -48,7 +64,7 @@ namespace Artemis.Managers
{ {
if (_canShowException) if (_canShowException)
{ {
Caliburn.Micro.Execute.OnUIThread(delegate Execute.OnUIThread(delegate
{ {
_canShowException = false; _canShowException = false;
_loopTimer.Stop(); _loopTimer.Stop();
@ -59,17 +75,6 @@ namespace Artemis.Managers
} }
} }
/// <summary>
/// Gets whether the loop is running
/// </summary>
public bool Running { get; private set; }
public void Dispose()
{
_loopTimer.Stop();
_loopTimer.Dispose();
}
public Task StartAsync() public Task StartAsync()
{ {
return Task.Run(() => Start()); return Task.Run(() => Start());
@ -185,6 +190,8 @@ namespace Artemis.Managers
foreach (var mousemat in mousemats) foreach (var mousemat in mousemats)
mousemat.UpdateDevice(frame.MousematBitmap); mousemat.UpdateDevice(frame.MousematBitmap);
_debugViewModel.DrawFrame(frame);
OnRenderCompleted(); OnRenderCompleted();
} }
} }
@ -254,6 +261,7 @@ namespace Artemis.Managers
MouseBitmap?.Dispose(); MouseBitmap?.Dispose();
HeadsetBitmap?.Dispose(); HeadsetBitmap?.Dispose();
GenericBitmap?.Dispose(); GenericBitmap?.Dispose();
MousematBitmap?.Dispose();
} }
} }
} }

View File

@ -36,12 +36,6 @@ namespace Artemis.Models
DeviceManager.OnKeyboardChangedEvent += DeviceManagerOnOnKeyboardChangedEvent; DeviceManager.OnKeyboardChangedEvent += DeviceManagerOnOnKeyboardChangedEvent;
} }
private void DeviceManagerOnOnKeyboardChangedEvent(object sender, KeyboardChangedEventArgs args)
{
if (!string.IsNullOrEmpty(Settings?.LastProfile))
Profile = ProfileProvider.GetProfile(DeviceManager.ActiveKeyboard, this, Settings.LastProfile);
}
public bool Initialized { get; set; } public bool Initialized { get; set; }
public DeviceManager DeviceManager { get; set; } public DeviceManager DeviceManager { get; set; }
public EffectSettings Settings { get; set; } public EffectSettings Settings { get; set; }
@ -59,6 +53,12 @@ namespace Artemis.Models
Profile?.Deactivate(); Profile?.Deactivate();
} }
private void DeviceManagerOnOnKeyboardChangedEvent(object sender, KeyboardChangedEventArgs args)
{
if (!string.IsNullOrEmpty(Settings?.LastProfile))
Profile = ProfileProvider.GetProfile(DeviceManager.ActiveKeyboard, this, Settings.LastProfile);
}
// Called on creation // Called on creation
public abstract void Enable(); public abstract void Enable();
@ -89,15 +89,15 @@ namespace Artemis.Models
var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); var keyboardRect = DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale);
using (var g = Graphics.FromImage(frame.KeyboardBitmap)) using (var g = Graphics.FromImage(frame.KeyboardBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard),
DataModel, keyboardRect, false, true, "keyboard"); DataModel, keyboardRect, false, true, "keyboard");
} }
// Render mice layer-by-layer // Render mice layer-by-layer
var devRec = new Rect(0, 0, 40, 40); var devRec = new Rect(0, 0, 40, 40);
using (var g = Graphics.FromImage(frame.MouseBitmap)) using (var g = Graphics.FromImage(frame.MouseBitmap))
{ {
Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel, Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse),
devRec, false, true, "mouse"); DataModel, devRec, false, true, "mouse");
} }
// Render headsets layer-by-layer // Render headsets layer-by-layer
using (var g = Graphics.FromImage(frame.HeadsetBitmap)) using (var g = Graphics.FromImage(frame.HeadsetBitmap))

View File

@ -13,9 +13,9 @@ namespace Artemis.Profiles.Layers.Types.Folder
public class FolderType : ILayerType public class FolderType : ILayerType
{ {
public string Name => "Folder"; public string Name => "Folder";
public bool ShowInEdtor { get; } = false; public bool ShowInEdtor => false;
// FolderType pretents to be a keyboard so it's children get drawn // FolderType pretents to be a keyboard so it's children get drawn
public DrawType DrawType { get; } = DrawType.Keyboard; public DrawType DrawType => DrawType.Keyboard;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -1,16 +1,13 @@
using System.Collections.Generic; using System.Linq;
using System.Linq;
using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Abstract;
using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Interfaces;
using Artemis.ViewModels.Profiles; using Artemis.ViewModels.Profiles;
using Caliburn.Micro; using Caliburn.Micro;
using ColorBox;
namespace Artemis.Profiles.Layers.Types.Generic namespace Artemis.Profiles.Layers.Types.Generic
{ {
public class GenericPropertiesViewModel : LayerPropertiesViewModel public class GenericPropertiesViewModel : LayerPropertiesViewModel
{ {
private IEnumerable<BrushTypes> _availableBrushTypes;
private ILayerAnimation _selectedLayerAnimation; private ILayerAnimation _selectedLayerAnimation;
public GenericPropertiesViewModel(LayerEditorViewModel editorVm) : base(editorVm) public GenericPropertiesViewModel(LayerEditorViewModel editorVm) : base(editorVm)

View File

@ -15,17 +15,15 @@ namespace Artemis.Profiles.Layers.Types.Generic
public class GenericType : ILayerType public class GenericType : ILayerType
{ {
public string Name => "Generic (Logitech)"; public string Name => "Generic (Logitech)";
public bool ShowInEdtor { get; } = false; public bool ShowInEdtor => false;
public DrawType DrawType { get; } = DrawType.Generic; public DrawType DrawType => DrawType.Generic;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {
var thumbnailRect = new Rect(0, 0, 18, 18); var thumbnailRect = new Rect(0, 0, 18, 18);
var visual = new DrawingVisual(); var visual = new DrawingVisual();
using (var c = visual.RenderOpen()) using (var c = visual.RenderOpen())
{ c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.headset), thumbnailRect);
c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.generic), thumbnailRect);
}
var image = new DrawingImage(visual.Drawing); var image = new DrawingImage(visual.Drawing);
return image; return image;
@ -61,7 +59,7 @@ namespace Artemis.Profiles.Layers.Types.Generic
layerModel.Properties.Y = 0; layerModel.Properties.Y = 0;
layerModel.Properties.Contain = true; layerModel.Properties.Contain = true;
layerModel.ApplyProperties(false); layerModel.ApplyProperties(true);
if (isPreview || dataModel == null) if (isPreview || dataModel == null)
return; return;

View File

@ -15,8 +15,8 @@ namespace Artemis.Profiles.Layers.Types.Headset
public class HeadsetType : ILayerType public class HeadsetType : ILayerType
{ {
public string Name => "Headset"; public string Name => "Headset";
public bool ShowInEdtor { get; } = false; public bool ShowInEdtor => false;
public DrawType DrawType { get; } = DrawType.Headset; public DrawType DrawType => DrawType.Headset;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -35,8 +35,8 @@ namespace Artemis.Profiles.Layers.Types.KeyPress
public string Name => "Keyboard - Key press"; public string Name => "Keyboard - Key press";
public bool ShowInEdtor { get; } = false; public bool ShowInEdtor => false;
public DrawType DrawType { get; } = DrawType.Keyboard; public DrawType DrawType => DrawType.Keyboard;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -12,8 +12,8 @@ namespace Artemis.Profiles.Layers.Types.Keyboard
public class KeyboardType : ILayerType public class KeyboardType : ILayerType
{ {
public string Name => "Keyboard"; public string Name => "Keyboard";
public bool ShowInEdtor { get; } = true; public bool ShowInEdtor => true;
public DrawType DrawType { get; } = DrawType.Keyboard; public DrawType DrawType => DrawType.Keyboard;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -16,8 +16,8 @@ namespace Artemis.Profiles.Layers.Types.KeyboardGif
internal class KeyboardGifType : ILayerType internal class KeyboardGifType : ILayerType
{ {
public string Name => "Keyboard - GIF"; public string Name => "Keyboard - GIF";
public bool ShowInEdtor { get; } = true; public bool ShowInEdtor => true;
public DrawType DrawType { get; } = DrawType.Keyboard; public DrawType DrawType => DrawType.Keyboard;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -15,8 +15,8 @@ namespace Artemis.Profiles.Layers.Types.Mouse
public class MouseType : ILayerType public class MouseType : ILayerType
{ {
public string Name => "Mouse"; public string Name => "Mouse";
public bool ShowInEdtor { get; } = false; public bool ShowInEdtor => false;
public DrawType DrawType { get; } = DrawType.Mouse; public DrawType DrawType => DrawType.Mouse;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -15,8 +15,8 @@ namespace Artemis.Profiles.Layers.Types.Mousemat
public class MousematType : ILayerType public class MousematType : ILayerType
{ {
public string Name => "Mousemat"; public string Name => "Mousemat";
public bool ShowInEdtor { get; } = false; public bool ShowInEdtor => false;
public DrawType DrawType { get; } = DrawType.Mousemat; public DrawType DrawType => DrawType.Mousemat;
public ImageSource DrawThumbnail(LayerModel layer) public ImageSource DrawThumbnail(LayerModel layer)
{ {

View File

@ -90,5 +90,21 @@ namespace Artemis.Utilities
bitmap.Render(iconImage); bitmap.Render(iconImage);
return bitmap; return bitmap;
} }
public static DrawingImage BitmapToDrawingImage(Bitmap b, Rect rect)
{
if (b == null)
return new DrawingImage();
var visual = new DrawingVisual();
using (var c = visual.RenderOpen())
{
c.DrawImage(BitmapToBitmapImage(b), rect);
}
var image = new DrawingImage(visual.Drawing);
image.Freeze();
return image;
}
} }
} }

View File

@ -3,13 +3,28 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using Artemis.Managers;
using Artemis.Utilities;
using Caliburn.Micro; using Caliburn.Micro;
using Action = System.Action;
namespace Artemis.ViewModels namespace Artemis.ViewModels
{ {
public class DebugViewModel : Screen public class DebugViewModel : Screen
{ {
private readonly DeviceManager _deviceManager;
private DrawingImage _razerDisplay; private DrawingImage _razerDisplay;
private DrawingImage _keyboard;
private DrawingImage _mouse;
private DrawingImage _headset;
private DrawingImage _mousemat;
private DrawingImage _generic;
public DebugViewModel(DeviceManager deviceManager)
{
_deviceManager = deviceManager;
}
public DrawingImage RazerDisplay public DrawingImage RazerDisplay
{ {
@ -22,6 +37,62 @@ namespace Artemis.ViewModels
} }
} }
public DrawingImage Keyboard
{
get { return _keyboard; }
set
{
if (Equals(value, _keyboard)) return;
_keyboard = value;
NotifyOfPropertyChange(() => Keyboard);
}
}
public DrawingImage Mouse
{
get { return _mouse; }
set
{
if (Equals(value, _mouse)) return;
_mouse = value;
NotifyOfPropertyChange(() => Mouse);
}
}
public DrawingImage Headset
{
get { return _headset; }
set
{
if (Equals(value, _headset)) return;
_headset = value;
NotifyOfPropertyChange(() => Headset);
}
}
public DrawingImage Mousemat
{
get { return _mousemat; }
set
{
if (Equals(value, _mousemat)) return;
_mousemat = value;
NotifyOfPropertyChange(() => Mousemat);
}
}
public DrawingImage Generic
{
get { return _generic; }
set
{
if (Equals(value, _generic)) return;
_generic = value;
NotifyOfPropertyChange(() => Generic);
}
}
public void OpenLog() public void OpenLog()
{ {
// Get the logging directory // Get the logging directory
@ -52,5 +123,24 @@ namespace Artemis.ViewModels
drawnDisplay.Freeze(); drawnDisplay.Freeze();
RazerDisplay = drawnDisplay; RazerDisplay = drawnDisplay;
} }
public void DrawFrame(RenderFrame frame)
{
// No point updating the display if the view isn't visible
if (!IsActive)
return;
// Only update keyboard if there is an active keyboard
if (_deviceManager.ActiveKeyboard != null)
{
var rect = _deviceManager.ActiveKeyboard.KeyboardRectangle(1);
Keyboard = ImageUtilities.BitmapToDrawingImage(frame.KeyboardBitmap, rect);
}
Mouse = ImageUtilities.BitmapToDrawingImage(frame.MouseBitmap, new Rect(0, 0, 10, 10));
Headset = ImageUtilities.BitmapToDrawingImage(frame.HeadsetBitmap, new Rect(0, 0, 10, 10));
Mousemat = ImageUtilities.BitmapToDrawingImage(frame.MousematBitmap, new Rect(0, 0, 10, 10));
Generic = ImageUtilities.BitmapToDrawingImage(frame.GenericBitmap, new Rect(0, 0, 10, 10));
}
} }
} }

View File

@ -12,27 +12,71 @@
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition /> <ColumnDefinition />
<ColumnDefinition /> <ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="40" /> <RowDefinition Height="32" />
<RowDefinition Height="80" />
<RowDefinition Height="32" />
<RowDefinition Height="80" /> <RowDefinition Height="80" />
<RowDefinition Height="40" /> <RowDefinition Height="40" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Keyboard output -->
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" FontSize="16" Content="Keyboard" HorizontalAlignment="Center" />
<Border Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Height="75" Width="300" HorizontalAlignment="Center"
VerticalAlignment="Top" BorderThickness="1" BorderBrush="{StaticResource GrayBrush7}"
SnapsToDevicePixels="True">
<Image Source="{Binding Path=Keyboard}" />
</Border>
<!-- Razer output --> <!-- Razer output -->
<Label Grid.Row="0" Grid.Column="0" FontSize="20" Content="Razer display" /> <Label Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="2" FontSize="16" Content="Razer SDK feed" HorizontalAlignment="Center" />
<Border Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Height="75" Width="300" HorizontalAlignment="Left" <Border Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Height="75" Width="300" HorizontalAlignment="Center"
VerticalAlignment="Top" BorderThickness="1" BorderBrush="{StaticResource GrayBrush7}" VerticalAlignment="Top" BorderThickness="1" BorderBrush="{StaticResource GrayBrush7}"
SnapsToDevicePixels="True"> SnapsToDevicePixels="True">
<Image Source="{Binding Path=RazerDisplay}" /> <Image Source="{Binding Path=RazerDisplay}" />
</Border> </Border>
<!-- Mouse output -->
<Label Grid.Row="2" Grid.Column="0" FontSize="16" Content="Mouse" HorizontalAlignment="Center" />
<Border Grid.Row="3" Grid.Column="0" Height="75" Width="75" HorizontalAlignment="Center"
VerticalAlignment="Top" BorderThickness="1" BorderBrush="{StaticResource GrayBrush7}"
SnapsToDevicePixels="True">
<Image Source="{Binding Path=Mouse}" />
</Border>
<!-- Headset output -->
<Label Grid.Row="2" Grid.Column="1" FontSize="16" Content="Headset" HorizontalAlignment="Center" />
<Border Grid.Row="3" Grid.Column="1" Height="75" Width="75" HorizontalAlignment="Center"
VerticalAlignment="Top" BorderThickness="1" BorderBrush="{StaticResource GrayBrush7}"
SnapsToDevicePixels="True">
<Image Source="{Binding Path=Headset}" />
</Border>
<!-- Mousemat output -->
<Label Grid.Row="2" Grid.Column="2" FontSize="16" Content="Mousemat" HorizontalAlignment="Center" />
<Border Grid.Row="3" Grid.Column="2" Height="75" Width="75" HorizontalAlignment="Center"
VerticalAlignment="Top" BorderThickness="1" BorderBrush="{StaticResource GrayBrush7}"
SnapsToDevicePixels="True">
<Image Source="{Binding Path=Mousemat}" />
</Border>
<!-- Generic output -->
<Label Grid.Row="2" Grid.Column="3" FontSize="16" Content="Generic" HorizontalAlignment="Center" />
<Border Grid.Row="3" Grid.Column="3" Height="75" Width="75" HorizontalAlignment="Center"
VerticalAlignment="Top" BorderThickness="1" BorderBrush="{StaticResource GrayBrush7}"
SnapsToDevicePixels="True">
<Image Source="{Binding Path=Generic}" />
</Border>
<!-- Log --> <!-- Log -->
<Label Grid.Row="2" Grid.Column="0" FontSize="20" Content="Log" /> <Label Grid.Row="4" Grid.Column="0" FontSize="20" Content="Log" />
<Button x:Name="OpenLog" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right" <Button x:Name="OpenLog" Grid.Row="4" Grid.Column="3" HorizontalAlignment="Right"
Style="{DynamicResource SquareButtonStyle}" Content="Open log file" VerticalAlignment="Center" /> Style="{DynamicResource SquareButtonStyle}" Content="Open log file" VerticalAlignment="Center" />
<Border Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" BorderThickness="1" <Border Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="4" BorderThickness="1"
BorderBrush="{StaticResource GrayBrush7}" SnapsToDevicePixels="True"> BorderBrush="{StaticResource GrayBrush7}" SnapsToDevicePixels="True">
<log:LoggingControl /> <log:LoggingControl />
</Border> </Border>