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

Implemented layer LED assignment

Added a centralised ProfileEditorSurface for communication between VMs
Prefixed Surface, Device and Led with Artemis to differentiate them better
This commit is contained in:
Robert 2019-11-29 17:37:22 +01:00
parent 8a596f1426
commit f32edcf502
50 changed files with 556 additions and 662 deletions

View File

@ -161,9 +161,9 @@
<Compile Include="Extensions\RgbRectangleExtensions.cs" /> <Compile Include="Extensions\RgbRectangleExtensions.cs" />
<Compile Include="Extensions\TypeExtensions.cs" /> <Compile Include="Extensions\TypeExtensions.cs" />
<Compile Include="Models\DataModelDescription.cs" /> <Compile Include="Models\DataModelDescription.cs" />
<Compile Include="Models\Surface\DeviceLed.cs" /> <Compile Include="Models\Surface\ArtemisLed.cs" />
<Compile Include="Models\Surface\Surface.cs" /> <Compile Include="Models\Surface\ArtemisSurface.cs" />
<Compile Include="Models\Surface\Device.cs" /> <Compile Include="Models\Surface\ArtemisDevice.cs" />
<Compile Include="Ninject\LoggerProvider.cs" /> <Compile Include="Ninject\LoggerProvider.cs" />
<Compile Include="Ninject\PluginSettingsProvider.cs" /> <Compile Include="Ninject\PluginSettingsProvider.cs" />
<Compile Include="Ninject\SettingsServiceProvider.cs" /> <Compile Include="Ninject\SettingsServiceProvider.cs" />
@ -216,9 +216,7 @@
<Name>Artemis.Storage</Name> <Name>Artemis.Storage</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup />
<Folder Include="ProfileElements\Interfaces\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Fody.6.0.5\build\Fody.targets" Condition="Exists('..\packages\Fody.6.0.5\build\Fody.targets')" /> <Import Project="..\packages\Fody.6.0.5\build\Fody.targets" Condition="Exists('..\packages\Fody.6.0.5\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -5,11 +5,11 @@ namespace Artemis.Core.Events
{ {
public class SurfaceConfigurationEventArgs : EventArgs public class SurfaceConfigurationEventArgs : EventArgs
{ {
public SurfaceConfigurationEventArgs(Surface surface) public SurfaceConfigurationEventArgs(ArtemisSurface surface)
{ {
Surface = surface; Surface = surface;
} }
public Surface Surface { get; } public ArtemisSurface Surface { get; }
} }
} }

View File

@ -44,7 +44,7 @@ namespace Artemis.Core.Models.Profile.Abstract
/// <summary> /// <summary>
/// Renders the element /// Renders the element
/// </summary> /// </summary>
public abstract void Render(double deltaTime, Surface.Surface surface, Graphics graphics); public abstract void Render(double deltaTime, Surface.ArtemisSurface surface, Graphics graphics);
/// <summary> /// <summary>
/// Applies the profile element's properties to the underlying storage entity /// Applies the profile element's properties to the underlying storage entity

View File

@ -56,7 +56,7 @@ namespace Artemis.Core.Models.Profile
profileElement.Update(deltaTime); profileElement.Update(deltaTime);
} }
public override void Render(double deltaTime, Surface.Surface surface, Graphics graphics) public override void Render(double deltaTime, Surface.ArtemisSurface surface, Graphics graphics)
{ {
// Folders don't render but their children do // Folders don't render but their children do
foreach (var profileElement in Children) foreach (var profileElement in Children)

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Linq; using System.Linq;
@ -15,6 +16,8 @@ namespace Artemis.Core.Models.Profile
{ {
public sealed class Layer : ProfileElement public sealed class Layer : ProfileElement
{ {
private List<ArtemisLed> _leds;
public Layer(Profile profile, ProfileElement parent, string name) public Layer(Profile profile, ProfileElement parent, string name)
{ {
LayerEntity = new LayerEntity(); LayerEntity = new LayerEntity();
@ -23,7 +26,7 @@ namespace Artemis.Core.Models.Profile
Profile = profile; Profile = profile;
Parent = parent; Parent = parent;
Name = name; Name = name;
Leds = new List<DeviceLed>(); _leds = new List<ArtemisLed>();
} }
internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity, IPluginService pluginService) internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity, IPluginService pluginService)
@ -37,12 +40,12 @@ namespace Artemis.Core.Models.Profile
Order = layerEntity.Order; Order = layerEntity.Order;
LayerType = pluginService.GetLayerTypeByGuid(layerEntity.LayerTypeGuid); LayerType = pluginService.GetLayerTypeByGuid(layerEntity.LayerTypeGuid);
Leds = new List<DeviceLed>(); _leds = new List<ArtemisLed>();
} }
internal LayerEntity LayerEntity { get; set; } internal LayerEntity LayerEntity { get; set; }
public List<DeviceLed> Leds { get; private set; } public ReadOnlyCollection<ArtemisLed> Leds => _leds.AsReadOnly();
public LayerType LayerType { get; private set; } public LayerType LayerType { get; private set; }
public ILayerTypeConfiguration LayerTypeConfiguration { get; set; } public ILayerTypeConfiguration LayerTypeConfiguration { get; set; }
@ -60,7 +63,7 @@ namespace Artemis.Core.Models.Profile
} }
} }
public override void Render(double deltaTime, Surface.Surface surface, Graphics graphics) public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics)
{ {
if (LayerType == null) if (LayerType == null)
return; return;
@ -81,19 +84,62 @@ namespace Artemis.Core.Models.Profile
LayerEntity.Name = Name; LayerEntity.Name = Name;
LayerEntity.ProfileId = Profile.EntityId; LayerEntity.ProfileId = Profile.EntityId;
// TODO: LEDs, conditions, elements
}
public void ApplySurface(Surface.Surface surface) LayerEntity.Leds.Clear();
{ foreach (var artemisLed in Leds)
var leds = new List<DeviceLed>();
foreach (var surfaceDevice in surface.Devices)
{ {
var deviceHash = surfaceDevice.RgbDevice.GetDeviceHashCode(); var ledEntity = new LedEntity
leds.AddRange(surfaceDevice.Leds.Where(dl => LayerEntity.Leds.Any(l => l.DeviceHash == deviceHash && l.LedName == dl.RgbLed.ToString()))); {
DeviceHash = artemisLed.Device.RgbDevice.GetDeviceHashCode(),
LedName = artemisLed.RgbLed.Id.ToString()
};
LayerEntity.Leds.Add(ledEntity);
} }
Leds = leds; LayerEntity.Condition.Clear();
LayerEntity.Elements.Clear();
}
public void ApplySurface(ArtemisSurface surface)
{
var leds = new List<ArtemisLed>();
// Get the surface LEDs for this layer
var availableLeds = surface.Devices.SelectMany(d => d.Leds).ToList();
foreach (var ledEntity in LayerEntity.Leds)
{
var match = availableLeds.FirstOrDefault(a => a.Device.RgbDevice.GetDeviceHashCode() == ledEntity.DeviceHash &&
a.RgbLed.Id.ToString() == ledEntity.LedName);
if (match != null)
leds.Add(match);
}
_leds = leds;
CalculateRenderProperties();
}
public void AddLed(ArtemisLed led)
{
_leds.Add(led);
CalculateRenderProperties();
}
public void AddLeds(IEnumerable<ArtemisLed> leds)
{
_leds.AddRange(leds);
CalculateRenderProperties();
}
public void RemoveLed(ArtemisLed led)
{
_leds.Remove(led);
CalculateRenderProperties();
}
public void ClearLeds()
{
_leds.Clear();
CalculateRenderProperties(); CalculateRenderProperties();
} }

View File

