mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
UI - Added Avalonia projects
This commit is contained in:
parent
c45f1d9130
commit
1784d2b8b5
13
src/.idea/.idea.Artemis/.idea/.gitignore
generated
vendored
Normal file
13
src/.idea/.idea.Artemis/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/modules.xml
|
||||
/contentModel.xml
|
||||
/.idea.Artemis.iml
|
||||
/projectSettingsUpdater.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
1
src/.idea/.idea.Artemis/.idea/.name
generated
Normal file
1
src/.idea/.idea.Artemis/.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
Artemis
|
||||
17
src/.idea/.idea.Artemis/.idea/avalonia.xml
generated
Normal file
17
src/.idea/.idea.Artemis/.idea/avalonia.xml
generated
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AvaloniaProject">
|
||||
<option name="projectPerEditor">
|
||||
<map>
|
||||
<entry key="Artemis.UI.Avalonia/App.axaml" value="Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj" />
|
||||
<entry key="Artemis.UI.Avalonia/Screens/Main/Sidebar/Views/SidebarView.axaml" value="Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj" />
|
||||
<entry key="Artemis.UI.Avalonia/Screens/Main/Views/MainWindow.axaml" value="Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj" />
|
||||
<entry key="Artemis.UI.Avalonia/Screens/Sidebar/SidebarView.axaml" value="Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj" />
|
||||
<entry key="Artemis.UI.Avalonia/Screens/Sidebar/Views/SidebarCategoryView.axaml" value="Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj" />
|
||||
<entry key="Artemis.UI.Avalonia/Screens/Sidebar/Views/SidebarProfileConfigurationView.axaml" value="Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj" />
|
||||
<entry key="Artemis.UI.Avalonia/Screens/SidebarView.axaml" value="Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj" />
|
||||
<entry key="Artemis.UI.Avalonia/Views/MainWindow.axaml" value="Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj" />
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
4
src/.idea/.idea.Artemis/.idea/encodings.xml
generated
Normal file
4
src/.idea/.idea.Artemis/.idea/encodings.xml
generated
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||
</project>
|
||||
8
src/.idea/.idea.Artemis/.idea/indexLayout.xml
generated
Normal file
8
src/.idea/.idea.Artemis/.idea/indexLayout.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
||||
6
src/.idea/.idea.Artemis/.idea/vcs.xml
generated
Normal file
6
src/.idea/.idea.Artemis/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
||||
/// <returns>The RGB.NET color</returns>
|
||||
public static Color ToRgbColor(this SKColor color)
|
||||
{
|
||||
return new(color.Alpha, color.Red, color.Green, color.Blue);
|
||||
return new Color(color.Alpha, color.Red, color.Green, color.Blue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -49,7 +49,7 @@ namespace Artemis.Core
|
||||
/// <returns>The sum of the two colors</returns>
|
||||
public static SKColor Sum(this SKColor a, SKColor b)
|
||||
{
|
||||
return new(
|
||||
return new SKColor(
|
||||
ClampToByte(a.Red + b.Red),
|
||||
ClampToByte(a.Green + b.Green),
|
||||
ClampToByte(a.Blue + b.Blue),
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Artemis.Core
|
||||
|
||||
protected DataModelConditionPart()
|
||||
{
|
||||
Children = new(_children);
|
||||
Children = new ReadOnlyCollection<DataModelConditionPart>(_children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -18,7 +18,7 @@ namespace Artemis.Core
|
||||
{
|
||||
DataBinding = dataBinding;
|
||||
Entity = entity;
|
||||
Conditions = new(_conditions);
|
||||
Conditions = new ReadOnlyCollection<DataBindingCondition<TLayerProperty, TProperty>>(_conditions);
|
||||
Load();
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
||||
{
|
||||
DataBinding = dataBinding;
|
||||
Entity = entity;
|
||||
Modifiers = new(_modifiers);
|
||||
Modifiers = new ReadOnlyCollection<DataBindingModifier<TLayerProperty, TProperty>>(_modifiers);
|
||||
Load();
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ namespace Artemis.Core
|
||||
_baseValue = default!;
|
||||
|
||||
_keyframes = new List<LayerPropertyKeyframe<T>>();
|
||||
Keyframes = new(_keyframes);
|
||||
Keyframes = new ReadOnlyCollection<LayerPropertyKeyframe<T>>(_keyframes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -66,7 +66,7 @@ namespace Artemis.Core
|
||||
/// <inheritdoc />
|
||||
public KeyframeEntity GetKeyframeEntity()
|
||||
{
|
||||
return new()
|
||||
return new KeyframeEntity
|
||||
{
|
||||
Value = CoreJson.SerializeObject(Value),
|
||||
Position = Position,
|
||||
|
||||
@ -38,8 +38,8 @@ namespace Artemis.Core
|
||||
_layerProperties = new List<ILayerProperty>();
|
||||
_layerPropertyGroups = new List<LayerPropertyGroup>();
|
||||
|
||||
LayerProperties = new(_layerProperties);
|
||||
LayerPropertyGroups = new(_layerPropertyGroups);
|
||||
LayerProperties = new ReadOnlyCollection<ILayerProperty>(_layerProperties);
|
||||
LayerPropertyGroups = new ReadOnlyCollection<LayerPropertyGroup>(_layerPropertyGroups);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -24,14 +24,14 @@ namespace Artemis.Core
|
||||
{
|
||||
_name = name;
|
||||
Entity = new ProfileCategoryEntity();
|
||||
ProfileConfigurations = new(_profileConfigurations);
|
||||
ProfileConfigurations = new ReadOnlyCollection<ProfileConfiguration>(_profileConfigurations);
|
||||
}
|
||||
|
||||
internal ProfileCategory(ProfileCategoryEntity entity)
|
||||
{
|
||||
_name = null!;
|
||||
Entity = entity;
|
||||
ProfileConfigurations = new(_profileConfigurations);
|
||||
ProfileConfigurations = new ReadOnlyCollection<ProfileConfiguration>(_profileConfigurations);
|
||||
|
||||
Load();
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ namespace Artemis.Core
|
||||
{
|
||||
_profile = profile;
|
||||
ChildrenList = new List<ProfileElement>();
|
||||
Children = new(ChildrenList);
|
||||
Children = new ReadOnlyCollection<ProfileElement>(ChildrenList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -24,7 +24,7 @@ namespace Artemis.Core
|
||||
Timeline = new Timeline();
|
||||
ExpandedPropertyGroups = new List<string>();
|
||||
LayerEffectsList = new List<BaseLayerEffect>();
|
||||
LayerEffects = new(LayerEffectsList);
|
||||
LayerEffects = new ReadOnlyCollection<BaseLayerEffect>(LayerEffectsList);
|
||||
|
||||
LayerEffectStore.LayerEffectAdded += LayerEffectStoreOnLayerEffectAdded;
|
||||
LayerEffectStore.LayerEffectRemoved += LayerEffectStoreOnLayerEffectRemoved;
|
||||
|
||||
@ -24,7 +24,7 @@ namespace Artemis.Core
|
||||
MainSegmentLength = TimeSpan.FromSeconds(5);
|
||||
|
||||
_extraTimelines = new List<Timeline>();
|
||||
ExtraTimelines = new(_extraTimelines);
|
||||
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||
|
||||
Save();
|
||||
}
|
||||
@ -33,7 +33,7 @@ namespace Artemis.Core
|
||||
{
|
||||
Entity = entity;
|
||||
_extraTimelines = new List<Timeline>();
|
||||
ExtraTimelines = new(_extraTimelines);
|
||||
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||
|
||||
Load();
|
||||
}
|
||||
@ -47,7 +47,7 @@ namespace Artemis.Core
|
||||
EndSegmentLength = Parent.EndSegmentLength;
|
||||
|
||||
_extraTimelines = new List<Timeline>();
|
||||
ExtraTimelines = new(_extraTimelines);
|
||||
ExtraTimelines = new ReadOnlyCollection<Timeline>(_extraTimelines);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core.LayerBrushes
|
||||
protected LayerBrushProvider()
|
||||
{
|
||||
_layerBrushDescriptors = new List<LayerBrushDescriptor>();
|
||||
LayerBrushDescriptors = new(_layerBrushDescriptors);
|
||||
LayerBrushDescriptors = new ReadOnlyCollection<LayerBrushDescriptor>(_layerBrushDescriptors);
|
||||
Disabled += OnDisabled;
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ namespace Artemis.Core.LayerEffects
|
||||
protected LayerEffectProvider()
|
||||
{
|
||||
_layerEffectDescriptors = new List<LayerEffectDescriptor>();
|
||||
LayerEffectDescriptors = new(_layerEffectDescriptors);
|
||||
LayerEffectDescriptors = new ReadOnlyCollection<LayerEffectDescriptor>(_layerEffectDescriptors);
|
||||
Disabled += OnDisabled;
|
||||
}
|
||||
|
||||
|
||||
@ -27,8 +27,8 @@ namespace Artemis.Core.Modules
|
||||
Module = null!;
|
||||
DataModelDescription = null!;
|
||||
|
||||
ActivePaths = new(_activePaths);
|
||||
DynamicChildren = new(_dynamicChildren);
|
||||
ActivePaths = new ReadOnlyCollection<DataModelPath>(_activePaths);
|
||||
DynamicChildren = new ReadOnlyDictionary<string, DynamicChild>(_dynamicChildren);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -117,7 +117,7 @@ namespace Artemis.Core.Modules
|
||||
protected Module()
|
||||
{
|
||||
DefaultProfilePaths = new ReadOnlyCollection<(DefaultCategoryName, string)>(_defaultProfilePaths);
|
||||
HiddenProperties = new(HiddenPropertiesList);
|
||||
HiddenProperties = new ReadOnlyCollection<PropertyInfo>(HiddenPropertiesList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -237,7 +237,7 @@ namespace Artemis.Core.Modules
|
||||
/// <returns></returns>
|
||||
public virtual DataModelPropertyAttribute GetDataModelDescription()
|
||||
{
|
||||
return new() {Name = Info.Name, Description = Info.Description};
|
||||
return new DataModelPropertyAttribute {Name = Info.Name, Description = Info.Description};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -31,8 +31,8 @@ namespace Artemis.Core
|
||||
_features = new List<PluginFeatureInfo>();
|
||||
_profilers = new List<Profiler>();
|
||||
|
||||
Features = new(_features);
|
||||
Profilers = new(_profilers);
|
||||
Features = new ReadOnlyCollection<PluginFeatureInfo>(_features);
|
||||
Profilers = new ReadOnlyCollection<Profiler>(_profilers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -70,7 +70,7 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public TimeSpan GetLast()
|
||||
{
|
||||
return new(_last);
|
||||
return new TimeSpan(_last);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -46,7 +46,7 @@ namespace Artemis.Core.ScriptingProviders
|
||||
{
|
||||
protected ScriptingProvider()
|
||||
{
|
||||
Scripts = new(InternalScripts);
|
||||
Scripts = new ReadOnlyCollection<Script>(InternalScripts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -66,7 +66,7 @@ namespace Artemis.Core.Services
|
||||
float bestDarkMutedScore = 0;
|
||||
|
||||
//ugly but at least we only loop through the enumerable once ¯\_(ツ)_/¯
|
||||
foreach (var color in colors)
|
||||
foreach (SKColor color in colors)
|
||||
{
|
||||
static void SetIfBetterScore(ref float bestScore, ref SKColor bestColor, SKColor newColor, ColorType type, bool ignoreLimits)
|
||||
{
|
||||
@ -86,7 +86,7 @@ namespace Artemis.Core.Services
|
||||
SetIfBetterScore(ref bestDarkMutedScore, ref bestDarkMutedColor, color, ColorType.DarkMuted, ignoreLimits);
|
||||
}
|
||||
|
||||
return new()
|
||||
return new ColorSwatch
|
||||
{
|
||||
Vibrant = bestVibrantColor,
|
||||
LightVibrant = bestLightVibrantColor,
|
||||
|
||||
@ -435,7 +435,7 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Warning(new ArtemisPluginException(plugin, "Failed to instantiate feature", e), "Failed to instantiate feature", plugin);
|
||||
_logger.Warning(new ArtemisPluginException(plugin, "Failed to instantiate feature", e), "Failed to instantiate feature from plugin {plugin}", plugin);
|
||||
featureInfo.LoadException = e;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ namespace Artemis.Core.Services
|
||||
_profileService = profileService;
|
||||
|
||||
InternalGlobalScripts = new List<GlobalScript>();
|
||||
GlobalScripts = new(InternalGlobalScripts);
|
||||
GlobalScripts = new ReadOnlyCollection<GlobalScript>(InternalGlobalScripts);
|
||||
|
||||
_pluginManagementService.PluginFeatureEnabled += PluginManagementServiceOnPluginFeatureToggled;
|
||||
_pluginManagementService.PluginFeatureDisabled += PluginManagementServiceOnPluginFeatureToggled;
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.10.7" />
|
||||
<PackageReference Include="Avalonia.Svg.Skia" Version="0.10.7.2" />
|
||||
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.7.1" />
|
||||
<PackageReference Include="Avalonia.Xaml.Interactions" Version="0.10.7.1" />
|
||||
<PackageReference Include="Avalonia.Xaml.Interactivity" Version="0.10.7.1" />
|
||||
<PackageReference Include="Material.Icons.Avalonia" Version="1.0.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Material.Icons.Avalonia">
|
||||
<HintPath>..\..\..\..\Users\Robert\.nuget\packages\material.icons.avalonia\1.0.2\lib\netstandard2.0\Material.Icons.Avalonia.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
120
src/Artemis.UI.Avalonia.Shared/Controls/DeviceVisualizer.cs
Normal file
120
src/Artemis.UI.Avalonia.Shared/Controls/DeviceVisualizer.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Shared.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Visualizes an <see cref="ArtemisDevice" /> with optional per-LED colors
|
||||
/// </summary>
|
||||
public class DeviceVisualizer : Control
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ArtemisDevice" /> to display
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<ArtemisDevice?> DeviceProperty =
|
||||
AvaloniaProperty.Register<ProfileConfigurationIcon, ArtemisDevice?>(nameof(Device));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="ArtemisDevice" /> to display
|
||||
/// </summary>
|
||||
public ArtemisDevice? Device
|
||||
{
|
||||
get => GetValue(DeviceProperty);
|
||||
set => SetValue(DeviceProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets boolean indicating whether or not to show per-LED colors
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<bool> ShowColorsProperty =
|
||||
AvaloniaProperty.Register<ProfileConfigurationIcon, bool>(nameof(ShowColors));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether or not to show per-LED colors
|
||||
/// </summary>
|
||||
public bool ShowColors
|
||||
{
|
||||
get => GetValue(ShowColorsProperty);
|
||||
set => SetValue(ShowColorsProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of LEDs to highlight
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<ObservableCollection<ArtemisLed>?> HighlightedLedsProperty =
|
||||
AvaloniaProperty.Register<ProfileConfigurationIcon, ObservableCollection<ArtemisLed>?>(nameof(HighlightedLeds));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a list of LEDs to highlight
|
||||
/// </summary>
|
||||
public ObservableCollection<ArtemisLed>? HighlightedLeds
|
||||
{
|
||||
get => GetValue(HighlightedLedsProperty);
|
||||
set => SetValue(HighlightedLedsProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly DispatcherTimer _timer;
|
||||
|
||||
/// <inheritdoc />
|
||||
public DeviceVisualizer()
|
||||
{
|
||||
// Run an update timer at 25 fps
|
||||
_timer = new DispatcherTimer(DispatcherPriority.Render) {Interval = TimeSpan.FromMilliseconds(40)};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#region Lifetime management
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
_timer.Start();
|
||||
_timer.Tick += TimerOnTick;
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
_timer.Stop();
|
||||
_timer.Tick -= TimerOnTick;
|
||||
base.OnDetachedFromLogicalTree(e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void TimerOnTick(object? sender, EventArgs e)
|
||||
{
|
||||
if (ShowColors && IsVisible && Opacity > 0)
|
||||
Update();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Avalonia.Shared.Controls.ProfileConfigurationIcon">
|
||||
</UserControl>
|
||||
@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Artemis.Core;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Svg.Skia;
|
||||
using Material.Icons;
|
||||
using Material.Icons.Avalonia;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Shared.Controls
|
||||
{
|
||||
public class ProfileConfigurationIcon : UserControl
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Core.ProfileConfigurationIcon" /> to display
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<Core.ProfileConfigurationIcon?> ConfigurationIconProperty =
|
||||
AvaloniaProperty.Register<ProfileConfigurationIcon, Core.ProfileConfigurationIcon?>(nameof(ConfigurationIcon));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Core.ProfileConfigurationIcon" /> to display
|
||||
/// </summary>
|
||||
public Core.ProfileConfigurationIcon? ConfigurationIcon
|
||||
{
|
||||
get => GetValue(ConfigurationIconProperty);
|
||||
set => SetValue(ConfigurationIconProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public ProfileConfigurationIcon()
|
||||
{
|
||||
InitializeComponent();
|
||||
DetachedFromLogicalTree += OnDetachedFromLogicalTree;
|
||||
PropertyChanged += OnPropertyChanged;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (ConfigurationIcon == null)
|
||||
return;
|
||||
|
||||
if (ConfigurationIcon.IconType == ProfileConfigurationIconType.SvgImage && ConfigurationIcon.FileIcon != null)
|
||||
{
|
||||
SvgSource source = new();
|
||||
source.Load(ConfigurationIcon.FileIcon);
|
||||
Content = new SvgImage {Source = source};
|
||||
}
|
||||
else if (ConfigurationIcon.IconType == ProfileConfigurationIconType.MaterialIcon && ConfigurationIcon.MaterialIcon != null)
|
||||
{
|
||||
Content = Enum.TryParse(typeof(MaterialIconKind), ConfigurationIcon.MaterialIcon, true, out object? parsedIcon)
|
||||
? new MaterialIcon {Kind = (MaterialIconKind) parsedIcon!}
|
||||
: new MaterialIcon {Kind = MaterialIconKind.QuestionMark};
|
||||
}
|
||||
else if (ConfigurationIcon.IconType == ProfileConfigurationIconType.BitmapImage && ConfigurationIcon.FileIcon != null)
|
||||
Content = new Image {Source = new Bitmap(ConfigurationIcon.FileIcon)};
|
||||
else
|
||||
Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark};
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void OnDetachedFromLogicalTree(object? sender, LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (ConfigurationIcon != null)
|
||||
ConfigurationIcon.PropertyChanged -= IconOnPropertyChanged;
|
||||
}
|
||||
|
||||
private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.Property == ConfigurationIconProperty)
|
||||
{
|
||||
if (e.OldValue is Core.ProfileConfigurationIcon oldIcon)
|
||||
oldIcon.PropertyChanged -= IconOnPropertyChanged;
|
||||
if (e.NewValue is Core.ProfileConfigurationIcon newIcon)
|
||||
newIcon.PropertyChanged += IconOnPropertyChanged;
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
private void IconOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
Update();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
11
src/Artemis.UI.Avalonia.Shared/nuget.config
Normal file
11
src/Artemis.UI.Avalonia.Shared/nuget.config
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
To use the Avalonia CI feed to get unstable packages, move this file to the root of your solution.
|
||||
-->
|
||||
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="AvaloniaCI" value="https://www.myget.org/F/avalonia-ci/api/v2" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
1440
src/Artemis.UI.Avalonia.Shared/packages.lock.json
Normal file
1440
src/Artemis.UI.Avalonia.Shared/packages.lock.json
Normal file
File diff suppressed because it is too large
Load Diff
21
src/Artemis.UI.Avalonia/App.axaml
Normal file
21
src/Artemis.UI.Avalonia/App.axaml
Normal file
@ -0,0 +1,21 @@
|
||||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Artemis.UI.Avalonia"
|
||||
xmlns:sty="using:FluentAvalonia.Styling"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
xmlns:uip="using:FluentAvalonia.UI.Controls.Primitives"
|
||||
x:Class="Artemis.UI.Avalonia.App">
|
||||
<Application.DataTemplates>
|
||||
<local:ViewLocator/>
|
||||
</Application.DataTemplates>
|
||||
|
||||
<Application.Styles>
|
||||
<!-- Third party styles -->
|
||||
<sty:FluentAvaloniaTheme CustomAccentColor="#4db6ac"/>
|
||||
<StyleInclude Source="avares://Material.Icons.Avalonia/App.xaml"></StyleInclude>
|
||||
|
||||
<!-- Global styles -->
|
||||
<StyleInclude Source="/Styles/Button.axaml"></StyleInclude>
|
||||
<StyleInclude Source="/Styles/Sidebar.axaml"></StyleInclude>
|
||||
</Application.Styles>
|
||||
</Application>
|
||||
43
src/Artemis.UI.Avalonia/App.axaml.cs
Normal file
43
src/Artemis.UI.Avalonia/App.axaml.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using Artemis.Core.Ninject;
|
||||
using Artemis.UI.Avalonia.Ninject;
|
||||
using Artemis.UI.Avalonia.Screens.Main.Views;
|
||||
using Artemis.UI.Avalonia.Screens.Root.ViewModels;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Ninject;
|
||||
using Splat.Ninject;
|
||||
|
||||
namespace Artemis.UI.Avalonia
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
private StandardKernel _kernel = null!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
InitializeNinject();
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
desktop.MainWindow = new MainWindow
|
||||
{
|
||||
DataContext = _kernel.Get<RootViewModel>()
|
||||
};
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
|
||||
private void InitializeNinject()
|
||||
{
|
||||
_kernel = new StandardKernel();
|
||||
_kernel.Load<CoreModule>();
|
||||
_kernel.Load<UIModule>();
|
||||
|
||||
_kernel.UseNinjectDependencyResolver();
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj
Normal file
76
src/Artemis.UI.Avalonia/Artemis.UI.Avalonia.csproj
Normal file
@ -0,0 +1,76 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Controls\" />
|
||||
<Folder Include="Models\" />
|
||||
<AvaloniaResource Include="Assets\**" />
|
||||
<Folder Include="Screens\Home\Views" />
|
||||
<Folder Include="Screens\Settings\Views" />
|
||||
<Folder Include="Screens\SurfaceEditor\Views" />
|
||||
<Folder Include="Screens\Workshop\Views" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.10.7" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.10.7" />
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.7" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.7" />
|
||||
<PackageReference Include="Avalonia.Svg.Skia" Version="0.10.7.2" />
|
||||
<PackageReference Include="FluentAvaloniaUI" Version="1.1.3" />
|
||||
<PackageReference Include="Live.Avalonia" Version="1.3.1" />
|
||||
<PackageReference Include="Material.Icons.Avalonia" Version="1.0.2" />
|
||||
<PackageReference Include="Splat.Ninject" Version="13.1.22" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj" />
|
||||
<ProjectReference Include="..\Artemis.UI.Avalonia.Shared\Artemis.UI.Avalonia.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Update="MainWindow.axaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Screens\Root\Views\SidebarCategoryView.axaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Screens\Root\Views\SidebarProfileConfigurationView.axaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Screens\Root\Views\SidebarScreenView.axaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Screens\Root\Views\SidebarView.axaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Update="Screens\Sidebar\Views\SidebarView.axaml.cs">
|
||||
<DependentUpon>SidebarView.axaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Screens\Root\Views\RootView.axaml.cs">
|
||||
<DependentUpon>RootView.axaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<UpToDateCheckInput Remove="Views\MainWindow.axaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Assets\Images\Logo\bow-black.ico" />
|
||||
<Content Include="Assets\Images\Logo\bow-white.ico" />
|
||||
<Content Include="Assets\Images\Logo\bow.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="RGB.NET.Core">
|
||||
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Assets\Images\Logo\bow-black.ico" />
|
||||
<Resource Include="Assets\Images\Logo\bow-white.ico" />
|
||||
<Resource Include="Assets\Images\Logo\bow-white.svg" />
|
||||
<Resource Include="Assets\Images\Logo\bow.ico" />
|
||||
<Resource Include="Assets\Images\Logo\bow.svg" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
BIN
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow-black.ico
Normal file
BIN
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow-black.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow-white.ico
Normal file
BIN
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow-white.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
12
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow-white.svg
Normal file
12
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow-white.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<defs>
|
||||
<style>.cls-1,.cls-2{fill:#fff;}.cls-2{fill-rule:evenodd;}</style>
|
||||
</defs>
|
||||
<g id="Layer_10" data-name="Layer 10">
|
||||
<path class="cls-1" d="M52.32,17.68l-2.83,5a1.16,1.16,0,0,1-2,0l-.57-1-.54.32c-.22-.44-.46-.88-.71-1.31s-.66-1.1-1-1.63l.53-.3-.63-1.06a1.16,1.16,0,0,1,1-1.74l5.75,0A1.15,1.15,0,0,1,52.32,17.68Z"/>
|
||||
<path class="cls-1" d="M24.71,25.63l-4.84,2.58-.53.28a38.15,38.15,0,0,1-5.54-2.18c-4.51-1.49-1.48-7,1.93-4.31.34.22.69.44,1,.64.59.35,1.21.67,1.82,1A25.88,25.88,0,0,0,24.71,25.63Z"/>
|
||||
<path class="cls-1" d="M30.83,36.22c-.15.43-.28.86-.41,1.29a25.74,25.74,0,0,0-.81,4.09,26.72,26.72,0,0,0-.17,3.1c0,.37,0,.75,0,1.12A2.45,2.45,0,0,1,25,47.72c-.56-1-.22-2-.18-3.08s.21-2,.39-3c.12-.74.27-1.47.43-2.2l.53-.33,3.63-2.26Z"/>
|
||||
<path class="cls-1" d="M35,28.71l-.91.57L31.3,31,24,35.59l-4.45,2.78-2.22,1.37a2.6,2.6,0,0,1-1.26.34,2.45,2.45,0,0,1-.8-4.72l.58-.31,1.3-.69,4.67-2.5,7.6-4.05,2.94-1.57.94-.5a17.91,17.91,0,0,1,1,1.55C34.57,27.75,34.82,28.23,35,28.71Z"/>
|
||||
<path class="cls-2" d="M39.29,53.89a2.56,2.56,0,0,1-1.09.74l-.34.08a.13.13,0,0,1-.09,0,1.84,1.84,0,0,1-.33,0,2.41,2.41,0,0,1-1.84-4,22.32,22.32,0,0,0,5-18.09c0-.24-.08-.48-.13-.72s-.1-.48-.16-.73-.11-.48-.18-.72-.12-.45-.2-.68a20.49,20.49,0,0,0-.7-1.94c-.06-.18-.14-.34-.21-.51a21.83,21.83,0,0,0-1.09-2.16c-.14-.22-.27-.45-.4-.66-.25-.4-.51-.78-.77-1.16s-.63-.85-1-1.26l-.48-.56c-.35-.4-.72-.78-1.09-1.14a6.51,6.51,0,0,0-.54-.51l-.45-.4a22.08,22.08,0,0,0-3-2.2c-.17-.11-.36-.21-.54-.31s-.42-.24-.63-.35l-.46-.23a19.7,19.7,0,0,0-2.31-1l-.44-.15-.1,0c-.53-.18-1.07-.34-1.63-.48l-.25-.06a19.61,19.61,0,0,0-2-.39c-.35-.06-.7-.1-1-.13s-.8-.07-1.2-.08-.65,0-1,0h0a22.18,22.18,0,0,0-4,.36,3.28,3.28,0,0,1-.43,0,2.42,2.42,0,0,1-.42-4.8A26,26,0,0,1,18,9.26h.62c.43,0,.86,0,1.28,0l1,.07,1.07.11c.52.07,1,.14,1.53.24.23,0,.46.08.7.13l.14,0c.35.08.69.15,1,.25a20.61,20.61,0,0,1,2.16.65c.48.16.94.33,1.4.52h0c.33.14.67.28,1,.44s.58.27.86.42l.27.13c.28.14.56.29.82.45s.64.36,1,.55c.49.31,1,.62,1.45,1l.15.11c.31.22.62.46.93.7l.11.08c.36.28.71.58,1.06.89l0,0c.33.28.64.57,1,.88s.64.62.94.95c.1.1.19.21.29.32.26.29.52.58.77.88,0,0,0,.05.06.09.28.34.55.68.81,1s.55.75.82,1.15l.28.44c.21.33.42.67.62,1A27.14,27.14,0,0,1,39.29,53.89Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
BIN
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow.ico
Normal file
BIN
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
43
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow.svg
Normal file
43
src/Artemis.UI.Avalonia/Assets/Images/Logo/bow.svg
Normal file
@ -0,0 +1,43 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512">
|
||||
<defs>
|
||||
<style>.cls-1{fill:url(#linear-gradient);}.cls-2{fill:url(#linear-gradient-2);}.cls-3{fill:url(#linear-gradient-3);}.cls-4{fill:url(#linear-gradient-4);}.cls-5{fill:url(#linear-gradient-5);}.cls-6{fill:url(#linear-gradient-6);}.cls-7{fill:url(#linear-gradient-7);}.cls-8{fill-rule:evenodd;fill:url(#linear-gradient-8);}</style>
|
||||
<linearGradient id="linear-gradient" x1="151.25" y1="94.74" x2="810.05" y2="369.54" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#f19d25"/>
|
||||
<stop offset="0.12" stop-color="#f63d3d"/>
|
||||
<stop offset="0.28" stop-color="#c93cec"/>
|
||||
<stop offset="0.44" stop-color="#2667f4"/>
|
||||
<stop offset="0.56" stop-color="#1cb6e7"/>
|
||||
<stop offset="0.7" stop-color="#2df4b5"/>
|
||||
<stop offset="0.87" stop-color="#70ea37"/>
|
||||
<stop offset="1" stop-color="#cfe726"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-2" x1="132.17" y1="204.4" x2="234.7" y2="230.88" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#ef3d3d"/>
|
||||
<stop offset="1" stop-color="#b72222"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-3" x1="217.07" y1="354.42" x2="253.03" y2="258.52" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#2b75f6"/>
|
||||
<stop offset="1" stop-color="#1452aa"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-4" x1="105.18" y1="320.77" x2="311.18" y2="203.81" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#22f15e"/>
|
||||
<stop offset="1" stop-color="#29af4d"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-5" x1="112.68" y1="187.21" x2="771.48" y2="462.01" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-6" x1="88.75" y1="244.59" x2="747.54" y2="519.39" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-7" x1="102.97" y1="210.49" x2="761.77" y2="485.29" xlink:href="#linear-gradient"/>
|
||||
<linearGradient id="linear-gradient-8" x1="141.26" y1="116.54" x2="347.22" y2="356.89" gradientTransform="translate(11.74 6.94)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#009385"/>
|
||||
<stop offset="1" stop-color="#045e53"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="Teal_Bow" data-name="Teal Bow">
|
||||
<g id="TealRainbow">
|
||||
<path class="cls-1" d="M375.54,156.66,340,157a7.14,7.14,0,0,0-6.1,10.76l3.85,6.55-16.8,9.84c2.18,3.26,4.26,6.61,6.24,10,1.54,2.67,3,5.37,4.39,8.09l16.82-9.85,3.53,6a7.14,7.14,0,0,0,12.37-.1l17.53-30.94A7.15,7.15,0,0,0,375.54,156.66Z"/>
|
||||
<path class="cls-5" d="M235.3,221.27l-34.52,18.41c-6.08-1-12.11-2.36-18.05-4a230.91,230.91,0,0,1-39.4-14.9c-27.91-9.26-9.21-43.22,11.93-26.76,2.11,1.41,4.28,2.76,6.48,4,3.65,2.15,7.42,4.09,11.24,5.91a156.68,156.68,0,0,0,42.24,13.31A130.42,130.42,0,0,0,239.63,219Z"/>
|
||||
<path class="cls-6" d="M257,258.59l4.09-2.55a135.41,135.41,0,0,0-14.8,34.07,160.44,160.44,0,0,0-5,25.32,158,158,0,0,0-1.06,19.21c0,2.32.11,4.63.26,6.94,4.06,16.9-18.44,27-27.64,11.76-3.51-6-1.35-12.66-1.14-19.08.58-6.21,1.35-12.39,2.39-18.55a200.68,200.68,0,0,1,9.63-36.38l10.53-6.56Z"/>
|
||||
<path class="cls-7" d="M284,219.06c-1.92-3.33-4-6.55-6.21-9.68h0l-9.46,5.54a17.12,17.12,0,0,0-2.69,1.52l-7.34,3.92L240,230.1q-23.52,12.53-47,25.08L164,270.62l-8,4.27c-1.21.65-2.43,1.29-3.64,1.95C132.81,285.25,146.31,314,165.2,304l13.72-8.55,27.53-17.15,45.22-28.18,17.55-10.94,7-4.39a15.73,15.73,0,0,0,3.58-2.29h0l8.56-5Q286.34,223.21,284,219.06Z"/>
|
||||
<path class="cls-8" d="M169.2,115.38A169,169,0,0,0,143.28,118a15,15,0,0,0,5.26,29.44A137.81,137.81,0,0,1,278.31,372.15a14.95,14.95,0,0,0,22.82,19.31A167.69,167.69,0,0,0,169.2,115.38Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
BIN
src/Artemis.UI.Avalonia/Assets/avalonia-logo.ico
Normal file
BIN
src/Artemis.UI.Avalonia/Assets/avalonia-logo.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Media;
|
||||
using RGBColor = RGB.NET.Core.Color;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts <see cref="T:RGB.NET.Core.Color" /> into <see cref="T:Avalonia.Media.Color" />.
|
||||
/// </summary>
|
||||
public class ColorToSolidColorBrushConverter : IValueConverter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
|
||||
return new SolidColorBrush(!(value is RGBColor color)
|
||||
? new Color(0, 0, 0, 0)
|
||||
: new Color((byte) color.A, (byte) color.R, (byte) color.G, (byte) color.B));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return !(value is SolidColorBrush brush)
|
||||
? RGBColor.Transparent
|
||||
: new RGBColor(brush.Color.A, brush.Color.R, brush.Color.G, brush.Color.B);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Converters
|
||||
{
|
||||
|
||||
public class EnumToCollectionConverter : MarkupExtension, IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return GetAllValuesAndDescriptions(value.GetType());
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
private static string Description(Enum value)
|
||||
{
|
||||
object[] attributes = value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
if (attributes.Any())
|
||||
return (attributes.First() as DescriptionAttribute)?.Description;
|
||||
|
||||
// If no description is found, the least we can do is replace underscores with spaces
|
||||
TextInfo ti = CultureInfo.CurrentCulture.TextInfo;
|
||||
return ti.ToTitleCase(ti.ToLower(value.ToString().Replace("_", " ")));
|
||||
}
|
||||
|
||||
private static IEnumerable<Tuple<object, object>> GetAllValuesAndDescriptions(Type t)
|
||||
{
|
||||
if (!t.IsEnum)
|
||||
throw new ArgumentException($"{nameof(t)} must be an enum type");
|
||||
|
||||
return Enum.GetValues(t).Cast<Enum>().Select(e => new Tuple<object, object>(e, Description(e))).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/Artemis.UI.Avalonia/Converters/LedIdToStringConverter.cs
Normal file
28
src/Artemis.UI.Avalonia/Converters/LedIdToStringConverter.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Converters
|
||||
{
|
||||
public class LedIdToStringConverter : IValueConverter
|
||||
{
|
||||
#region Implementation of IValueConverter
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value?.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (Enum.TryParse(typeof(LedId), value?.ToString(), true, out object parsedLedId))
|
||||
return parsedLedId;
|
||||
return LedId.Unknown1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Converters
|
||||
{
|
||||
public class NormalizedPercentageConverter : IValueConverter
|
||||
{
|
||||
#region IValueConverter Members
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is double number)
|
||||
return number * 100.0;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is double number)
|
||||
return number / 100.0;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
22
src/Artemis.UI.Avalonia/Converters/UriToFileNameConverter.cs
Normal file
22
src/Artemis.UI.Avalonia/Converters/UriToFileNameConverter.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Converters
|
||||
{
|
||||
public class UriToFileNameConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is Uri uri && uri.IsFile)
|
||||
return Path.GetFileName(uri.LocalPath);
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Converters
|
||||
{
|
||||
public class ValuesAdditionConverter : IMultiValueConverter
|
||||
{
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return values.Where(v => v is double).Cast<double>().Sum();
|
||||
}
|
||||
}
|
||||
}
|
||||
14
src/Artemis.UI.Avalonia/MainWindow.axaml
Normal file
14
src/Artemis.UI.Avalonia/MainWindow.axaml
Normal file
@ -0,0 +1,14 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveUi="http://reactiveui.net"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Avalonia.Screens.Main.Views.MainWindow"
|
||||
Icon="/Assets/avalonia-logo.ico"
|
||||
Title="Artemis.UI.Avalonia"
|
||||
TransparencyLevelHint="AcrylicBlur"
|
||||
Background="Transparent"
|
||||
ExtendClientAreaToDecorationsHint="True"
|
||||
Content="{Binding}">
|
||||
</Window>
|
||||
23
src/Artemis.UI.Avalonia/MainWindow.axaml.cs
Normal file
23
src/Artemis.UI.Avalonia/MainWindow.axaml.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using Artemis.UI.Avalonia.Screens.Root.ViewModels;
|
||||
using Avalonia;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Main.Views
|
||||
{
|
||||
public partial class MainWindow : ReactiveWindow<RootViewModel>
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/Artemis.UI.Avalonia/Ninject/Factories/IVMFactory.cs
Normal file
15
src/Artemis.UI.Avalonia/Ninject/Factories/IVMFactory.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Avalonia.Screens.Root.ViewModels;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Ninject.Factories
|
||||
{
|
||||
public interface IVmFactory
|
||||
{
|
||||
}
|
||||
|
||||
public interface ISidebarVmFactory : IVmFactory
|
||||
{
|
||||
SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory);
|
||||
SidebarProfileConfigurationViewModel SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration);
|
||||
}
|
||||
}
|
||||
43
src/Artemis.UI.Avalonia/Ninject/UIModule.cs
Normal file
43
src/Artemis.UI.Avalonia/Ninject/UIModule.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using Artemis.UI.Avalonia.Ninject.Factories;
|
||||
using Artemis.UI.Avalonia.Screens;
|
||||
using Ninject.Extensions.Conventions;
|
||||
using Ninject.Modules;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Ninject
|
||||
{
|
||||
public class UIModule : NinjectModule
|
||||
{
|
||||
public override void Load()
|
||||
{
|
||||
if (Kernel == null)
|
||||
throw new ArgumentNullException("Kernel shouldn't be null here.");
|
||||
|
||||
|
||||
Kernel.Bind(x =>
|
||||
{
|
||||
x.FromThisAssembly()
|
||||
.SelectAllClasses()
|
||||
.InheritedFrom<ViewModelBase>()
|
||||
.BindToSelf();
|
||||
});
|
||||
|
||||
Kernel.Bind(x =>
|
||||
{
|
||||
x.FromThisAssembly()
|
||||
.SelectAllClasses()
|
||||
.InheritedFrom<MainScreenViewModel>()
|
||||
.BindAllBaseClasses();
|
||||
});
|
||||
|
||||
// Bind UI factories
|
||||
Kernel.Bind(x =>
|
||||
{
|
||||
x.FromThisAssembly()
|
||||
.SelectAllInterfaces()
|
||||
.InheritedFrom<IVmFactory>()
|
||||
.BindToFactory();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/Artemis.UI.Avalonia/Program.cs
Normal file
29
src/Artemis.UI.Avalonia/Program.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Ninject;
|
||||
using ReactiveUI;
|
||||
using Splat;
|
||||
using Splat.Ninject;
|
||||
|
||||
namespace Artemis.UI.Avalonia
|
||||
{
|
||||
class Program
|
||||
{
|
||||
private static StandardKernel _kernel;
|
||||
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.LogToTrace()
|
||||
.UseReactiveUI();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
namespace Artemis.UI.Avalonia.Screens.Home.ViewModels
|
||||
{
|
||||
public class HomeViewModel : MainScreenViewModel
|
||||
{
|
||||
public HomeViewModel()
|
||||
{
|
||||
DisplayName = "Home";
|
||||
}
|
||||
|
||||
public void OpenUrl(string url)
|
||||
{
|
||||
Core.Utilities.OpenUrl(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
7
src/Artemis.UI.Avalonia/Screens/MainScreenViewModel.cs
Normal file
7
src/Artemis.UI.Avalonia/Screens/MainScreenViewModel.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Artemis.UI.Avalonia.Screens
|
||||
{
|
||||
public class MainScreenViewModel : ViewModelBase
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Artemis.Core.Services;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
||||
{
|
||||
public class RootViewModel : ViewModelBase, IScreen, IActivatableViewModel
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
|
||||
public RootViewModel(ICoreService coreService, SidebarViewModel sidebarViewModel)
|
||||
{
|
||||
SidebarViewModel = sidebarViewModel;
|
||||
_coreService = coreService;
|
||||
_coreService.Initialize();
|
||||
Console.WriteLine("test");
|
||||
}
|
||||
|
||||
public SidebarViewModel SidebarViewModel { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ViewModelActivator Activator { get; } = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public RoutingState Router { get; } = new();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Avalonia.Ninject.Factories;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
||||
{
|
||||
public class SidebarCategoryViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IProfileService _profileService;
|
||||
private readonly ISidebarVmFactory _vmFactory;
|
||||
private SidebarProfileConfigurationViewModel _selectedProfileConfiguration;
|
||||
public ProfileCategory ProfileCategory { get; }
|
||||
|
||||
public SidebarCategoryViewModel(ProfileCategory profileCategory, IProfileService profileService, ISidebarVmFactory vmFactory)
|
||||
{
|
||||
_profileService = profileService;
|
||||
_vmFactory = vmFactory;
|
||||
|
||||
ProfileCategory = profileCategory;
|
||||
|
||||
if (ShowItems)
|
||||
CreateProfileViewModels();
|
||||
}
|
||||
|
||||
public ObservableCollection<SidebarProfileConfigurationViewModel> ProfileConfigurations { get; } = new();
|
||||
|
||||
public SidebarProfileConfigurationViewModel SelectedProfileConfiguration
|
||||
{
|
||||
get => _selectedProfileConfiguration;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedProfileConfiguration, value);
|
||||
}
|
||||
|
||||
public bool ShowItems
|
||||
{
|
||||
get => !ProfileCategory.IsCollapsed;
|
||||
set
|
||||
{
|
||||
ProfileCategory.IsCollapsed = !value;
|
||||
if (ProfileCategory.IsCollapsed)
|
||||
ProfileConfigurations.Clear();
|
||||
else
|
||||
CreateProfileViewModels();
|
||||
_profileService.SaveProfileCategory(ProfileCategory);
|
||||
|
||||
this.RaisePropertyChanged(nameof(ShowItems));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSuspended
|
||||
{
|
||||
get => ProfileCategory.IsSuspended;
|
||||
set
|
||||
{
|
||||
ProfileCategory.IsSuspended = value;
|
||||
this.RaisePropertyChanged(nameof(IsSuspended));
|
||||
_profileService.SaveProfileCategory(ProfileCategory);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateProfileViewModels()
|
||||
{
|
||||
ProfileConfigurations.Clear();
|
||||
foreach (ProfileConfiguration profileConfiguration in ProfileCategory.ProfileConfigurations.OrderBy(p => p.Order))
|
||||
ProfileConfigurations.Add(_vmFactory.SidebarProfileConfigurationViewModel(profileConfiguration));
|
||||
|
||||
SelectedProfileConfiguration = ProfileConfigurations.FirstOrDefault(i => i.ProfileConfiguration.IsBeingEdited);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
||||
{
|
||||
public class SidebarProfileConfigurationViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IProfileService _profileService;
|
||||
public ProfileConfiguration ProfileConfiguration { get; }
|
||||
|
||||
public SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration, IProfileService profileService)
|
||||
{
|
||||
_profileService = profileService;
|
||||
ProfileConfiguration = profileConfiguration;
|
||||
|
||||
_profileService.LoadProfileConfigurationIcon(ProfileConfiguration);
|
||||
}
|
||||
|
||||
public bool IsProfileActive => ProfileConfiguration.Profile != null;
|
||||
|
||||
public bool IsSuspended
|
||||
{
|
||||
get => ProfileConfiguration.IsSuspended;
|
||||
set
|
||||
{
|
||||
ProfileConfiguration.IsSuspended = value;
|
||||
_profileService.SaveProfileCategory(ProfileConfiguration.Category);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
using Material.Icons;
|
||||
using Ninject;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
||||
{
|
||||
public class SidebarScreenViewModel<T> : SidebarScreenViewModel where T : MainScreenViewModel
|
||||
{
|
||||
public SidebarScreenViewModel(MaterialIconKind icon, string displayName) : base(icon, displayName)
|
||||
{
|
||||
}
|
||||
|
||||
public override MainScreenViewModel CreateInstance(IKernel kernel)
|
||||
{
|
||||
return kernel.Get<T>();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class SidebarScreenViewModel : ViewModelBase
|
||||
{
|
||||
protected SidebarScreenViewModel(MaterialIconKind icon, string displayName)
|
||||
{
|
||||
Icon = icon;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
public MaterialIconKind Icon { get; }
|
||||
public string DisplayName { get; }
|
||||
|
||||
public abstract MainScreenViewModel CreateInstance(IKernel kernel);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Avalonia.Ninject.Factories;
|
||||
using Artemis.UI.Avalonia.Screens.Home.ViewModels;
|
||||
using Artemis.UI.Avalonia.Screens.Settings.ViewModels;
|
||||
using Artemis.UI.Avalonia.Screens.SurfaceEditor.ViewModels;
|
||||
using Artemis.UI.Avalonia.Screens.Workshop.ViewModels;
|
||||
using Material.Icons;
|
||||
using Ninject;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.ViewModels
|
||||
{
|
||||
public class SidebarViewModel : ViewModelBase
|
||||
{
|
||||
private readonly IKernel _kernel;
|
||||
private readonly IProfileService _profileService;
|
||||
private readonly ISidebarVmFactory _sidebarVmFactory;
|
||||
private SidebarScreenViewModel _selectedSidebarScreen;
|
||||
|
||||
public SidebarViewModel(IKernel kernel, IProfileService profileService, ISidebarVmFactory sidebarVmFactory)
|
||||
{
|
||||
_kernel = kernel;
|
||||
_profileService = profileService;
|
||||
_sidebarVmFactory = sidebarVmFactory;
|
||||
|
||||
SidebarScreens = new ObservableCollection<SidebarScreenViewModel>
|
||||
{
|
||||
new SidebarScreenViewModel<HomeViewModel>(MaterialIconKind.Home, "Home"),
|
||||
new SidebarScreenViewModel<WorkshopViewModel>(MaterialIconKind.TestTube, "Workshop"),
|
||||
new SidebarScreenViewModel<SurfaceEditorViewModel>(MaterialIconKind.Devices, "Surface Editor"),
|
||||
new SidebarScreenViewModel<SettingsViewModel>(MaterialIconKind.Cog, "Settings")
|
||||
};
|
||||
SelectedSidebarScreen = SidebarScreens.First();
|
||||
UpdateProfileCategories();
|
||||
}
|
||||
|
||||
public ObservableCollection<SidebarScreenViewModel> SidebarScreens { get; }
|
||||
public ObservableCollection<SidebarCategoryViewModel> SidebarCategories { get; } = new();
|
||||
|
||||
public SidebarScreenViewModel SelectedSidebarScreen
|
||||
{
|
||||
get => _selectedSidebarScreen;
|
||||
set => this.RaiseAndSetIfChanged(ref _selectedSidebarScreen, value);
|
||||
}
|
||||
|
||||
private void UpdateProfileCategories()
|
||||
{
|
||||
SidebarCategories.Clear();
|
||||
foreach (ProfileCategory profileCategory in _profileService.ProfileCategories.OrderBy(p => p.Order))
|
||||
AddProfileCategoryViewModel(profileCategory);
|
||||
}
|
||||
|
||||
public SidebarCategoryViewModel AddProfileCategoryViewModel(ProfileCategory profileCategory)
|
||||
{
|
||||
SidebarCategoryViewModel viewModel = _sidebarVmFactory.SidebarCategoryViewModel(profileCategory);
|
||||
SidebarCategories.Add(viewModel);
|
||||
return viewModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/Artemis.UI.Avalonia/Screens/Root/Views/RootView.axaml
Normal file
29
src/Artemis.UI.Avalonia/Screens/Root/Views/RootView.axaml
Normal file
@ -0,0 +1,29 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveUi="http://reactiveui.net"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.RootView">
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="240" MinWidth="175" MaxWidth="400" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ExperimentalAcrylicBorder Grid.Column="0">
|
||||
<ExperimentalAcrylicBorder.Material>
|
||||
<ExperimentalAcrylicMaterial
|
||||
BackgroundSource="Digger"
|
||||
TintColor="Black"
|
||||
TintOpacity="1"
|
||||
MaterialOpacity="0.65" />
|
||||
</ExperimentalAcrylicBorder.Material>
|
||||
<ContentControl Content="{Binding SidebarViewModel}"/>
|
||||
</ExperimentalAcrylicBorder>
|
||||
<Border Grid.Column="1" Background="Black">
|
||||
<reactiveUi:RoutedViewHost Router="{Binding Router}" Margin="0 20 0 0" Padding="15" />
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
19
src/Artemis.UI.Avalonia/Screens/Root/Views/RootView.axaml.cs
Normal file
19
src/Artemis.UI.Avalonia/Screens/Root/Views/RootView.axaml.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Artemis.UI.Avalonia.Screens.Root.ViewModels;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.Views
|
||||
{
|
||||
public class RootView : ReactiveUserControl<RootViewModel>
|
||||
{
|
||||
public RootView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Avalonia.Screens.Root.ViewModels"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.SidebarCategoryView">
|
||||
<UserControl.Styles>
|
||||
<Style Selector=":is(Button).category-button">
|
||||
<Setter Property="IsVisible" Value="False"></Setter>
|
||||
</Style>
|
||||
<Style Selector="Grid#ContainerGrid:pointerover :is(Button).category-button">
|
||||
<Setter Property="IsVisible" Value="True"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="avalonia|MaterialIcon.chevron-collapsed">
|
||||
<Setter Property="RenderTransform" Value="rotate(180deg)" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.fadable.suspended">
|
||||
<Setter Property="Opacity" Value="0.33" />
|
||||
</Style>
|
||||
<Style Selector="Border.fadable">
|
||||
<Setter Property="Opacity" Value="0" />
|
||||
</Style>
|
||||
<Style Selector="Border.fadable.suspended">
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<Grid x:Name="ContainerGrid" Margin="0 8 0 0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" Background="Transparent">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<avalonia:MaterialIcon Classes.chevron-collapsed="{Binding ShowItems}"
|
||||
Kind="ChevronUp"
|
||||
Grid.Column="0"
|
||||
Margin="5 0"
|
||||
PointerPressed="Title_OnPointerPressed"
|
||||
Background="Transparent">
|
||||
<avalonia:MaterialIcon.Transitions>
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.2" />
|
||||
</Transitions>
|
||||
</avalonia:MaterialIcon.Transitions>
|
||||
</avalonia:MaterialIcon>
|
||||
|
||||
<TextBlock Classes="fadable"
|
||||
Classes.suspended="{Binding IsSuspended}"
|
||||
Grid.Column="1"
|
||||
Padding="0 5"
|
||||
FontWeight="SemiBold"
|
||||
FontSize="13"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding ProfileCategory.Name, FallbackValue='Profile name'}"
|
||||
PointerPressed="Title_OnPointerPressed"
|
||||
Background="Transparent">
|
||||
<TextBlock.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="0:0:0.2" />
|
||||
</Transitions>
|
||||
</TextBlock.Transitions>
|
||||
</TextBlock>
|
||||
|
||||
<Border Classes="fadable"
|
||||
Classes.suspended="{Binding IsSuspended}"
|
||||
Grid.Column="1"
|
||||
BorderBrush="White"
|
||||
BorderThickness="0.5"
|
||||
Height="1">
|
||||
<Border.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="0:0:0.2" />
|
||||
</Transitions>
|
||||
</Border.Transitions>
|
||||
</Border>
|
||||
|
||||
<Button Classes="category-button icon-button icon-button-small"
|
||||
Grid.Column="2"
|
||||
ToolTip.Tip="Edit category"
|
||||
HorizontalAlignment="Right">
|
||||
<avalonia:MaterialIcon Kind="Cog" />
|
||||
</Button>
|
||||
<ToggleButton Classes="category-button icon-button icon-button-small"
|
||||
Grid.Column="3"
|
||||
ToolTip.Tip="Suspend profile"
|
||||
Margin="2 0 0 0"
|
||||
IsChecked="{Binding IsSuspended}">
|
||||
<avalonia:MaterialIcon Kind="Pause" />
|
||||
</ToggleButton>
|
||||
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="1">
|
||||
<Border.Resources>
|
||||
<DataTemplate x:Key="ProfileDragTemplate" DataType="{x:Type local:SidebarProfileConfigurationViewModel}">
|
||||
<Border Background="{DynamicResource MaterialDesignDivider}" Padding="10" CornerRadius="4">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<!-- <shared:ProfileConfigurationIcon ConfigurationIcon="{Binding ProfileConfiguration.Icon}" -->
|
||||
<!-- Width="20" -->
|
||||
<!-- Height="20" -->
|
||||
<!-- Margin="0 0 10 0" -->
|
||||
<!-- Foreground="{DynamicResource MaterialDesignBody}" /> -->
|
||||
<TextBlock Text="{Binding ProfileConfiguration.Name}" VerticalAlignment="Center" Foreground="{DynamicResource MaterialDesignBody}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</Border.Resources>
|
||||
<ListBox Classes="sidebar-listbox"
|
||||
Items="{Binding ProfileConfigurations}"
|
||||
SelectedItem="{Binding SelectedProfileConfiguration}"
|
||||
MinHeight="10"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled">
|
||||
<ListBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Paste">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="ContentPaste" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</ListBox.ContextMenu>
|
||||
</ListBox>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,29 @@
|
||||
using Artemis.UI.Avalonia.Screens.Root.ViewModels;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.Views
|
||||
{
|
||||
public class SidebarCategoryView : ReactiveUserControl<SidebarCategoryViewModel>
|
||||
{
|
||||
public SidebarCategoryView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void Title_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (ViewModel != null)
|
||||
ViewModel.ShowItems = !ViewModel.ShowItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Avalonia.Converters"
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Avalonia.Shared.Controls;assembly=Artemis.UI.Avalonia.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.SidebarProfileConfigurationView">
|
||||
<UserControl.Resources>
|
||||
<converters:ValuesAdditionConverter x:Key="ValuesAddition" />
|
||||
</UserControl.Resources>
|
||||
<UserControl.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="View properties">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Cog" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Suspend">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Pause" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Suspend all">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Pause" />
|
||||
</MenuItem.Icon>
|
||||
<MenuItem Header="Above" CommandParameter="suspend" />
|
||||
<MenuItem Header="Below" CommandParameter="suspend" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="Resume all">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Play" />
|
||||
</MenuItem.Icon>
|
||||
<MenuItem Header="Above" CommandParameter="resume" />
|
||||
<MenuItem Header="Below" CommandParameter="resume" />
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Export">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Export" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Duplicate">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="ContentDuplicate" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Copy">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="ContentCopy" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Paste">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="ContentPaste" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
<Separator />
|
||||
<MenuItem Header="Delete">
|
||||
<MenuItem.Icon>
|
||||
<avalonia:MaterialIcon Kind="Trash" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</UserControl.ContextMenu>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<controls:ProfileConfigurationIcon Grid.Column="0"
|
||||
x:Name="ProfileIcon"
|
||||
VerticalAlignment="Center"
|
||||
ConfigurationIcon="{Binding ProfileConfiguration.Icon}"
|
||||
Width="20"
|
||||
Height="20">
|
||||
</controls:ProfileConfigurationIcon>
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
x:Name="ProfileName"
|
||||
FontSize="12"
|
||||
Margin="10 0 0 0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Text="{Binding ProfileConfiguration.Name}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
|
||||
<Border Grid.Column="0"
|
||||
Grid.ColumnSpan="2"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource MaterialDesignBody}"
|
||||
Height="1"
|
||||
Opacity="0"
|
||||
HorizontalAlignment="Left">
|
||||
<!-- Ensure the line covers the profile and the text but not the full two columns -->
|
||||
<Border.Width>
|
||||
<MultiBinding Converter="{StaticResource ValuesAddition}">
|
||||
<Binding Path="ActualWidth" ElementName="ProfileIcon" />
|
||||
<Binding Path="Width" ElementName="ProfileName" />
|
||||
<Binding Path="Margin.Left" ElementName="ProfileName" />
|
||||
</MultiBinding>
|
||||
</Border.Width>
|
||||
|
||||
</Border>
|
||||
|
||||
<Button Classes="icon-button icon-button-small"
|
||||
Grid.Column="2"
|
||||
ToolTip.Tip="View properties"
|
||||
HorizontalAlignment="Right">
|
||||
<avalonia:MaterialIcon Kind="Cog"/>
|
||||
</Button>
|
||||
<ToggleButton Classes="icon-button icon-button-small"
|
||||
Grid.Column="3"
|
||||
ToolTip.Tip="Suspend profile"
|
||||
Margin="2 0 0 0"
|
||||
IsChecked="{Binding IsSuspended}">
|
||||
<avalonia:MaterialIcon Kind="Pause" />
|
||||
</ToggleButton>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,18 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.Views
|
||||
{
|
||||
public class SidebarProfileConfigurationView : UserControl
|
||||
{
|
||||
public SidebarProfileConfigurationView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.SidebarScreenView">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<avalonia:MaterialIcon Kind="{Binding Icon}" Width="16" Height="16" />
|
||||
<TextBlock FontSize="12" Margin="10 0" VerticalAlignment="Center" Text="{Binding DisplayName}" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@ -0,0 +1,18 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.Views
|
||||
{
|
||||
public partial class SidebarScreenView : UserControl
|
||||
{
|
||||
public SidebarScreenView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
114
src/Artemis.UI.Avalonia/Screens/Root/Views/SidebarView.axaml
Normal file
114
src/Artemis.UI.Avalonia/Screens/Root/Views/SidebarView.axaml
Normal file
@ -0,0 +1,114 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Avalonia.Screens.Root.Views.SidebarView">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="60" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" ClipToBounds="True">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- <shared:DeviceVisualizer Grid.Column="0" -->
|
||||
<!-- Grid.ColumnSpan="2" -->
|
||||
<!-- Device="{Binding HeaderDevice}" -->
|
||||
<!-- ShowColors="True" -->
|
||||
<!-- RenderTransformOrigin="0.5 0.5" -->
|
||||
<!-- VerticalAlignment="Center" -->
|
||||
<!-- HorizontalAlignment="Center" -->
|
||||
<!-- RenderOptions.BitmapScalingMode="HighQuality"> -->
|
||||
<!-- <shared:DeviceVisualizer.RenderTransform> -->
|
||||
<!-- <TransformGroup> -->
|
||||
<!-- <RotateTransform Angle="20" /> -->
|
||||
<!-- <ScaleTransform ScaleX="2" ScaleY="2" /> -->
|
||||
<!-- </TransformGroup> -->
|
||||
<!-- </shared:DeviceVisualizer.RenderTransform> -->
|
||||
<!-- </shared:DeviceVisualizer> -->
|
||||
<Rectangle Grid.Column="0" Grid.ColumnSpan="2" Height="60" VerticalAlignment="Bottom">
|
||||
<Rectangle.Fill>
|
||||
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
|
||||
<GradientStop Color="Black" Offset="0" />
|
||||
<GradientStop Color="#00000000" Offset="1" />
|
||||
</LinearGradientBrush>
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
|
||||
<Image Grid.Column="0" Source="{SvgImage /Assets/Images/Logo/bow.svg}" Height="35" Width="35" Margin="10" />
|
||||
<TextBlock Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
|
||||
Foreground="{DynamicResource MaterialDesignDarkForeground}">
|
||||
Artemis 2
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
|
||||
<!-- Built-in screens -->
|
||||
<ListBox Classes="sidebar-listbox"
|
||||
Grid.Row="1"
|
||||
Margin="10 2"
|
||||
Items="{Binding SidebarScreens}"
|
||||
SelectedItem="{Binding SelectedSidebarScreen}" />
|
||||
<Separator Grid.Row="2" Margin="8" Height="1" Background="White" />
|
||||
|
||||
<!-- Categories -->
|
||||
<ScrollViewer Grid.Row="3" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel>
|
||||
<ItemsControl Margin="10 2" Items="{Binding SidebarCategories}" />
|
||||
<Button Content="ADD NEW CATEGORY" Margin="10 10 10 0" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- Bottom buttons -->
|
||||
<Separator Grid.Row="4" Margin="8" />
|
||||
<WrapPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5 0 5 5">
|
||||
<controls:HyperlinkButton Classes="icon-button"
|
||||
Width="44"
|
||||
Height="44"
|
||||
ToolTip.Tip="View website"
|
||||
NavigateUri="https://artemis-rgb.com">
|
||||
<avalonia:MaterialIcon Kind="Web" Width="20" Height="20" />
|
||||
</controls:HyperlinkButton>
|
||||
<controls:HyperlinkButton Classes="icon-button"
|
||||
Width="44"
|
||||
Height="44"
|
||||
ToolTip.Tip="View GitHub repository"
|
||||
NavigateUri="https://github.com/Artemis-RGB/Artemis">
|
||||
<avalonia:MaterialIcon Kind="Github" Width="20" Height="20" />
|
||||
</controls:HyperlinkButton>
|
||||
<controls:HyperlinkButton Classes="icon-button"
|
||||
Width="44"
|
||||
Height="44"
|
||||
ToolTip.Tip="View Wiki"
|
||||
NavigateUri="https://wiki.artemis-rgb.com">
|
||||
<avalonia:MaterialIcon Kind="BookOpenOutline" Width="20" Height="20" />
|
||||
</controls:HyperlinkButton>
|
||||
<controls:HyperlinkButton Classes="icon-button"
|
||||
Width="44"
|
||||
Height="44"
|
||||
ToolTip.Tip="Join our Discord"
|
||||
NavigateUri="https://discord.gg/S3MVaC9">
|
||||
<avalonia:MaterialIcon Kind="Discord" Width="20" Height="20" />
|
||||
</controls:HyperlinkButton>
|
||||
<controls:HyperlinkButton Classes="icon-button"
|
||||
Width="44"
|
||||
Height="44"
|
||||
ToolTip.Tip="View donation options"
|
||||
NavigateUri="https://wiki.artemis-rgb.com/en/donating">
|
||||
<avalonia:MaterialIcon Kind="Gift" Width="20" Height="20" />
|
||||
</controls:HyperlinkButton>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,18 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace Artemis.UI.Avalonia.Screens.Root.Views
|
||||
{
|
||||
public class SidebarView : UserControl
|
||||
{
|
||||
public SidebarView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
namespace Artemis.UI.Avalonia.Screens.Settings.ViewModels
|
||||
{
|
||||
public class SettingsViewModel : MainScreenViewModel
|
||||
{
|
||||
public SettingsViewModel()
|
||||
{
|
||||
DisplayName = "Settings";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
namespace Artemis.UI.Avalonia.Screens.SurfaceEditor.ViewModels
|
||||
{
|
||||
public class SurfaceEditorViewModel : MainScreenViewModel
|
||||
{
|
||||
public SurfaceEditorViewModel()
|
||||
{
|
||||
DisplayName = "Surface Editor";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
namespace Artemis.UI.Avalonia.Screens.Workshop.ViewModels
|
||||
{
|
||||
public class WorkshopViewModel : MainScreenViewModel
|
||||
{
|
||||
public WorkshopViewModel()
|
||||
{
|
||||
DisplayName = "Workshop";
|
||||
}
|
||||
}
|
||||
}
|
||||
55
src/Artemis.UI.Avalonia/Styles/Button.axaml
Normal file
55
src/Artemis.UI.Avalonia/Styles/Button.axaml
Normal file
@ -0,0 +1,55 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
|
||||
<!-- Preview -->
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<StackPanel>
|
||||
<TextBlock Margin="0 5 0 0">Button.icon-button</TextBlock>
|
||||
<Button Classes="icon-button">
|
||||
<avalonia:MaterialIcon Kind="Cog"></avalonia:MaterialIcon>
|
||||
</Button>
|
||||
|
||||
<TextBlock Margin="0 5 0 0">Button.icon-button icon-button-small</TextBlock>
|
||||
<Button Classes="icon-button icon-button-small">
|
||||
<avalonia:MaterialIcon Kind="Cog"></avalonia:MaterialIcon>
|
||||
</Button>
|
||||
|
||||
<TextBlock Margin="0 5 0 0">ToggleButton.icon-button</TextBlock>
|
||||
<ToggleButton Classes="icon-button">
|
||||
<avalonia:MaterialIcon Kind="Cog"></avalonia:MaterialIcon>
|
||||
</ToggleButton>
|
||||
|
||||
<TextBlock Margin="0 5 0 0">HyperlinkButton.icon-button</TextBlock>
|
||||
<controls:HyperlinkButton Classes="icon-button">
|
||||
<avalonia:MaterialIcon Kind="Web" />
|
||||
</controls:HyperlinkButton>
|
||||
|
||||
<TextBlock Margin="0 5 0 0">HyperlinkButton.icon-button icon-button-small</TextBlock>
|
||||
<controls:HyperlinkButton Classes="icon-button icon-button-small">
|
||||
<avalonia:MaterialIcon Kind="Web" />
|
||||
</controls:HyperlinkButton>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<!-- Styles -->
|
||||
<Style Selector=":is(Button).icon-button">
|
||||
<Setter Property="BorderBrush" Value="Transparent"></Setter>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Padding" Value="5.5"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector=":is(Button).icon-button-small">
|
||||
<Setter Property="Padding" Value="2"/>
|
||||
</Style>
|
||||
<Style Selector=":is(Button).icon-button-small avalonia|MaterialIcon">
|
||||
<Setter Property="Width" Value="14"></Setter>
|
||||
<Setter Property="Height" Value="14"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="controls|HyperlinkButton.icon-button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" />
|
||||
</Style>
|
||||
</Styles>
|
||||
20
src/Artemis.UI.Avalonia/Styles/Sidebar.axaml
Normal file
20
src/Artemis.UI.Avalonia/Styles/Sidebar.axaml
Normal file
@ -0,0 +1,20 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:views="clr-namespace:Artemis.UI.Avalonia.Screens.Root.Views">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<ListBox Classes="sidebar-listbox">
|
||||
<ListBoxItem>Test</ListBoxItem>
|
||||
<ListBoxItem>Test</ListBoxItem>
|
||||
<ListBoxItem>Test</ListBoxItem>
|
||||
<ListBoxItem>Test</ListBoxItem>
|
||||
</ListBox>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<!-- Add Styles Here -->
|
||||
<Style Selector="ListBox.sidebar-listbox ListBoxItem">
|
||||
<Setter Property="Margin" Value="0 2.5"></Setter>
|
||||
<Setter Property="MinHeight" Value="35"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
26
src/Artemis.UI.Avalonia/ViewLocator.cs
Normal file
26
src/Artemis.UI.Avalonia/ViewLocator.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
||||
namespace Artemis.UI.Avalonia
|
||||
{
|
||||
public class ViewLocator : IDataTemplate
|
||||
{
|
||||
public bool SupportsRecycling => false;
|
||||
|
||||
public IControl Build(object data)
|
||||
{
|
||||
string name = data.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
|
||||
Type? type = Type.GetType(name);
|
||||
|
||||
if (type != null)
|
||||
return (Control) Activator.CreateInstance(type)!;
|
||||
return new TextBlock { Text = "Not Found: " + name };
|
||||
}
|
||||
|
||||
public bool Match(object data)
|
||||
{
|
||||
return data is ViewModelBase;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/Artemis.UI.Avalonia/ViewModelBase.cs
Normal file
15
src/Artemis.UI.Avalonia/ViewModelBase.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Avalonia
|
||||
{
|
||||
public class ViewModelBase : ReactiveObject
|
||||
{
|
||||
private string? _displayName;
|
||||
|
||||
public string? DisplayName
|
||||
{
|
||||
get => _displayName;
|
||||
set => this.RaiseAndSetIfChanged(ref _displayName, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
1682
src/Artemis.UI.Avalonia/packages.lock.json
Normal file
1682
src/Artemis.UI.Avalonia/packages.lock.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"dependencies": {
|
||||
".NETCoreApp,Version=v5.0": {
|
||||
"net5.0-windows7.0": {
|
||||
"Humanizer.Core": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.11.10, )",
|
||||
|
||||
@ -13,32 +13,64 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.Shared", "Artemi
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.Console", "Artemis.ConsoleUI\Artemis.UI.Console.csproj", "{ACCC50FD-611A-41C4-B58F-DDC80B47D0CF}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.Avalonia", "Artemis.UI.Avalonia\Artemis.UI.Avalonia.csproj", "{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.UI.Avalonia.Shared", "Artemis.UI.Avalonia.Shared\Artemis.UI.Avalonia.Shared.csproj", "{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{46B74153-77CF-4489-BDF9-D53FDB1F7ACB}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{46B74153-77CF-4489-BDF9-D53FDB1F7ACB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{46B74153-77CF-4489-BDF9-D53FDB1F7ACB}.Debug|x64.Build.0 = Debug|x64
|
||||
{46B74153-77CF-4489-BDF9-D53FDB1F7ACB}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{46B74153-77CF-4489-BDF9-D53FDB1F7ACB}.Release|x64.ActiveCfg = Release|x64
|
||||
{46B74153-77CF-4489-BDF9-D53FDB1F7ACB}.Release|x64.Build.0 = Release|x64
|
||||
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Debug|x64.Build.0 = Debug|x64
|
||||
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Release|x64.ActiveCfg = Release|x64
|
||||
{E489E5E3-1A65-4AF5-A1EA-F9805FD19A65}.Release|x64.Build.0 = Release|x64
|
||||
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Debug|x64.Build.0 = Debug|x64
|
||||
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Release|x64.ActiveCfg = Release|x64
|
||||
{9B811F9B-86B9-4771-87AF-72BAE7078A36}.Release|x64.Build.0 = Release|x64
|
||||
{ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Debug|x64.Build.0 = Debug|x64
|
||||
{ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Release|x64.ActiveCfg = Release|x64
|
||||
{ADB357E6-151D-4D0D-87CB-68FD0BC29812}.Release|x64.Build.0 = Release|x64
|
||||
{ACCC50FD-611A-41C4-B58F-DDC80B47D0CF}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{ACCC50FD-611A-41C4-B58F-DDC80B47D0CF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{ACCC50FD-611A-41C4-B58F-DDC80B47D0CF}.Debug|x64.Build.0 = Debug|x64
|
||||
{ACCC50FD-611A-41C4-B58F-DDC80B47D0CF}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{ACCC50FD-611A-41C4-B58F-DDC80B47D0CF}.Release|x64.ActiveCfg = Release|x64
|
||||
{ACCC50FD-611A-41C4-B58F-DDC80B47D0CF}.Release|x64.Build.0 = Release|x64
|
||||
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{035CBB38-7B9E-4375-A39C-E9A5B01F23A5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{05A5AB0F-A303-4404-9623-4DB1C9AA1DA0}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user