@ -56,7 +56,7 @@ namespace Artemis.Core.Models.Profile
} }
} }
public override void Render(double deltaTime, Surface.Surface surface, Graphics graphics) public override void Render(double deltaTime, Surface.ArtemisSurface surface, Graphics graphics)
{ {
lock (this) lock (this)
{ {
@ -113,7 +113,7 @@ namespace Artemis.Core.Models.Profile
return $"{nameof(Order)}: {Order}, {nameof(Name)}: {Name}, {nameof(PluginInfo)}: {PluginInfo}"; return $"{nameof(Order)}: {Order}, {nameof(Name)}: {Name}, {nameof(PluginInfo)}: {PluginInfo}";
} }
public void ApplySurface(Surface.Surface surface) public void ApplySurface(Surface.ArtemisSurface surface)
{ {
foreach (var layer in GetAllLayers()) foreach (var layer in GetAllLayers())
layer.ApplySurface(surface); layer.ApplySurface(surface);

View File

@ -11,15 +11,15 @@ using Rectangle = System.Drawing.Rectangle;
namespace Artemis.Core.Models.Surface namespace Artemis.Core.Models.Surface
{ {
public class Device : PropertyChangedBase public class ArtemisDevice : PropertyChangedBase
{ {
internal Device(IRGBDevice rgbDevice, Plugin plugin, Surface surface) internal ArtemisDevice(IRGBDevice rgbDevice, Plugin plugin, ArtemisSurface surface)
{ {
RgbDevice = rgbDevice; RgbDevice = rgbDevice;
Plugin = plugin; Plugin = plugin;
Surface = surface; Surface = surface;
DeviceEntity = new DeviceEntity(); DeviceEntity = new DeviceEntity();
Leds = rgbDevice.Select(l => new DeviceLed(l, this)).ToList().AsReadOnly(); Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
Rotation = 0; Rotation = 0;
Scale = 1; Scale = 1;
@ -29,13 +29,13 @@ namespace Artemis.Core.Models.Surface
CalculateRenderProperties(); CalculateRenderProperties();
} }
internal Device(IRGBDevice rgbDevice, Plugin plugin, Surface surface, DeviceEntity deviceEntity) internal ArtemisDevice(IRGBDevice rgbDevice, Plugin plugin, ArtemisSurface surface, DeviceEntity deviceEntity)
{ {
RgbDevice = rgbDevice; RgbDevice = rgbDevice;
Plugin = plugin; Plugin = plugin;
Surface = surface; Surface = surface;
DeviceEntity = deviceEntity; DeviceEntity = deviceEntity;
Leds = rgbDevice.Select(l => new DeviceLed(l, this)).ToList().AsReadOnly(); Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
} }
public Rectangle RenderRectangle { get; private set; } public Rectangle RenderRectangle { get; private set; }
@ -43,9 +43,9 @@ namespace Artemis.Core.Models.Surface
public IRGBDevice RgbDevice { get; } public IRGBDevice RgbDevice { get; }
public Plugin Plugin { get; } public Plugin Plugin { get; }
public Surface Surface { get; } public ArtemisSurface Surface { get; }
public DeviceEntity DeviceEntity { get; } public DeviceEntity DeviceEntity { get; }
public ReadOnlyCollection<DeviceLed> Leds { get; set; } public ReadOnlyCollection<ArtemisLed> Leds { get; set; }
public double X public double X
{ {

View File

@ -5,9 +5,9 @@ using Rectangle = System.Drawing.Rectangle;
namespace Artemis.Core.Models.Surface namespace Artemis.Core.Models.Surface
{ {
public class DeviceLed : PropertyChangedBase public class ArtemisLed : PropertyChangedBase
{ {
public DeviceLed(Led led, Device device) public ArtemisLed(Led led, ArtemisDevice device)
{ {
RgbLed = led; RgbLed = led;
Device = device; Device = device;
@ -15,7 +15,7 @@ namespace Artemis.Core.Models.Surface
} }
public Led RgbLed { get; } public Led RgbLed { get; }
public Device Device { get; } public ArtemisDevice Device { get; }
public Rectangle RenderRectangle { get; private set; } public Rectangle RenderRectangle { get; private set; }
public Rectangle AbsoluteRenderRectangle { get; private set; } public Rectangle AbsoluteRenderRectangle { get; private set; }

View File

@ -7,9 +7,9 @@ using Stylet;
namespace Artemis.Core.Models.Surface namespace Artemis.Core.Models.Surface
{ {
public class Surface : PropertyChangedBase public class ArtemisSurface : PropertyChangedBase
{ {
internal Surface(RGBSurface rgbSurface, string name, double scale) internal ArtemisSurface(RGBSurface rgbSurface, string name, double scale)
{ {
SurfaceEntity = new SurfaceEntity {DeviceEntities = new List<DeviceEntity>()}; SurfaceEntity = new SurfaceEntity {DeviceEntities = new List<DeviceEntity>()};
EntityId = Guid.NewGuid(); EntityId = Guid.NewGuid();
@ -20,12 +20,12 @@ namespace Artemis.Core.Models.Surface
IsActive = false; IsActive = false;
// Devices are not populated here but as they are detected // Devices are not populated here but as they are detected
Devices = new List<Device>(); Devices = new List<ArtemisDevice>();
ApplyToEntity(); ApplyToEntity();
} }
internal Surface(RGBSurface rgbSurface, SurfaceEntity surfaceEntity, double scale) internal ArtemisSurface(RGBSurface rgbSurface, SurfaceEntity surfaceEntity, double scale)
{ {
SurfaceEntity = surfaceEntity; SurfaceEntity = surfaceEntity;
EntityId = surfaceEntity.Id; EntityId = surfaceEntity.Id;
@ -36,14 +36,14 @@ namespace Artemis.Core.Models.Surface
IsActive = surfaceEntity.IsActive; IsActive = surfaceEntity.IsActive;
// Devices are not populated here but as they are detected // Devices are not populated here but as they are detected
Devices = new List<Device>(); Devices = new List<ArtemisDevice>();
} }
public RGBSurface RgbSurface { get; } public RGBSurface RgbSurface { get; }
public double Scale { get; private set; } public double Scale { get; private set; }
public string Name { get; set; } public string Name { get; set; }
public bool IsActive { get; internal set; } public bool IsActive { get; internal set; }
public List<Device> Devices { get; internal set; } public List<ArtemisDevice> Devices { get; internal set; }
internal SurfaceEntity SurfaceEntity { get; set; } internal SurfaceEntity SurfaceEntity { get; set; }
internal Guid EntityId { get; set; } internal Guid EntityId { get; set; }

View File

@ -24,6 +24,6 @@ namespace Artemis.Core.Plugins.Abstract
/// <summary> /// <summary>
/// Renders the layer type /// Renders the layer type
/// </summary> /// </summary>
public abstract void Render(Layer device, Surface surface, Graphics graphics); public abstract void Render(Layer device, ArtemisSurface surface, Graphics graphics);
} }
} }

View File

@ -38,7 +38,7 @@ namespace Artemis.Core.Plugins.Abstract
/// <param name="deltaTime">Time since the last render</param> /// <param name="deltaTime">Time since the last render</param>
/// <param name="surface">The RGB Surface to render to</param> /// <param name="surface">The RGB Surface to render to</param>
/// <param name="graphics"></param> /// <param name="graphics"></param>
public abstract void Render(double deltaTime, Surface surface, Graphics graphics); public abstract void Render(double deltaTime, ArtemisSurface surface, Graphics graphics);
/// <summary> /// <summary>
/// Called when the module's view model is being show, return view models here to create tabs for them /// Called when the module's view model is being show, return view models here to create tabs for them

View File

@ -25,7 +25,7 @@ namespace Artemis.Core.Plugins.Abstract
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Render(double deltaTime, Surface surface, Graphics graphics) public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics)
{ {
lock (this) lock (this)
{ {

View File

@ -1,60 +0,0 @@
using System.Collections.Generic;
using System.Drawing;
using Artemis.Core.ProfileElements.Interfaces;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Entities;
using RGB.NET.Core;
namespace Artemis.Core.ProfileElements
{
public class Folder : IProfileElement
{
public Folder(Profile profile)
{
Profile = profile;
Children = new List<IProfileElement>();
}
public Profile Profile { get; }
public List<IProfileElement> Children { get; set; }
public int Order { get; set; }
public string Name { get; set; }
public void Update(double deltaTime)
{
// Folders don't update but their children do
foreach (var profileElement in Children)
profileElement.Update(deltaTime);
}
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
{
// Folders don't render but their children do
foreach (var profileElement in Children)
profileElement.Render(deltaTime, surface, graphics);
}
public static Folder FromFolderEntity(Profile profile, FolderEntity folderEntity, IPluginService pluginService)
{
var folder = new Folder(profile)
{
Name = folderEntity.Name,
Order = folderEntity.Order
};
// Load child folders
foreach (var childFolder in folderEntity.Folders)
folder.Children.Add(FromFolderEntity(profile, childFolder, pluginService));
// Load child layers
foreach (var childLayer in folderEntity.Layers)
folder.Children.Add(Layer.FromLayerEntity(profile, childLayer, pluginService));
return folder;
}
public override string ToString()
{
return $"{nameof(Profile)}: {Profile}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}";
}
}
}

View File

@ -1,35 +0,0 @@
using System.Collections.Generic;
using System.Drawing;
using RGB.NET.Core;
namespace Artemis.Core.ProfileElements.Interfaces
{
public interface IProfileElement
{
/// <summary>
/// The element's children
/// </summary>
List<IProfileElement> Children { get; set; }
/// <summary>
/// The order in which this element appears in the update loop and editor
/// </summary>
int Order { get; set; }
/// <summary>
/// The name which appears in the editor
/// </summary>
string Name { get; set; }
/// <summary>
/// Updates the element
/// </summary>
/// <param name="deltaTime"></param>
void Update(double deltaTime);
/// <summary>
/// Renders the element
/// </summary>
void Render(double deltaTime, RGBSurface surface, Graphics graphics);
}
}

View File

@ -1,80 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Interfaces;
using Artemis.Core.ProfileElements.Interfaces;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Entities;
using RGB.NET.Core;
namespace Artemis.Core.ProfileElements
{
public class Layer : IProfileElement
{
public Layer(Profile profile)
{
Profile = profile;
Children = new List<IProfileElement>();
}
public Profile Profile { get; }
public LayerType LayerType { get; private set; }
public ILayerTypeConfiguration LayerTypeConfiguration { get; set; }
public List<IProfileElement> Children { get; set; }
public int Order { get; set; }
public string Name { get; set; }
public void Update(double deltaTime)
{
if (LayerType == null)
return;
lock (LayerType)
{
LayerType.Update(this);
}
}
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
{
if (LayerType == null)
return;
lock (LayerType)
{
LayerType.Render(this, surface, graphics);
}
}
public static Layer FromLayerEntity(Profile profile, LayerEntity layerEntity, IPluginService pluginService)
{
var layer = new Layer(profile)
{
Name = layerEntity.Name,
Order = layerEntity.Order,
LayerType = pluginService.GetLayerTypeByGuid(Guid.Parse(layerEntity.Guid))
};
return layer;
}
public void UpdateLayerType(LayerType layerType)
{
if (LayerType != null)
{
lock (LayerType)
{
LayerType.Dispose();
}
}
LayerType = layerType;
}
public override string ToString()
{
return $"{nameof(Profile)}: {Profile}, {nameof(Order)}: {Order}, {nameof(Name)}: {Name}";
}
}
}

View File

@ -1,113 +0,0 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using Artemis.Core.Exceptions;
using Artemis.Core.Plugins.Models;
using Artemis.Core.ProfileElements.Interfaces;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Entities;
using RGB.NET.Core;
namespace Artemis.Core.ProfileElements
{
public class Profile : IProfileElement
{
private Profile(PluginInfo pluginInfo)
{
PluginInfo = pluginInfo;
}
public PluginInfo PluginInfo { get; }
public bool IsActivated { get; private set; }
public int Order { get; set; }
public string Name { get; set; }
public List<IProfileElement> Children { get; set; }
public void Update(double deltaTime)
{
lock (this)
{
if (!IsActivated)
throw new ArtemisCoreException($"Cannot update inactive profile: {this}");
foreach (var profileElement in Children)
profileElement.Update(deltaTime);
}
}
public void Render(double deltaTime, RGBSurface surface, Graphics graphics)
{
lock (this)
{
if (!IsActivated)
throw new ArtemisCoreException($"Cannot render inactive profile: {this}");
foreach (var profileElement in Children)
profileElement.Render(deltaTime, surface, graphics);
}
}
public static Profile FromProfileEntity(PluginInfo pluginInfo, ProfileEntity profileEntity, IPluginService pluginService)
{
var profile = new Profile(pluginInfo) {Name = profileEntity.Name};
lock (profile)
{
// Populate the profile starting at the root, the rest is populated recursively
profile.Children.Add(Folder.FromFolderEntity(profile, profileEntity.RootFolder, pluginService));
return profile;
}
}
public void Activate()
{
lock (this)
{
if (IsActivated) return;
OnActivated();
IsActivated = true;
}
}
public void Deactivate()
{
lock (this)
{
if (!IsActivated) return;
IsActivated = false;
OnDeactivated();
}
}
public override string ToString()
{
return $"{nameof(Order)}: {Order}, {nameof(Name)}: {Name}, {nameof(PluginInfo)}: {PluginInfo}";
}
#region Events
/// <summary>
/// Occurs when the profile is being activated.
/// </summary>
public event EventHandler Activated;
/// <summary>
/// Occurs when the profile is being deactivated.
/// </summary>
public event EventHandler Deactivated;
private void OnActivated()
{
Activated?.Invoke(this, EventArgs.Empty);
}
private void OnDeactivated()
{
Deactivated?.Invoke(this, EventArgs.Empty);
}
#endregion
}
}

View File

@ -19,12 +19,12 @@ namespace Artemis.Core.Services
_coreService = coreService; _coreService = coreService;
} }
public void IdentifyDevice(Device device) public void IdentifyDevice(ArtemisDevice device)
{ {
BlinkDevice(device, 0); BlinkDevice(device, 0);
} }
private void BlinkDevice(Device device, int blinkCount) private void BlinkDevice(ArtemisDevice device, int blinkCount)
{ {
// Draw a white overlay over the device // Draw a white overlay over the device
void DrawOverlay(object sender, FrameRenderingEventArgs args) void DrawOverlay(object sender, FrameRenderingEventArgs args)
@ -59,6 +59,6 @@ namespace Artemis.Core.Services
/// Identifies the device by making it blink white 5 times /// Identifies the device by making it blink white 5 times
/// </summary> /// </summary>
/// <param name="device"></param> /// <param name="device"></param>
void IdentifyDevice(Device device); void IdentifyDevice(ArtemisDevice device);
} }
} }

View File

@ -11,38 +11,38 @@ namespace Artemis.Core.Services.Storage.Interfaces
/// <summary> /// <summary>
/// Gets the currently active surface entity, to change config use <see cref="SetActiveSurfaceConfiguration" /> /// Gets the currently active surface entity, to change config use <see cref="SetActiveSurfaceConfiguration" />
/// </summary> /// </summary>
Surface ActiveSurface { get; } ArtemisSurface ActiveSurface { get; }
/// <summary> /// <summary>
/// Gets a read-only list of all surface configurations /// Gets a read-only list of all surface configurations
/// </summary> /// </summary>
ReadOnlyCollection<Surface> SurfaceConfigurations { get; } ReadOnlyCollection<ArtemisSurface> SurfaceConfigurations { get; }
/// <summary> /// <summary>
/// Creates a new surface entity with the supplied name /// Creates a new surface entity with the supplied name
/// </summary> /// </summary>
/// <param name="name">The name for the new surface entity</param> /// <param name="name">The name for the new surface entity</param>
/// <returns></returns> /// <returns></returns>
Surface CreateSurfaceConfiguration(string name); ArtemisSurface CreateSurfaceConfiguration(string name);
/// <summary> /// <summary>
/// Sets the provided entity as active and applies it to the surface /// Sets the provided entity as active and applies it to the surface
/// </summary> /// </summary>
/// <param name="surface">The entity to activate and apply</param> /// <param name="surface">The entity to activate and apply</param>
void SetActiveSurfaceConfiguration(Surface surface); void SetActiveSurfaceConfiguration(ArtemisSurface surface);
/// <summary> /// <summary>
/// Saves the provided surface entity to permanent storage and if config is active, applies it to the surface /// Saves the provided surface entity to permanent storage and if config is active, applies it to the surface
/// </summary> /// </summary>
/// <param name="surface">The entity to save (and apply if active)</param> /// <param name="surface">The entity to save (and apply if active)</param>
/// <param name="includeDevices">Whether to also save devices. If false, devices changes won't be applied either</param> /// <param name="includeDevices">Whether to also save devices. If false, devices changes won't be applied either</param>
void UpdateSurfaceConfiguration(Surface surface, bool includeDevices); void UpdateSurfaceConfiguration(ArtemisSurface surface, bool includeDevices);
/// <summary> /// <summary>
/// Deletes the supplied surface entity, surface entity may not be the active surface entity /// Deletes the supplied surface entity, surface entity may not be the active surface entity
/// </summary> /// </summary>
/// <param name="surface">The surface entity to delete, may not be the active surface entity</param> /// <param name="surface">The surface entity to delete, may not be the active surface entity</param>
void DeleteSurfaceConfiguration(Surface surface); void DeleteSurfaceConfiguration(ArtemisSurface surface);
/// <summary> /// <summary>
/// Occurs when the active device entity has been changed /// Occurs when the active device entity has been changed

View File

@ -41,7 +41,7 @@ namespace Artemis.Core.Services.Storage
ApplySurfaceToProfiles(e.Surface); ApplySurfaceToProfiles(e.Surface);
} }
private void ApplySurfaceToProfiles(Surface surface) private void ApplySurfaceToProfiles(ArtemisSurface surface)
{ {
var profileModules = _pluginService.GetPluginsOfType<ProfileModule>(); var profileModules = _pluginService.GetPluginsOfType<ProfileModule>();
foreach (var profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList()) foreach (var profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList())

View File

@ -21,7 +21,7 @@ namespace Artemis.Core.Services.Storage
private readonly IPluginService _pluginService; private readonly IPluginService _pluginService;
private readonly PluginSetting<double> _renderScaleSetting; private readonly PluginSetting<double> _renderScaleSetting;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly List<Surface> _surfaceConfigurations; private readonly List<ArtemisSurface> _surfaceConfigurations;
private readonly ISurfaceRepository _surfaceRepository; private readonly ISurfaceRepository _surfaceRepository;
internal SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, IPluginService pluginService, ISettingsService settingsService) internal SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, IPluginService pluginService, ISettingsService settingsService)
@ -30,7 +30,7 @@ namespace Artemis.Core.Services.Storage
_surfaceRepository = surfaceRepository; _surfaceRepository = surfaceRepository;
_rgbService = rgbService; _rgbService = rgbService;
_pluginService = pluginService; _pluginService = pluginService;
_surfaceConfigurations = new List<Surface>(); _surfaceConfigurations = new List<ArtemisSurface>();
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 1.0); _renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 1.0);
LoadFromRepository(); LoadFromRepository();
@ -39,19 +39,19 @@ namespace Artemis.Core.Services.Storage
_renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged; _renderScaleSetting.SettingChanged += RenderScaleSettingOnSettingChanged;
} }
public Surface ActiveSurface { get; private set; } public ArtemisSurface ActiveSurface { get; private set; }
public ReadOnlyCollection<Surface> SurfaceConfigurations => _surfaceConfigurations.AsReadOnly(); public ReadOnlyCollection<ArtemisSurface> SurfaceConfigurations => _surfaceConfigurations.AsReadOnly();
public Surface CreateSurfaceConfiguration(string name) public ArtemisSurface CreateSurfaceConfiguration(string name)
{ {
// Create a blank config // Create a blank config
var configuration = new Surface(_rgbService.Surface, name, _renderScaleSetting.Value); var configuration = new ArtemisSurface(_rgbService.Surface, name, _renderScaleSetting.Value);
// Add all current devices // Add all current devices
foreach (var rgbDevice in _rgbService.LoadedDevices) foreach (var rgbDevice in _rgbService.LoadedDevices)
{ {
var plugin = _pluginService.GetDevicePlugin(rgbDevice); var plugin = _pluginService.GetDevicePlugin(rgbDevice);
configuration.Devices.Add(new Device(rgbDevice, plugin, configuration)); configuration.Devices.Add(new ArtemisDevice(rgbDevice, plugin, configuration));
} }
lock (_surfaceConfigurations) lock (_surfaceConfigurations)
@ -64,7 +64,7 @@ namespace Artemis.Core.Services.Storage
} }
} }
public void SetActiveSurfaceConfiguration(Surface surface) public void SetActiveSurfaceConfiguration(ArtemisSurface surface)
{ {
if (ActiveSurface == surface) if (ActiveSurface == surface)
return; return;
@ -97,7 +97,7 @@ namespace Artemis.Core.Services.Storage
OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurface)); OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(ActiveSurface));
} }
public void UpdateSurfaceConfiguration(Surface surface, bool includeDevices) public void UpdateSurfaceConfiguration(ArtemisSurface surface, bool includeDevices)
{ {
surface.ApplyToEntity(); surface.ApplyToEntity();
if (includeDevices) if (includeDevices)
@ -115,7 +115,7 @@ namespace Artemis.Core.Services.Storage
OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surface)); OnSurfaceConfigurationUpdated(new SurfaceConfigurationEventArgs(surface));
} }
public void DeleteSurfaceConfiguration(Surface surface) public void DeleteSurfaceConfiguration(ArtemisSurface surface)
{ {
if (surface == ActiveSurface) if (surface == ActiveSurface)
throw new ArtemisCoreException($"Cannot delete surface entity '{surface.Name}' because it is active."); throw new ArtemisCoreException($"Cannot delete surface entity '{surface.Name}' because it is active.");
@ -136,14 +136,14 @@ namespace Artemis.Core.Services.Storage
foreach (var surfaceEntity in configs) foreach (var surfaceEntity in configs)
{ {
// Create the surface entity // Create the surface entity
var surfaceConfiguration = new Surface(_rgbService.Surface, surfaceEntity, _renderScaleSetting.Value); var surfaceConfiguration = new ArtemisSurface(_rgbService.Surface, surfaceEntity, _renderScaleSetting.Value);
foreach (var position in surfaceEntity.DeviceEntities) foreach (var position in surfaceEntity.DeviceEntities)
{ {
var device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceHashCode() == position.DeviceHashCode); var device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceHashCode() == position.DeviceHashCode);
if (device != null) if (device != null)
{ {
var plugin = _pluginService.GetDevicePlugin(device); var plugin = _pluginService.GetDevicePlugin(device);
surfaceConfiguration.Devices.Add(new Device(device, plugin, surfaceConfiguration, position)); surfaceConfiguration.Devices.Add(new ArtemisDevice(device, plugin, surfaceConfiguration, position));
} }
} }
@ -172,7 +172,7 @@ namespace Artemis.Core.Services.Storage
#region Utilities #region Utilities
private void AddDeviceIfMissing(IRGBDevice rgbDevice, Surface surface) private void AddDeviceIfMissing(IRGBDevice rgbDevice, ArtemisSurface surface)
{ {
var deviceHashCode = rgbDevice.GetDeviceHashCode(); var deviceHashCode = rgbDevice.GetDeviceHashCode();
var device = surface.Devices.FirstOrDefault(d => d.DeviceEntity.DeviceHashCode == deviceHashCode); var device = surface.Devices.FirstOrDefault(d => d.DeviceEntity.DeviceHashCode == deviceHashCode);
@ -185,7 +185,7 @@ namespace Artemis.Core.Services.Storage
if (existingDeviceConfig != null) if (existingDeviceConfig != null)
{ {
var plugin = _pluginService.GetDevicePlugin(rgbDevice); var plugin = _pluginService.GetDevicePlugin(rgbDevice);
device = new Device(rgbDevice, plugin, surface, existingDeviceConfig); device = new ArtemisDevice(rgbDevice, plugin, surface, existingDeviceConfig);
} }
// Fall back on creating a new device // Fall back on creating a new device
else else
@ -196,7 +196,7 @@ namespace Artemis.Core.Services.Storage
deviceHashCode deviceHashCode
); );
var plugin = _pluginService.GetDevicePlugin(rgbDevice); var plugin = _pluginService.GetDevicePlugin(rgbDevice);
device = new Device(rgbDevice, plugin, surface); device = new ArtemisDevice(rgbDevice, plugin, surface);
} }
surface.Devices.Add(device); surface.Devices.Add(device);

View File

@ -31,7 +31,7 @@ namespace Artemis.Plugins.LayerTypes.Brush
// Update the brush // Update the brush
} }
public override void Render(Layer device, Surface surface, Graphics graphics) public override void Render(Layer device, ArtemisSurface surface, Graphics graphics)
{ {
} }

View File

@ -8,7 +8,6 @@ using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Plugins.Models; using Artemis.Core.Plugins.Models;
using Artemis.Core.Services.Storage.Interfaces; using Artemis.Core.Services.Storage.Interfaces;
using Artemis.Plugins.Modules.General.ViewModels; using Artemis.Plugins.Modules.General.ViewModels;
using Device = Artemis.Core.Models.Surface.Device;
namespace Artemis.Plugins.Modules.General namespace Artemis.Plugins.Modules.General
{ {
@ -22,7 +21,7 @@ namespace Artemis.Plugins.Modules.General
_settings = settings; _settings = settings;
DisplayName = "General"; DisplayName = "General";
ExpandsMainDataModel = true; ExpandsMainDataModel = true;
DeviceBrushes = new Dictionary<Device, TextureBrush>(); DeviceBrushes = new Dictionary<ArtemisDevice, TextureBrush>();
var testSetting = _settings.GetSetting("TestSetting", DateTime.Now); var testSetting = _settings.GetSetting("TestSetting", DateTime.Now);
@ -69,7 +68,7 @@ namespace Artemis.Plugins.Modules.General
} }
public override void Render(double deltaTime, Surface surface, Graphics graphics) public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics)
{ {
// Per-device coloring, slower // Per-device coloring, slower
RenderPerDevice(surface, graphics); RenderPerDevice(surface, graphics);
@ -78,11 +77,11 @@ namespace Artemis.Plugins.Modules.General
// RenderPerLed(surface, graphics); // RenderPerLed(surface, graphics);
} }
public void RenderFullSurface(Surface surface, Graphics graphics) public void RenderFullSurface(ArtemisSurface surface, Graphics graphics)
{ {
} }
public void RenderPerDevice(Surface surface, Graphics graphics) public void RenderPerDevice(ArtemisSurface surface, Graphics graphics)
{ {
foreach (var device in surface.Devices) foreach (var device in surface.Devices)
{ {
@ -98,9 +97,9 @@ namespace Artemis.Plugins.Modules.General
} }
} }
public Dictionary<Device, TextureBrush> DeviceBrushes { get; set; } public Dictionary<ArtemisDevice, TextureBrush> DeviceBrushes { get; set; }
private Image RenderGradientForDevice(Device device) private Image RenderGradientForDevice(ArtemisDevice device)
{ {
var brush = new LinearGradientBrush(device.RenderRectangle, Color.Black, Color.Black, 0, false) var brush = new LinearGradientBrush(device.RenderRectangle, Color.Black, Color.Black, 0, false)
{ {
@ -115,7 +114,7 @@ namespace Artemis.Plugins.Modules.General
return bitmap; return bitmap;
} }
public void RenderPerLed(Surface surface, Graphics graphics) public void RenderPerLed(ArtemisSurface surface, Graphics graphics)
{ {
var index = 0; var index = 0;
foreach (var led in surface.Devices.SelectMany(d => d.Leds)) foreach (var led in surface.Devices.SelectMany(d => d.Leds))

View File

@ -1,11 +1,7 @@
using System; namespace Artemis.Storage.Entities.Profile
namespace Artemis.Storage.Entities.Profile
{ {
public class LedEntity public class LedEntity
{ {
public Guid Id { get; set; }
public string LedName { get; set; } public string LedName { get; set; }
public int DeviceHash { get; set; } public int DeviceHash { get; set; }
} }

View File

@ -152,9 +152,9 @@
<Compile Include="Converters\InverseBooleanConverter.cs" /> <Compile Include="Converters\InverseBooleanConverter.cs" />
<Compile Include="Converters\NullToImageConverter.cs" /> <Compile Include="Converters\NullToImageConverter.cs" />
<Compile Include="Converters\NullToVisibilityConverter.cs" /> <Compile Include="Converters\NullToVisibilityConverter.cs" />
<Compile Include="Events\MainWindowFocusChanged.cs" /> <Compile Include="Events\MainWindowFocusChangedEvent.cs" />
<Compile Include="Events\ProfileEditorSelectedElementChanged.cs" /> <Compile Include="Services\Interfaces\IProfileEditorService.cs" />
<Compile Include="Events\ProfileEditorSelectedProfileChanged.cs" /> <Compile Include="Services\ProfileEditorService.cs" />
<Compile Include="Utilities\BindableSelectedItemBehavior.cs" /> <Compile Include="Utilities\BindableSelectedItemBehavior.cs" />
<Compile Include="Utilities\TriggerTracing.cs" /> <Compile Include="Utilities\TriggerTracing.cs" />
<Compile Include="Exceptions\ArtemisCoreException.cs" /> <Compile Include="Exceptions\ArtemisCoreException.cs" />
@ -182,11 +182,11 @@
<Compile Include="Screens\Module\ProfileEditor\ElementProperties\ElementPropertyViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\ElementProperties\ElementPropertyViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerElements\LayerElementsViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\LayerElements\LayerElementsViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerElements\LayerElementViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\LayerElements\LayerElementViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\ProfileElements\ProfileElement\FolderViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\ProfileElements\ProfileElement\LayerViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\ProfileElements\ProfileElementsViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\ProfileTree\ProfileTreeViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\ProfileEditorPanelViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\ProfileEditorPanelViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\ProfileElements\ProfileElement\ProfileElementViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\ProfileTree\TreeItem\TreeItemViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\Visualization\ProfileViewModel.cs" /> <Compile Include="Screens\Module\ProfileEditor\Visualization\ProfileViewModel.cs" />
<Compile Include="Screens\News\NewsViewModel.cs" /> <Compile Include="Screens\News\NewsViewModel.cs" />
<Compile Include="Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigViewModelValidator.cs" /> <Compile Include="Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigViewModelValidator.cs" />
@ -258,15 +258,15 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Screens\Module\ProfileEditor\ProfileElements\ProfileElement\FolderView.xaml"> <Page Include="Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Screens\Module\ProfileEditor\ProfileElements\ProfileElement\LayerView.xaml"> <Page Include="Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Screens\Module\ProfileEditor\ProfileElements\ProfileElementsView.xaml"> <Page Include="Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>

View File

@ -1,8 +1,8 @@
namespace Artemis.UI.Events namespace Artemis.UI.Events
{ {
public class MainWindowFocusChanged public class MainWindowFocusChangedEvent
{ {
public MainWindowFocusChanged(bool isFocused) public MainWindowFocusChangedEvent(bool isFocused)
{ {
IsFocused = isFocused; IsFocused = isFocused;
} }

View File

@ -1,15 +0,0 @@
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.Abstract;
namespace Artemis.UI.Events
{
public class ProfileEditorSelectedElementChanged
{
public ProfileEditorSelectedElementChanged(ProfileElement profileElement)
{
ProfileElement = profileElement;
}
public ProfileElement ProfileElement { get; }
}
}

View File

@ -1,14 +0,0 @@
using Artemis.Core.Models.Profile;
namespace Artemis.UI.Events
{
public class ProfileEditorSelectedProfileChanged
{
public ProfileEditorSelectedProfileChanged(Profile profile)
{
Profile = profile;
}
public Profile Profile { get; }
}
}

View File

@ -5,6 +5,6 @@ namespace Artemis.UI.Ninject.Factories
{ {
public interface IDeviceSettingsViewModelFactory : IArtemisUIFactory public interface IDeviceSettingsViewModelFactory : IArtemisUIFactory
{ {
DeviceSettingsViewModel Create(Device device); DeviceSettingsViewModel Create(ArtemisDevice device);
} }
} }

View File

@ -141,7 +141,7 @@
<!-- Profile elements --> <!-- Profile elements -->
<materialDesign:Card Grid.Row="1" materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch"> <materialDesign:Card Grid.Row="1" materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch">
<ContentControl s:View.Model="{Binding ProfileElementsViewModel}" Margin="0,-1,-0.2,1" /> <ContentControl s:View.Model="{Binding ProfileTreeViewModel}" Margin="0,-1,-0.2,1" />
</materialDesign:Card> </materialDesign:Card>
<!-- Conditions resize --> <!-- Conditions resize -->

View File

@ -13,7 +13,7 @@ using Artemis.UI.Screens.Module.ProfileEditor.Dialogs;
using Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions; using Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions;
using Artemis.UI.Screens.Module.ProfileEditor.ElementProperties; using Artemis.UI.Screens.Module.ProfileEditor.ElementProperties;
using Artemis.UI.Screens.Module.ProfileEditor.LayerElements; using Artemis.UI.Screens.Module.ProfileEditor.LayerElements;
using Artemis.UI.Screens.Module.ProfileEditor.ProfileElements; using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree;
using Artemis.UI.Screens.Module.ProfileEditor.Visualization; using Artemis.UI.Screens.Module.ProfileEditor.Visualization;
using Artemis.UI.Services.Interfaces; using Artemis.UI.Services.Interfaces;
using Stylet; using Stylet;
@ -22,16 +22,20 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
{ {
public class ProfileEditorViewModel : Conductor<ProfileEditorPanelViewModel>.Collection.AllActive public class ProfileEditorViewModel : Conductor<ProfileEditorPanelViewModel>.Collection.AllActive
{ {
private readonly IEventAggregator _eventAggregator; private readonly IProfileEditorService _profileEditorService;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
public ProfileEditorViewModel(ProfileModule module, ICollection<ProfileEditorPanelViewModel> viewModels, IProfileService profileService, public ProfileEditorViewModel(ProfileModule module,
IDialogService dialogService, ISettingsService settingsService, IEventAggregator eventAggregator) ICollection<ProfileEditorPanelViewModel> viewModels,
IProfileEditorService profileEditorService,
IProfileService profileService,
IDialogService dialogService,
ISettingsService settingsService)
{ {
_profileEditorService = profileEditorService;
_profileService = profileService; _profileService = profileService;
_settingsService = settingsService; _settingsService = settingsService;
_eventAggregator = eventAggregator;
DisplayName = "Profile editor"; DisplayName = "Profile editor";
Module = module; Module = module;
@ -40,7 +44,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
DisplayConditionsViewModel = (DisplayConditionsViewModel) viewModels.First(vm => vm is DisplayConditionsViewModel); DisplayConditionsViewModel = (DisplayConditionsViewModel) viewModels.First(vm => vm is DisplayConditionsViewModel);
ElementPropertiesViewModel = (ElementPropertiesViewModel) viewModels.First(vm => vm is ElementPropertiesViewModel); ElementPropertiesViewModel = (ElementPropertiesViewModel) viewModels.First(vm => vm is ElementPropertiesViewModel);
LayerElementsViewModel = (LayerElementsViewModel) viewModels.First(vm => vm is LayerElementsViewModel); LayerElementsViewModel = (LayerElementsViewModel) viewModels.First(vm => vm is LayerElementsViewModel);
ProfileElementsViewModel = (ProfileElementsViewModel) viewModels.First(vm => vm is ProfileElementsViewModel); ProfileTreeViewModel = (ProfileTreeViewModel) viewModels.First(vm => vm is ProfileTreeViewModel);
ProfileViewModel = (ProfileViewModel) viewModels.First(vm => vm is ProfileViewModel); ProfileViewModel = (ProfileViewModel) viewModels.First(vm => vm is ProfileViewModel);
Profiles = new BindableCollection<Profile>(); Profiles = new BindableCollection<Profile>();
@ -54,7 +58,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
public DisplayConditionsViewModel DisplayConditionsViewModel { get; } public DisplayConditionsViewModel DisplayConditionsViewModel { get; }
public ElementPropertiesViewModel ElementPropertiesViewModel { get; } public ElementPropertiesViewModel ElementPropertiesViewModel { get; }
public LayerElementsViewModel LayerElementsViewModel { get; } public LayerElementsViewModel LayerElementsViewModel { get; }
public ProfileElementsViewModel ProfileElementsViewModel { get; } public ProfileTreeViewModel ProfileTreeViewModel { get; }
public ProfileViewModel ProfileViewModel { get; } public ProfileViewModel ProfileViewModel { get; }
public BindableCollection<Profile> Profiles { get; set; } public BindableCollection<Profile> Profiles { get; set; }
@ -78,12 +82,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
var oldProfile = Module.ActiveProfile; var oldProfile = Module.ActiveProfile;
Module.ChangeActiveProfile(profile); Module.ChangeActiveProfile(profile);
_eventAggregator.Publish(new ProfileEditorSelectedProfileChanged(SelectedProfile));
if (oldProfile != null) if (oldProfile != null)
_profileService.UpdateProfile(oldProfile, false); _profileService.UpdateProfile(oldProfile, false);
if (profile != null) if (profile != null)
_profileService.UpdateProfile(profile, false); _profileService.UpdateProfile(profile, false);
_profileEditorService.ChangeSelectedProfile(profile);
} }
public Profile CreateProfile(string name) public Profile CreateProfile(string name)
@ -135,11 +140,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
protected override void OnActivate() protected override void OnActivate()
{ {
LoadWorkspaceSettings(); LoadWorkspaceSettings();
Task.Run(() => Task.Run(() => LoadProfiles());
{
LoadProfiles();
_eventAggregator.Publish(new ProfileEditorSelectedProfileChanged(SelectedProfile));
});
base.OnActivate(); base.OnActivate();
} }
@ -176,14 +177,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
profiles = profiles.Where(p => p.EntityId != activeProfile.EntityId).ToList(); profiles = profiles.Where(p => p.EntityId != activeProfile.EntityId).ToList();
profiles.Add(activeProfile); profiles.Add(activeProfile);
Execute.PostToUIThread(() => // Populate the UI collection
{ Profiles.Clear();
// Populate the UI collection Profiles.AddRange(profiles.OrderBy(p => p.Name));
Profiles.Clear();
Profiles.AddRange(profiles.OrderBy(p => p.Name));
SelectedProfile = activeProfile; SelectedProfile = activeProfile;
});
_profileEditorService.ChangeSelectedProfile(SelectedProfile);
if (!activeProfile.IsActivated) if (!activeProfile.IsActivated)
Module.ChangeActiveProfile(activeProfile); Module.ChangeActiveProfile(activeProfile);

View File

@ -1,12 +0,0 @@
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement
{
public class FolderViewModel : ProfileElementViewModel
{
public FolderViewModel(ProfileElementViewModel parent, Core.Models.Profile.Abstract.ProfileElement folder, ProfileEditorViewModel profileEditorViewModel)
: base(parent, folder, profileEditorViewModel)
{
}
public override bool SupportsChildren => true;
}
}

View File

@ -1,12 +0,0 @@
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement
{
public class LayerViewModel : ProfileElementViewModel
{
public LayerViewModel(ProfileElementViewModel parent, Core.Models.Profile.Abstract.ProfileElement layer, ProfileEditorViewModel profileEditorViewModel)
: base(parent, layer, profileEditorViewModel)
{
}
public override bool SupportsChildren => false;
}
}

View File

@ -1,20 +1,18 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElementsView" <UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.ProfileTreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:profileEditor="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileElements"
xmlns:models="clr-namespace:Artemis.Core.Models.Profile.Abstract;assembly=Artemis.Core"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet" xmlns:s="https://github.com/canton7/Stylet"
xmlns:dd="urn:gong-wpf-dragdrop" xmlns:dd="urn:gong-wpf-dragdrop"
xmlns:profileElements="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileElements"
xmlns:profileElement="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:utilities="clr-namespace:Artemis.UI.Utilities" xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
xmlns:profileTree="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree"
xmlns:treeItem="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type profileElements:ProfileElementsViewModel}}"> d:DataContext="{d:DesignInstance {x:Type profileTree:ProfileTreeViewModel}}">
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@ -35,13 +33,13 @@
dd:DragDrop.IsDropTarget="True" dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{Binding}"> dd:DragDrop.DropHandler="{Binding}">
<i:Interaction.Behaviors> <i:Interaction.Behaviors>
<utilities:BindableSelectedItemBehavior SelectedItem="{Binding SelectedProfileElement, Mode=TwoWay}" /> <utilities:BindableSelectedItemBehavior SelectedItem="{Binding SelectedTreeItem, Mode=TwoWay}" />
</i:Interaction.Behaviors> </i:Interaction.Behaviors>
<TreeView.Resources> <TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type profileElement:FolderViewModel}" ItemsSource="{Binding Children}"> <HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Children}">
<ContentControl s:View.Model="{Binding}" /> <ContentControl s:View.Model="{Binding}" />
</HierarchicalDataTemplate> </HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type profileElement:LayerViewModel}" ItemsSource="{Binding Children}"> <HierarchicalDataTemplate DataType="{x:Type treeItem:LayerViewModel}" ItemsSource="{Binding Children}">
<ContentControl s:View.Model="{Binding}" /> <ContentControl s:View.Model="{Binding}" />
</HierarchicalDataTemplate> </HierarchicalDataTemplate>
</TreeView.Resources> </TreeView.Resources>

View File

@ -1,37 +1,36 @@
using System.Linq; using System;
using System.Linq;
using System.Windows; using System.Windows;
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.Core.Services.Storage.Interfaces; using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem;
using Artemis.UI.Events; using Artemis.UI.Services.Interfaces;
using Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement;
using GongSolutions.Wpf.DragDrop; using GongSolutions.Wpf.DragDrop;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
{ {
public class ProfileElementsViewModel : ProfileEditorPanelViewModel, IDropTarget public class ProfileTreeViewModel : ProfileEditorPanelViewModel, IDropTarget
{ {
private readonly IProfileService _profileService; private readonly IProfileEditorService _profileEditorService;
private readonly IEventAggregator _eventAggregator; private TreeItemViewModel _selectedTreeItem;
private ProfileElementViewModel _selectedProfileElement;
public ProfileElementsViewModel(IProfileService profileService, IEventAggregator eventAggregator) public ProfileTreeViewModel(IProfileEditorService profileEditorService)
{ {
_profileService = profileService; _profileEditorService = profileEditorService;
_eventAggregator = eventAggregator;
CreateRootFolderViewModel(); CreateRootFolderViewModel();
_profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged;
_profileEditorService.SelectedProfileElementChanged += OnSelectedElementChanged;
} }
public FolderViewModel RootFolder { get; set; } public FolderViewModel RootFolder { get; set; }
public ProfileElementViewModel SelectedProfileElement public TreeItemViewModel SelectedTreeItem
{ {
get => _selectedProfileElement; get => _selectedTreeItem;
set set
{ {
_selectedProfileElement = value; _selectedTreeItem = value;
_eventAggregator.Publish(new ProfileEditorSelectedElementChanged(_selectedProfileElement.ProfileElement)); _profileEditorService.ChangeSelectedProfileElement(value?.ProfileElement);
} }
} }
@ -55,8 +54,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements
public void Drop(IDropInfo dropInfo) public void Drop(IDropInfo dropInfo)
{ {
var source = (ProfileElementViewModel) dropInfo.Data; var source = (TreeItemViewModel) dropInfo.Data;
var target = (ProfileElementViewModel) dropInfo.TargetItem; var target = (TreeItemViewModel) dropInfo.TargetItem;
var dragDropType = GetDragDropType(dropInfo); var dragDropType = GetDragDropType(dropInfo);
switch (dragDropType) switch (dragDropType)
@ -73,8 +72,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements
break; break;
} }
_profileService.UpdateProfile(this.RootFolder.P); _profileEditorService.UpdateSelectedProfile();
ProfileEditorViewModel.OnProfileUpdated(this);
} }
// ReSharper disable once UnusedMember.Global - Called from view // ReSharper disable once UnusedMember.Global - Called from view
@ -89,36 +87,22 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements
RootFolder?.AddLayer(); RootFolder?.AddLayer();
} }
public override void ActiveProfileChanged()
{
CreateRootFolderViewModel();
base.ActiveProfileChanged();
}
public override void ProfileElementSelected(ProfileElementViewModel profileElement)
{
// Don't set it using the setter or that will trigger the event again
_selectedProfileElement = profileElement;
NotifyOfPropertyChange(() => SelectedProfileElement);
base.ProfileElementSelected(profileElement);
}
private void CreateRootFolderViewModel() private void CreateRootFolderViewModel()
{ {
if (!(ProfileEditorViewModel?.SelectedProfile?.Children?.FirstOrDefault() is Folder folder)) var firstChild = _profileEditorService.SelectedProfile?.Children?.FirstOrDefault();
if (!(firstChild is Folder folder))
{ {
RootFolder = null; RootFolder = null;
return; return;
} }
RootFolder = new FolderViewModel(null, folder, ProfileEditorViewModel); RootFolder = new FolderViewModel(null, folder, _profileEditorService);
} }
private static DragDropType GetDragDropType(IDropInfo dropInfo) private static DragDropType GetDragDropType(IDropInfo dropInfo)
{ {
var source = (ProfileElementViewModel) dropInfo.Data; var source = (TreeItemViewModel) dropInfo.Data;
var target = (ProfileElementViewModel) dropInfo.TargetItem; var target = (TreeItemViewModel) dropInfo.TargetItem;
if (source == target) if (source == target)
return DragDropType.None; return DragDropType.None;
@ -143,6 +127,24 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements
return DragDropType.None; return DragDropType.None;
} }
} }
#region Event handlers
private void OnSelectedElementChanged(object sender, EventArgs e)
{
var vms = RootFolder.GetAllChildren();
// Don't set it using the setter or that will trigger the event again
_selectedTreeItem = vms.FirstOrDefault(vm => vm.ProfileElement == _profileEditorService.SelectedProfileElement);
NotifyOfPropertyChange(() => SelectedTreeItem);
}
private void OnSelectedProfileChanged(object sender, EventArgs e)
{
CreateRootFolderViewModel();
}
#endregion
} }
public enum DragDropType public enum DragDropType

View File

@ -1,15 +1,14 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement.FolderView" <UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem.FolderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileElements"
xmlns:s="https://github.com/canton7/Stylet" xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:profileElement="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement" xmlns:treeItem="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type profileElement:FolderViewModel}}"> d:DataContext="{d:DesignInstance {x:Type treeItem:FolderViewModel}}">
<!-- Capture clicks on full tree view item --> <!-- Capture clicks on full tree view item -->
<StackPanel Margin="-10" Background="Transparent"> <StackPanel Margin="-10" Background="Transparent">
<StackPanel.ContextMenu> <StackPanel.ContextMenu>

View File

@ -0,0 +1,14 @@
using Artemis.Core.Models.Profile.Abstract;
using Artemis.UI.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{
public class FolderViewModel : TreeItemViewModel
{
public FolderViewModel(TreeItemViewModel parent, ProfileElement folder, IProfileEditorService profileEditorService) : base(parent, folder, profileEditorService)
{
}
public override bool SupportsChildren => true;
}
}

View File

@ -1,15 +1,14 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement.LayerView" <UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem.LayerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileElements"
xmlns:s="https://github.com/canton7/Stylet" xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:profileElement="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement" xmlns:treeItem="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type profileElement:LayerViewModel}}"> d:DataContext="{d:DesignInstance {x:Type treeItem:LayerViewModel}}">
<!-- Capture clicks on full tree view item --> <!-- Capture clicks on full tree view item -->
<StackPanel Margin="-10" Background="Transparent"> <StackPanel Margin="-10" Background="Transparent">
<StackPanel.ContextMenu> <StackPanel.ContextMenu>

View File

@ -0,0 +1,14 @@
using Artemis.Core.Models.Profile.Abstract;
using Artemis.UI.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{
public class LayerViewModel : TreeItemViewModel
{
public LayerViewModel(TreeItemViewModel parent, ProfileElement layer, IProfileEditorService profileEditorService) : base(parent, layer, profileEditorService)
{
}
public override bool SupportsChildren => false;
}
}

View File

@ -2,32 +2,47 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.Abstract;
using Artemis.UI.Exceptions; using Artemis.UI.Exceptions;
using Artemis.UI.Screens.Module.ProfileEditor.Dialogs; using Artemis.UI.Services.Interfaces;
using Stylet; using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{ {
public abstract class ProfileElementViewModel : PropertyChangedBase public abstract class TreeItemViewModel : PropertyChangedBase
{ {
protected ProfileElementViewModel(ProfileElementViewModel parent, Core.Models.Profile.Abstract.ProfileElement profileElement, ProfileEditorViewModel profileEditorViewModel) protected TreeItemViewModel(TreeItemViewModel parent, ProfileElement profileElement, IProfileEditorService profileEditorService)
{ {
Parent = parent; Parent = parent;
ProfileElement = profileElement; ProfileElement = profileElement;
ProfileEditorViewModel = profileEditorViewModel; ProfileEditorService = profileEditorService;
Children = new BindableCollection<ProfileElementViewModel>(); Children = new BindableCollection<TreeItemViewModel>();
UpdateProfileElements(); UpdateProfileElements();
} }
public TreeItemViewModel Parent { get; set; }
public ProfileElement ProfileElement { get; set; }
public IProfileEditorService ProfileEditorService { get; set; }
public abstract bool SupportsChildren { get; } public abstract bool SupportsChildren { get; }
public ProfileElementViewModel Parent { get; set; } public BindableCollection<TreeItemViewModel> Children { get; set; }
public ProfileEditorViewModel ProfileEditorViewModel { get; set; }
public Core.Models.Profile.Abstract.ProfileElement ProfileElement { get; set; } public List<TreeItemViewModel> GetAllChildren()
public BindableCollection<ProfileElementViewModel> Children { get; set; } {
var children = new List<TreeItemViewModel>();
foreach (var childFolder in Children)
{
// Add all children in this element
children.Add(childFolder);
// Add all children of children inside this element
children.AddRange(childFolder.GetAllChildren());
}
public void SetElementInFront(ProfileElementViewModel source) return children;
}
public void SetElementInFront(TreeItemViewModel source)
{ {
if (source.Parent != Parent) if (source.Parent != Parent)
{ {
@ -40,7 +55,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement
Parent.UpdateProfileElements(); Parent.UpdateProfileElements();
} }
public void SetElementBehind(ProfileElementViewModel source) public void SetElementBehind(TreeItemViewModel source)
{ {
if (source.Parent != Parent) if (source.Parent != Parent)
{ {
@ -53,24 +68,24 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement
Parent.UpdateProfileElements(); Parent.UpdateProfileElements();
} }
public void RemoveExistingElement(ProfileElementViewModel element) public void RemoveExistingElement(TreeItemViewModel treeItem)
{ {
if (!SupportsChildren) if (!SupportsChildren)
throw new ArtemisUIException("Cannot remove a child from a profile element of type " + ProfileElement.GetType().Name); throw new ArtemisUIException("Cannot remove a child from a profile element of type " + ProfileElement.GetType().Name);
ProfileElement.RemoveChild(element.ProfileElement); ProfileElement.RemoveChild(treeItem.ProfileElement);
Children.Remove(element); Children.Remove(treeItem);
element.Parent = null; treeItem.Parent = null;
} }
public void AddExistingElement(ProfileElementViewModel element) public void AddExistingElement(TreeItemViewModel treeItem)
{ {
if (!SupportsChildren) if (!SupportsChildren)
throw new ArtemisUIException("Cannot add a child to a profile element of type " + ProfileElement.GetType().Name); throw new ArtemisUIException("Cannot add a child to a profile element of type " + ProfileElement.GetType().Name);
ProfileElement.AddChild(element.ProfileElement); ProfileElement.AddChild(treeItem.ProfileElement);
Children.Add(element); Children.Add(treeItem);
element.Parent = this; treeItem.Parent = this;
} }
public void AddFolder() public void AddFolder()
@ -80,7 +95,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement
ProfileElement.AddChild(new Folder(ProfileElement.Profile, ProfileElement, "New folder")); ProfileElement.AddChild(new Folder(ProfileElement.Profile, ProfileElement, "New folder"));
UpdateProfileElements(); UpdateProfileElements();
ProfileEditorViewModel.OnProfileUpdated(); ProfileEditorService.UpdateSelectedProfile();
} }
public void AddLayer() public void AddLayer()
@ -90,40 +105,40 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement
ProfileElement.AddChild(new Layer(ProfileElement.Profile, ProfileElement, "New layer")); ProfileElement.AddChild(new Layer(ProfileElement.Profile, ProfileElement, "New layer"));
UpdateProfileElements(); UpdateProfileElements();
ProfileEditorViewModel.OnProfileUpdated(); ProfileEditorService.UpdateSelectedProfile();
} }
// ReSharper disable once UnusedMember.Global - Called from view // ReSharper disable once UnusedMember.Global - Called from view
public async Task RenameElement() public async Task RenameElement()
{ {
var result = await ProfileEditorViewModel.DialogService.ShowDialog<ProfileElementRenameViewModel>( // var result = await ProfileEditorService.DialogService.ShowDialog<ProfileElementRenameViewModel>(
new Dictionary<string, object> {{"profileElement", ProfileElement}} // new Dictionary<string, object> {{"profileElement", ProfileElement}}
); // );
if (result is string newName) // if (result is string newName)
{ // {
ProfileElement.Name = newName; // ProfileElement.Name = newName;
ProfileEditorViewModel.OnProfileUpdated(); // ProfileEditorService.UpdateSelectedProfile();
} // }
} }
// ReSharper disable once UnusedMember.Global - Called from view // ReSharper disable once UnusedMember.Global - Called from view
public async Task DeleteElement() public async Task DeleteElement()
{ {
var result = await ProfileEditorViewModel.DialogService.ShowConfirmDialog( // var result = await ProfileEditorService.DialogService.ShowConfirmDialog(
"Delete profile element", // "Delete profile element",
"Are you sure you want to delete this element? This cannot be undone." // "Are you sure you want to delete this element? This cannot be undone."
); // );
//
if (!result) // if (!result)
return; // return;
//
// Farewell, cruel world // // Farewell, cruel world
var parent = Parent; // var parent = Parent;
ProfileElement.Parent.RemoveChild(ProfileElement); // ProfileElement.Parent.RemoveChild(ProfileElement);
parent.RemoveExistingElement(this); // parent.RemoveExistingElement(this);
parent.UpdateProfileElements(); // parent.UpdateProfileElements();
//
ProfileEditorViewModel.OnProfileUpdated(); // ProfileEditorService.UpdateSelectedProfile();
} }
private void UpdateProfileElements() private void UpdateProfileElements()
@ -141,18 +156,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileElements.ProfileElement
{ {
foreach (var profileElement in ProfileElement.Children.OrderBy(c => c.Order)) foreach (var profileElement in ProfileElement.Children.OrderBy(c => c.Order))
{ {
ProfileElementViewModel existing = null; TreeItemViewModel existing = null;
if (profileElement is Folder folder) if (profileElement is Folder folder)
{ {
existing = Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder); existing = Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder);
if (existing == null) if (existing == null)
Children.Add(new FolderViewModel(this, folder, ProfileEditorViewModel)); Children.Add(new FolderViewModel(this, folder, ProfileEditorService));
} }
else if (profileElement is Layer layer) else if (profileElement is Layer layer)
{ {
existing = Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer); existing = Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer);
if (existing == null) if (existing == null)
Children.Add(new LayerViewModel(this, layer, ProfileEditorViewModel)); Children.Add(new LayerViewModel(this, layer, ProfileEditorService));
} }
existing?.UpdateProfileElements(); existing?.UpdateProfileElements();

View File

@ -9,17 +9,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{ {
public class ProfileDeviceViewModel : PropertyChangedBase public class ProfileDeviceViewModel : PropertyChangedBase
{ {
public ProfileDeviceViewModel(Device device) public ProfileDeviceViewModel(ArtemisDevice device)
{ {
Device = device; Device = device;
Leds = new ObservableCollection<ProfileLedViewModel>(); Leds = new ObservableCollection<ProfileLedViewModel>();
if (Device.RgbDevice != null) Task.Run(AddLedsAsync);
Task.Run(AddLedsAsync);
} }
public ObservableCollection<ProfileLedViewModel> Leds { get; set; } public ObservableCollection<ProfileLedViewModel> Leds { get; set; }
public Device Device { get; set; } public ArtemisDevice Device { get; set; }
public bool AddedLeds { get; private set; } public bool AddedLeds { get; private set; }
public double X public double X
@ -52,7 +51,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
private async Task AddLedsAsync() private async Task AddLedsAsync()
{ {
var index = 0; var index = 0;
foreach (var led in Device.RgbDevice.ToList()) foreach (var led in Device.Leds.ToList())
{ {
Execute.OnUIThreadSync(() => Leds.Add(new ProfileLedViewModel(led))); Execute.OnUIThreadSync(() => Leds.Add(new ProfileLedViewModel(led)));
if (index % 5 == 0) if (index % 5 == 0)

View File

@ -1,57 +1,60 @@
<UserControl <UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.ProfileLedView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:converters="clr-namespace:Artemis.UI.Converters" xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:visualization="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization" xmlns:visualization="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization"
xmlns:surfaceEditor="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Visualization" mc:Ignorable="d"
x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.ProfileLedView" d:DataContext="{d:DesignInstance {x:Type visualization:ProfileLedViewModel}}"
mc:Ignorable="d" d:DesignHeight="25" d:DesignWidth="25">
d:DataContext="{d:DesignInstance {x:Type visualization:ProfileLedViewModel}}"
d:DesignHeight="25" d:DesignWidth="25">
<UserControl.Resources> <UserControl.Resources>
<converters:NullToImageConverter x:Key="NullToImageConverter" /> <converters:NullToImageConverter x:Key="NullToImageConverter" />
<Style TargetType="{x:Type Path}" x:Key="DimStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDimmed}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Shape.Opacity)" To="0.2" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Shape.Opacity)" To="1" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources> </UserControl.Resources>
<Canvas Width="{Binding Led.ActualSize.Width, Mode=OneWay}" Height="{Binding Led.ActualSize.Height, Mode=OneWay}"> <Canvas Width="{Binding Led.RgbLed.ActualSize.Width, Mode=OneWay}" Height="{Binding Led.RgbLed.ActualSize.Height, Mode=OneWay}">
<Canvas.Background> <Canvas.Background>
<ImageBrush AlignmentX="Center" AlignmentY="Center" Stretch="Fill" <ImageBrush AlignmentX="Center" AlignmentY="Center" Stretch="Fill"
ImageSource="{Binding Led.Image, Converter={StaticResource NullToImageConverter}, Mode=OneWay}" /> ImageSource="{Binding Led.RgbLed.Image, Converter={StaticResource NullToImageConverter}, Mode=OneWay}" />
</Canvas.Background> </Canvas.Background>
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False"> <Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" Style="{StaticResource DimStyle}">
<Path.Fill> <Path.Fill>
<SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" Opacity="0.333" /> <SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" Opacity="0.333" />
</Path.Fill> </Path.Fill>
</Path> </Path>
<Path Data="{Binding StrokeGeometry, Mode=OneWay}" ClipToBounds="False"> <Path Data="{Binding StrokeGeometry, Mode=OneWay}" ClipToBounds="False" Style="{StaticResource DimStyle}">
<Path.Fill> <Path.Fill>
<SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" /> <SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" />
</Path.Fill> </Path.Fill>
</Path> </Path>
<!-- Selection -->
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="2"> <Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="2">
<Path.Style> <Path.Style>
<Style TargetType="{x:Type Path}"> <Style TargetType="{x:Type Path}">
<Style.Triggers> <Style.Triggers>
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.Hover}"> <DataTrigger Binding="{Binding IsSelected}" Value="True">
<DataTrigger.EnterActions> <DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="ToSelected" />
<BeginStoryboard x:Name="ToHover">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="{StaticResource IdealForegroundColor}" Duration="0:0:0.25" />
<ColorAnimation
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
To="{StaticResource IdealForegroundColor}" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.Selected}">
<DataTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="ToHover" />
<BeginStoryboard x:Name="ToSelected"> <BeginStoryboard x:Name="ToSelected">
<Storyboard> <Storyboard>
<ColorAnimation <ColorAnimation
@ -63,27 +66,15 @@
</Storyboard> </Storyboard>
</BeginStoryboard> </BeginStoryboard>
</DataTrigger.EnterActions> </DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding SelectionStatus}" Value="{x:Static surfaceEditor:SelectionStatus.None}">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.25">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions> <DataTrigger.ExitActions>
<BeginStoryboard> <BeginStoryboard>
<Storyboard> <Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.25" > <ColorAnimation
<DoubleAnimation.EasingFunction> Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
<QuadraticEase EasingMode="EaseOut" /> To="Transparent" Duration="0:0:0.25" />
</DoubleAnimation.EasingFunction> <ColorAnimation
</DoubleAnimation> Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
To="Transparent" Duration="0:0:0.25" />
</Storyboard> </Storyboard>
</BeginStoryboard> </BeginStoryboard>
</DataTrigger.ExitActions> </DataTrigger.ExitActions>

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using Artemis.Core.Models.Surface;
using Artemis.UI.Extensions; using Artemis.UI.Extensions;
using Artemis.UI.Screens.SurfaceEditor.Visualization;
using RGB.NET.Core; using RGB.NET.Core;
using Stylet; using Stylet;
using Color = System.Windows.Media.Color; using Color = System.Windows.Media.Color;
@ -11,21 +11,23 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{ {
public class ProfileLedViewModel : PropertyChangedBase public class ProfileLedViewModel : PropertyChangedBase
{ {
public ProfileLedViewModel(Led led) public ProfileLedViewModel(ArtemisLed led)
{ {
Led = led; Led = led;
// Don't want ActualLocation here since rotation is done in XAML // Don't want ActualLocation here since rotation is done in XAML
X = Led.Location.X * Led.Device.Scale.Horizontal; X = led.RgbLed.Location.X * led.RgbLed.Device.Scale.Horizontal;
Y = Led.Location.Y * Led.Device.Scale.Vertical; Y = led.RgbLed.Location.Y * led.RgbLed.Device.Scale.Vertical;
Width = Led.ActualSize.Width; Width = led.RgbLed.ActualSize.Width;
Height = Led.ActualSize.Height; Height = led.RgbLed.ActualSize.Height;
Execute.PostToUIThread(CreateLedGeometry); Execute.PostToUIThread(CreateLedGeometry);
} }
public Led Led { get; } public ArtemisLed Led { get; }
public SelectionStatus SelectionStatus { get; set; }
public bool IsSelected { get; set; }
public bool IsDimmed { get; set; }
public double X { get; } public double X { get; }
public double Y { get; } public double Y { get; }
@ -36,18 +38,19 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
public Geometry StrokeGeometry { get; private set; } public Geometry StrokeGeometry { get; private set; }
public Color DisplayColor { get; private set; } public Color DisplayColor { get; private set; }
private void CreateLedGeometry() private void CreateLedGeometry()
{ {
switch (Led.Shape) switch (Led.RgbLed.Shape)
{ {
case Shape.Custom: case Shape.Custom:
if (Led.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad) if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
CreateCustomGeometry(2.0); CreateCustomGeometry(2.0);
else else
CreateCustomGeometry(1.0); CreateCustomGeometry(1.0);
break; break;
case Shape.Rectangle: case Shape.Rectangle:
if (Led.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad) if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
CreateKeyCapGeometry(); CreateKeyCapGeometry();
else else
CreateRectangleGeometry(); CreateRectangleGeometry();
@ -86,7 +89,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{ {
DisplayGeometry = Geometry.Combine( DisplayGeometry = Geometry.Combine(
Geometry.Empty, Geometry.Empty,
Geometry.Parse(Led.ShapeData), Geometry.Parse(Led.RgbLed.ShapeData),
GeometryCombineMode.Union, GeometryCombineMode.Union,
new TransformGroup new TransformGroup
{ {
@ -106,7 +109,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
public void Update() public void Update()
{ {
var newColor = Led.Color.ToMediaColor(); var newColor = Led.RgbLed.Color.ToMediaColor();
Execute.PostToUIThread(() => Execute.PostToUIThread(() =>
{ {
if (!DisplayColor.Equals(newColor)) if (!DisplayColor.Equals(newColor))

View File

@ -5,6 +5,7 @@ using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Artemis.Core.Events; using Artemis.Core.Events;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Surface; using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins.Models; using Artemis.Core.Plugins.Models;
using Artemis.Core.Services; using Artemis.Core.Services;
@ -13,21 +14,26 @@ using Artemis.UI.Events;
using Artemis.UI.Extensions; using Artemis.UI.Extensions;
using Artemis.UI.Screens.Shared; using Artemis.UI.Screens.Shared;
using Artemis.UI.Screens.SurfaceEditor; using Artemis.UI.Screens.SurfaceEditor;
using Artemis.UI.Screens.SurfaceEditor.Visualization; using Artemis.UI.Services.Interfaces;
using RGB.NET.Core; using RGB.NET.Core;
using Stylet; using Stylet;
using Point = System.Windows.Point; using Point = System.Windows.Point;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{ {
public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle<ProfileEditorSelectedElementChanged>, IHandle<MainWindowFocusChanged> public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>
{ {
private readonly IProfileEditorService _profileEditorService;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
private readonly ISurfaceService _surfaceService; private readonly ISurfaceService _surfaceService;
private TimerUpdateTrigger _updateTrigger; private TimerUpdateTrigger _updateTrigger;
public ProfileViewModel(ISurfaceService surfaceService, ISettingsService settingsService, IEventAggregator eventAggregator) public ProfileViewModel(IProfileEditorService profileEditorService,
ISurfaceService surfaceService,
ISettingsService settingsService,
IEventAggregator eventAggregator)
{ {
_profileEditorService = profileEditorService;
_surfaceService = surfaceService; _surfaceService = surfaceService;
_settingsService = settingsService; _settingsService = settingsService;
Devices = new ObservableCollection<ProfileDeviceViewModel>(); Devices = new ObservableCollection<ProfileDeviceViewModel>();
@ -42,6 +48,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
ApplySurfaceConfiguration(surfaceService.ActiveSurface); ApplySurfaceConfiguration(surfaceService.ActiveSurface);
CreateUpdateTrigger(); CreateUpdateTrigger();
_profileEditorService.SelectedProfileElementChanged += OnSelectedProfileElementChanged;
_profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementChanged;
eventAggregator.Subscribe(this); eventAggregator.Subscribe(this);
} }
@ -71,7 +79,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
ApplySurfaceConfiguration(e.Surface); ApplySurfaceConfiguration(e.Surface);
} }
private void ApplySurfaceConfiguration(Surface surface) private void ApplySurfaceConfiguration(ArtemisSurface surface)
{ {
// Make sure all devices have an up-to-date VM // Make sure all devices have an up-to-date VM
foreach (var surfaceDeviceConfiguration in surface.Devices) foreach (var surfaceDeviceConfiguration in surface.Devices)
@ -120,11 +128,27 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
} }
} }
private void UpdateLedsDimStatus()
{
if (HighlightSelectedLayer.Value && _profileEditorService.SelectedProfileElement is Layer layer)
{
foreach (var led in Devices.SelectMany(d => d.Leds))
led.IsDimmed = !layer.Leds.Contains(led.Led);
}
else
{
foreach (var led in Devices.SelectMany(d => d.Leds))
led.IsDimmed = false;
}
}
protected override void OnActivate() protected override void OnActivate()
{ {
HighlightSelectedLayer = _settingsService.GetSetting("ProfileEditor.HighlightSelectedLayer", true); HighlightSelectedLayer = _settingsService.GetSetting("ProfileEditor.HighlightSelectedLayer", true);
PauseRenderingOnFocusLoss = _settingsService.GetSetting("ProfileEditor.PauseRenderingOnFocusLoss", true); PauseRenderingOnFocusLoss = _settingsService.GetSetting("ProfileEditor.PauseRenderingOnFocusLoss", true);
HighlightSelectedLayer.SettingChanged += HighlightSelectedLayerOnSettingChanged;
_updateTrigger.Start(); _updateTrigger.Start();
base.OnActivate(); base.OnActivate();
} }
@ -138,6 +162,45 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
base.OnDeactivate(); base.OnDeactivate();
} }
#region Context menu actions
public bool CanApplyToLayer { get; set; }
public void CreateLayer()
{
}
public void ApplyToLayer()
{
if (!(_profileEditorService.SelectedProfileElement is Layer layer))
return;
layer.ClearLeds();
layer.AddLeds(Devices.SelectMany(d => d.Leds).Where(vm => vm.IsSelected).Select(vm => vm.Led));
_profileEditorService.UpdateSelectedProfileElement();
}
public void SelectAll()
{
foreach (var ledVm in Devices.SelectMany(d => d.Leds))
ledVm.IsSelected = true;
}
public void InverseSelection()
{
foreach (var ledVm in Devices.SelectMany(d => d.Leds))
ledVm.IsSelected = !ledVm.IsSelected;
}
public void ClearSelection()
{
foreach (var ledVm in Devices.SelectMany(d => d.Leds))
ledVm.IsSelected = false;
}
#endregion
#region Selection #region Selection
private MouseDragStatus _mouseDragStatus; private MouseDragStatus _mouseDragStatus;
@ -188,10 +251,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{ {
foreach (var profileLedViewModel in device.Leds) foreach (var profileLedViewModel in device.Leds)
{ {
if (PanZoomViewModel.TransformContainingRect(profileLedViewModel.Led.AbsoluteLedRectangle.ToWindowsRect(1)).IntersectsWith(selectedRect)) if (PanZoomViewModel.TransformContainingRect(profileLedViewModel.Led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1)).IntersectsWith(selectedRect))
profileLedViewModel.SelectionStatus = SelectionStatus.Selected; profileLedViewModel.IsSelected = true;
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
profileLedViewModel.SelectionStatus = SelectionStatus.None; profileLedViewModel.IsSelected = false;
} }
} }
@ -210,10 +273,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{ {
foreach (var profileLedViewModel in device.Leds) foreach (var profileLedViewModel in device.Leds)
{ {
if (PanZoomViewModel.TransformContainingRect(profileLedViewModel.Led.AbsoluteLedRectangle.ToWindowsRect(1)).IntersectsWith(selectedRect)) if (PanZoomViewModel.TransformContainingRect(profileLedViewModel.Led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1)).IntersectsWith(selectedRect))
profileLedViewModel.SelectionStatus = SelectionStatus.Selected; profileLedViewModel.IsSelected = true;
else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) else if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
profileLedViewModel.SelectionStatus = SelectionStatus.None; profileLedViewModel.IsSelected = false;
} }
} }
} }
@ -259,17 +322,24 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
#endregion #endregion
#region EventAggregator handlers #region Event handlers
public void Handle(ProfileEditorSelectedElementChanged message) private void HighlightSelectedLayerOnSettingChanged(object sender, EventArgs e)
{ {
if (HighlightSelectedLayer.Value) UpdateLedsDimStatus();
{
}
} }
public void Handle(MainWindowFocusChanged message) private void OnSelectedProfileElementChanged(object sender, EventArgs e)
{ {
UpdateLedsDimStatus();
CanApplyToLayer = _profileEditorService.SelectedProfileElement is Layer;
}
public void Handle(MainWindowFocusChangedEvent message)
{
if (PauseRenderingOnFocusLoss == null || ScreenState != ScreenState.Active)
return;
if (PauseRenderingOnFocusLoss.Value && !message.IsFocused) if (PauseRenderingOnFocusLoss.Value && !message.IsFocused)
_updateTrigger.Stop(); _updateTrigger.Stop();
else if (PauseRenderingOnFocusLoss.Value && message.IsFocused) else if (PauseRenderingOnFocusLoss.Value && message.IsFocused)

View File

@ -143,7 +143,7 @@ namespace Artemis.UI.Screens
return; return;
_lostFocus = true; _lostFocus = true;
_eventAggregator.Publish(new MainWindowFocusChanged(false)); _eventAggregator.Publish(new MainWindowFocusChangedEvent(false));
} }
public void WindowActivated() public void WindowActivated()
@ -152,7 +152,7 @@ namespace Artemis.UI.Screens
return; return;
_lostFocus = false; _lostFocus = false;
_eventAggregator.Publish(new MainWindowFocusChanged(true)); _eventAggregator.Publish(new MainWindowFocusChangedEvent(true));
} }
} }
} }

View File

@ -9,7 +9,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
{ {
private readonly IDeviceService _deviceService; private readonly IDeviceService _deviceService;
public DeviceSettingsViewModel(Device device, IDeviceService deviceService) public DeviceSettingsViewModel(ArtemisDevice device, IDeviceService deviceService)
{ {
_deviceService = deviceService; _deviceService = deviceService;
Device = device; Device = device;
@ -20,7 +20,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
IsDeviceEnabled = true; IsDeviceEnabled = true;
} }
public Device Device { get; } public ArtemisDevice Device { get; }
public string Type { get; set; } public string Type { get; set; }
public string Name { get; set; } public string Name { get; set; }

View File

@ -198,7 +198,7 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<ListBox Grid.Row="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding SurfaceConfigurations}" SelectedItem="{Binding SelectedSurface}"> <ListBox Grid.Row="0" HorizontalContentAlignment="Stretch" ItemsSource="{Binding SurfaceConfigurations}" SelectedItem="{Binding SelectedSurface}">
<ListBox.Resources> <ListBox.Resources>
<DataTemplate DataType="{x:Type models:Surface}"> <DataTemplate DataType="{x:Type models:ArtemisSurface}">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />

View File

@ -29,7 +29,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
public SurfaceEditorViewModel(ISurfaceService surfaceService, IDialogService dialogService, ISettingsService settingsService, IDeviceService deviceService) public SurfaceEditorViewModel(ISurfaceService surfaceService, IDialogService dialogService, ISettingsService settingsService, IDeviceService deviceService)
{ {
Devices = new ObservableCollection<SurfaceDeviceViewModel>(); Devices = new ObservableCollection<SurfaceDeviceViewModel>();
SurfaceConfigurations = new ObservableCollection<Surface>(); SurfaceConfigurations = new ObservableCollection<ArtemisSurface>();
SelectionRectangle = new RectangleGeometry(); SelectionRectangle = new RectangleGeometry();
PanZoomViewModel = new PanZoomViewModel(); PanZoomViewModel = new PanZoomViewModel();
Cursor = null; Cursor = null;
@ -41,13 +41,13 @@ namespace Artemis.UI.Screens.SurfaceEditor
} }
public ObservableCollection<SurfaceDeviceViewModel> Devices { get; set; } public ObservableCollection<SurfaceDeviceViewModel> Devices { get; set; }
public ObservableCollection<Surface> SurfaceConfigurations { get; set; } public ObservableCollection<ArtemisSurface> SurfaceConfigurations { get; set; }
public RectangleGeometry SelectionRectangle { get; set; } public RectangleGeometry SelectionRectangle { get; set; }
public PanZoomViewModel PanZoomViewModel { get; set; } public PanZoomViewModel PanZoomViewModel { get; set; }
public PluginSetting<GridLength> SurfaceListWidth { get; set; } public PluginSetting<GridLength> SurfaceListWidth { get; set; }
public Cursor Cursor { get; set; } public Cursor Cursor { get; set; }
public Surface SelectedSurface public ArtemisSurface SelectedSurface
{ {
get => _selectedSurface; get => _selectedSurface;
set set
@ -62,7 +62,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
public string Title => "Surface Editor"; public string Title => "Surface Editor";
public Surface CreateSurfaceConfiguration(string name) public ArtemisSurface CreateSurfaceConfiguration(string name)
{ {
var config = _surfaceService.CreateSurfaceConfiguration(name); var config = _surfaceService.CreateSurfaceConfiguration(name);
Execute.PostToUIThread(() => SurfaceConfigurations.Add(config)); Execute.PostToUIThread(() => SurfaceConfigurations.Add(config));
@ -148,7 +148,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
#region Configuration management #region Configuration management
public async Task DeleteSurfaceConfiguration(Surface surface) public async Task DeleteSurfaceConfiguration(ArtemisSurface surface)
{ {
var result = await _dialogService.ShowConfirmDialogAt( var result = await _dialogService.ShowConfirmDialogAt(
"SurfaceListDialogHost", "SurfaceListDialogHost",
@ -240,7 +240,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
private MouseDragStatus _mouseDragStatus; private MouseDragStatus _mouseDragStatus;
private Point _mouseDragStartPoint; private Point _mouseDragStartPoint;
private Surface _selectedSurface; private ArtemisSurface _selectedSurface;
// ReSharper disable once UnusedMember.Global - Called from view // ReSharper disable once UnusedMember.Global - Called from view
public void EditorGridMouseClick(object sender, MouseButtonEventArgs e) public void EditorGridMouseClick(object sender, MouseButtonEventArgs e)

View File

@ -13,7 +13,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
private double _dragOffsetX; private double _dragOffsetX;
private double _dragOffsetY; private double _dragOffsetY;
public SurfaceDeviceViewModel(Device device) public SurfaceDeviceViewModel(ArtemisDevice device)
{ {
Device = device; Device = device;
_leds = new List<SurfaceLedViewModel>(); _leds = new List<SurfaceLedViewModel>();
@ -25,7 +25,7 @@ namespace Artemis.UI.Screens.SurfaceEditor.Visualization
} }
} }
public Device Device { get; set; } public ArtemisDevice Device { get; set; }
public SelectionStatus SelectionStatus { get; set; } public SelectionStatus SelectionStatus { get; set; }
public Cursor Cursor { get; set; } public Cursor Cursor { get; set; }

View File

@ -0,0 +1,22 @@
using System;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.Abstract;
namespace Artemis.UI.Services.Interfaces
{
public interface IProfileEditorService : IArtemisUIService
{
Profile SelectedProfile { get; }
ProfileElement SelectedProfileElement { get; }
void ChangeSelectedProfile(Profile profile);
void UpdateSelectedProfile();
void ChangeSelectedProfileElement(ProfileElement profileElement);
void UpdateSelectedProfileElement();
event EventHandler SelectedProfileChanged;
event EventHandler SelectedProfileUpdated;
event EventHandler SelectedProfileElementChanged;
event EventHandler SelectedProfileElementUpdated;
}
}

View File

@ -0,0 +1,70 @@
using System;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.Abstract;
using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Services.Interfaces;
namespace Artemis.UI.Services
{
public class ProfileEditorService : IProfileEditorService
{
private readonly IProfileService _profileService;
public ProfileEditorService(IProfileService profileService)
{
_profileService = profileService;
}
public Profile SelectedProfile { get; private set; }
public ProfileElement SelectedProfileElement { get; private set; }
public void ChangeSelectedProfile(Profile profile)
{
SelectedProfile = profile;
OnSelectedProfileChanged();
}
public void UpdateSelectedProfile()
{
_profileService.UpdateProfile(SelectedProfile, false);
OnSelectedProfileElementUpdated();
}
public void ChangeSelectedProfileElement(ProfileElement profileElement)
{
SelectedProfileElement = profileElement;
OnSelectedProfileElementChanged();
}
public void UpdateSelectedProfileElement()
{
_profileService.UpdateProfile(SelectedProfile, true);
OnSelectedProfileElementUpdated();
}
public event EventHandler SelectedProfileChanged;
public event EventHandler SelectedProfileUpdated;
public event EventHandler SelectedProfileElementChanged;
public event EventHandler SelectedProfileElementUpdated;
protected virtual void OnSelectedProfileElementUpdated()
{
SelectedProfileElementUpdated?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnSelectedProfileElementChanged()
{
SelectedProfileElementChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnSelectedProfileUpdated()
{
SelectedProfileUpdated?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnSelectedProfileChanged()
{
SelectedProfileChanged?.Invoke(this, EventArgs.Empty);
}
}
}