mirror of
https://github.com/DarthAffe/RGBSyncPlus
synced 2026-11-11 04:57:28 +00:00
Initial implementation
This commit is contained in:
1 parent
278e22020e
commit
fd662dcf34
63 files changed
+4881
No files matched your search
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using GongSolutions.Wpf.DragDrop;
|
||||
using RGB.NET.Core;
|
||||
using RGBSyncPlus.Helper;
|
||||
using RGBSyncPlus.Model;
|
||||
|
||||
namespace RGBSyncPlus.UI
|
||||
{
|
||||
public sealed class ConfigurationViewModel : AbstractBindable, IDropTarget
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public Version Version => Assembly.GetEntryAssembly().GetName().Version;
|
||||
|
||||
public double UpdateRate
|
||||
{
|
||||
get => 1.0 / ApplicationManager.Instance.UpdateTrigger.UpdateFrequency;
|
||||
set
|
||||
{
|
||||
double val = MathHelper.Clamp(value, 1, 100);
|
||||
ApplicationManager.Instance.Settings.UpdateRate = val;
|
||||
ApplicationManager.Instance.UpdateTrigger.UpdateFrequency = 1.0 / val;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<SyncGroup> _syncGroups;
|
||||
public ObservableCollection<SyncGroup> SyncGroups
|
||||
{
|
||||
get => _syncGroups;
|
||||
set => SetProperty(ref _syncGroups, value);
|
||||
}
|
||||
|
||||
private SyncGroup _selectedSyncGroup;
|
||||
public SyncGroup SelectedSyncGroup
|
||||
{
|
||||
get => _selectedSyncGroup;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _selectedSyncGroup, value))
|
||||
UpdateLedLists();
|
||||
}
|
||||
}
|
||||
|
||||
private ListCollectionView _availableSyncLeds;
|
||||
public ListCollectionView AvailableSyncLeds
|
||||
{
|
||||
get => _availableSyncLeds;
|
||||
set => SetProperty(ref _availableSyncLeds, value);
|
||||
}
|
||||
|
||||
private ListCollectionView _availableLeds;
|
||||
public ListCollectionView AvailableLeds
|
||||
{
|
||||
get => _availableLeds;
|
||||
set => SetProperty(ref _availableLeds, value);
|
||||
}
|
||||
|
||||
private ListCollectionView _synchronizedLeds;
|
||||
public ListCollectionView SynchronizedLeds
|
||||
{
|
||||
get => _synchronizedLeds;
|
||||
set => SetProperty(ref _synchronizedLeds, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Commands
|
||||
|
||||
private ActionCommand _openHomepageCommand;
|
||||
public ActionCommand OpenHomepageCommand => _openHomepageCommand ?? (_openHomepageCommand = new ActionCommand(OpenHomepage));
|
||||
|
||||
private ActionCommand _addSyncGroupCommand;
|
||||
public ActionCommand AddSyncGroupCommand => _addSyncGroupCommand ?? (_addSyncGroupCommand = new ActionCommand(AddSyncGroup));
|
||||
|
||||
private ActionCommand<SyncGroup> _removeSyncGroupCommand;
|
||||
public ActionCommand<SyncGroup> RemoveSyncGroupCommand => _removeSyncGroupCommand ?? (_removeSyncGroupCommand = new ActionCommand<SyncGroup>(RemoveSyncGroup));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ConfigurationViewModel()
|
||||
{
|
||||
SyncGroups = new ObservableCollection<SyncGroup>(ApplicationManager.Instance.Settings.SyncGroups);
|
||||
|
||||
AvailableSyncLeds = GetGroupedLedList(RGBSurface.Instance.Leds.Where(x => x.Device.DeviceInfo.SupportsSyncBack));
|
||||
OnPropertyChanged(nameof(AvailableSyncLeds));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private ListCollectionView GetGroupedLedList(IEnumerable<Led> leds) => GetGroupedLedList(leds.Select(led => new SyncLed(led)).ToList());
|
||||
|
||||
private ListCollectionView GetGroupedLedList(IList syncLeds)
|
||||
{
|
||||
ListCollectionView collectionView = new ListCollectionView(syncLeds);
|
||||
collectionView.GroupDescriptions.Add(new PropertyGroupDescription(nameof(SyncLed.Device)));
|
||||
collectionView.SortDescriptions.Add(new SortDescription(nameof(SyncLed.Device), ListSortDirection.Ascending));
|
||||
collectionView.SortDescriptions.Add(new SortDescription(nameof(SyncLed.LedId), ListSortDirection.Ascending));
|
||||
collectionView.Refresh();
|
||||
return collectionView;
|
||||
}
|
||||
|
||||
private void UpdateLedLists()
|
||||
{
|
||||
SynchronizedLeds = GetGroupedLedList(SelectedSyncGroup.Leds);
|
||||
OnPropertyChanged(nameof(SynchronizedLeds));
|
||||
|
||||
AvailableLeds = GetGroupedLedList(RGBSurface.Instance.Leds.Where(led => !SelectedSyncGroup.Leds.Any(sc => (sc.LedId == led.Id) && (sc.Device == led.Device.GetDeviceName()))));
|
||||
OnPropertyChanged(nameof(AvailableLeds));
|
||||
}
|
||||
|
||||
private void OpenHomepage() => Process.Start("https://github.com/DarthAffe/RGBSyncPlus");
|
||||
|
||||
private void AddSyncGroup()
|
||||
{
|
||||
SyncGroup syncGroup = new SyncGroup();
|
||||
SyncGroups.Add(syncGroup);
|
||||
ApplicationManager.Instance.AddSyncGroup(syncGroup);
|
||||
}
|
||||
|
||||
private void RemoveSyncGroup(SyncGroup syncGroup)
|
||||
{
|
||||
if (syncGroup == null) return;
|
||||
|
||||
if (MessageBox.Show($"Are you sure that you want to delete the group '{syncGroup.DisplayName}'", "Remove Sync-Group", MessageBoxButton.YesNo) == MessageBoxResult.No)
|
||||
return;
|
||||
|
||||
SyncGroups.Remove(syncGroup);
|
||||
ApplicationManager.Instance.RemoveSyncGroup(syncGroup);
|
||||
}
|
||||
|
||||
void IDropTarget.DragOver(IDropInfo dropInfo)
|
||||
{
|
||||
if ((dropInfo.Data is SyncLed || dropInfo.Data is IEnumerable<SyncLed>) && (dropInfo.TargetCollection is ListCollectionView))
|
||||
{
|
||||
dropInfo.DropTargetAdorner = DropTargetAdorners.Highlight;
|
||||
dropInfo.Effects = DragDropEffects.Copy;
|
||||
}
|
||||
}
|
||||
|
||||
void IDropTarget.Drop(IDropInfo dropInfo)
|
||||
{
|
||||
if (!(dropInfo.TargetCollection is ListCollectionView targetList)) return;
|
||||
|
||||
//HACK DarthAffe 04.06.2018: Super ugly hack - I've no idea how to do this correctly ...
|
||||
ListCollectionView sourceList = targetList == AvailableLeds ? SynchronizedLeds : AvailableLeds;
|
||||
|
||||
if (dropInfo.Data is SyncLed syncLed)
|
||||
{
|
||||
targetList.AddNewItem(syncLed);
|
||||
sourceList.Remove(syncLed);
|
||||
|
||||
targetList.CommitNew();
|
||||
sourceList.CommitEdit();
|
||||
}
|
||||
else if (dropInfo.Data is IEnumerable<SyncLed> syncLeds)
|
||||
{
|
||||
foreach (SyncLed led in syncLeds)
|
||||
{
|
||||
targetList.AddNewItem(led);
|
||||
sourceList.Remove(led);
|
||||
}
|
||||
targetList.CommitNew();
|
||||
sourceList.CommitEdit();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
<controls:BlurredDecorationWindow x:Class="RGBSyncPlus.UI.ConfigurationWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:core="clr-namespace:RGB.NET.Core;assembly=RGB.NET.Core"
|
||||
xmlns:ui="clr-namespace:RGBSyncPlus.UI"
|
||||
xmlns:controls="clr-namespace:RGBSyncPlus.Controls"
|
||||
xmlns:styles="clr-namespace:RGBSyncPlus.Styles"
|
||||
xmlns:attached="clr-namespace:RGBSyncPlus.Attached"
|
||||
xmlns:helper="clr-namespace:RGBSyncPlus.Helper"
|
||||
xmlns:dd="urn:gong-wpf-dragdrop"
|
||||
mc:Ignorable="d"
|
||||
Title="RGBSync+ # Configuration"
|
||||
Icon="pack://application:,,,/RGBSync+;component/Resources/argebee.ico"
|
||||
IconCommand="{Binding OpenHomepageCommand}"
|
||||
Width="1280" Height="720"
|
||||
Closed="ConfigurationWindow_OnClosed">
|
||||
|
||||
<controls:BlurredDecorationWindow.Resources>
|
||||
<styles:CachedResourceDictionary>
|
||||
<styles:CachedResourceDictionary.MergedDictionaries>
|
||||
<styles:CachedResourceDictionary Source="/RGBSync+;component/Styles/Navigation.xaml" />
|
||||
</styles:CachedResourceDictionary.MergedDictionaries>
|
||||
</styles:CachedResourceDictionary>
|
||||
</controls:BlurredDecorationWindow.Resources>
|
||||
|
||||
<controls:BlurredDecorationWindow.DataContext>
|
||||
<ui:ConfigurationViewModel />
|
||||
</controls:BlurredDecorationWindow.DataContext>
|
||||
|
||||
<TabControl Style="{StaticResource StyleTabControlNavigation}">
|
||||
<TabItem Header="Sync-Groups">
|
||||
<AdornerDecorator>
|
||||
<DockPanel LastChildFill="True">
|
||||
<GroupBox DockPanel.Dock="Left" Width="260">
|
||||
<DockPanel VerticalAlignment="Top">
|
||||
<Button DockPanel.Dock="Bottom"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="8"
|
||||
Content="New Sync-Group"
|
||||
Command="{Binding AddSyncGroupCommand}" />
|
||||
|
||||
<ListBox ItemsSource="{Binding SyncGroups}"
|
||||
SelectedItem="{Binding SelectedSyncGroup}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}"
|
||||
ToolTip="Remove"
|
||||
Command="{Binding DataContext.RemoveSyncGroupCommand, RelativeSource={RelativeSource AncestorType={x:Type controls:BlurredDecorationWindow}}}"
|
||||
CommandParameter="{Binding DataContext, RelativeSource={RelativeSource AncestorType=ListBoxItem}}">
|
||||
<Image Source="/RGBSync+;component/Resources/close.png" />
|
||||
</Button>
|
||||
<TextBlock Grid.Column="1" Margin="4" Text="{Binding DisplayName}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
|
||||
<DockPanel Margin="8,0,0,0">
|
||||
<GroupBox DockPanel.Dock="Top">
|
||||
<Grid>
|
||||
<Border HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Margin="16"
|
||||
Visibility="{Binding SelectedSyncGroup, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=True}">
|
||||
<TextBlock Text="No Sync-Group selected ..." />
|
||||
</Border>
|
||||
|
||||
<Border Visibility="{Binding SelectedSyncGroup, Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<Border.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
</Border.Resources>
|
||||
|
||||
<controls:Form DockPanel.Dock="Top">
|
||||
<Label controls:Form.IsLabel="True"
|
||||
Content="Name:" />
|
||||
<TextBox controls:Form.Fill="True"
|
||||
Text="{Binding SelectedSyncGroup.Name, UpdateSourceTrigger=PropertyChanged}" />
|
||||
|
||||
<Label controls:Form.IsLabel="True"
|
||||
Content="Sync-LED:" />
|
||||
<ComboBox controls:Form.Fill="True"
|
||||
ItemsSource="{Binding AvailableSyncLeds}"
|
||||
SelectedItem="{Binding SelectedSyncGroup.SyncLed}">
|
||||
<ComboBox.GroupStyle>
|
||||
<GroupStyle>
|
||||
<GroupStyle.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<Border VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{StaticResource BrushComboBoxBackgroundGroupHeader}">
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding Name}" />
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</GroupStyle.HeaderTemplate>
|
||||
</GroupStyle>
|
||||
</ComboBox.GroupStyle>
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding LedId}"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</controls:Form>
|
||||
</Border>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<Grid Margin="0,8,0,0"
|
||||
Visibility="{Binding SelectedSyncGroup, Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.Resources>
|
||||
<GroupStyle x:Key="StyleListBoxGroup">
|
||||
<GroupStyle.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0,8,0,0"
|
||||
FontWeight="Bold"
|
||||
Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</GroupStyle.HeaderTemplate>
|
||||
</GroupStyle>
|
||||
|
||||
<DataTemplate x:Key="DataTemplateListBoxItem">
|
||||
<TextBlock Text="{Binding LedId}"/>
|
||||
</DataTemplate>
|
||||
</Grid.Resources>
|
||||
|
||||
<GroupBox Grid.Column="0">
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,8"
|
||||
FontWeight="Bold"
|
||||
Text="Available LEDS" />
|
||||
<ListBox SelectionMode="Extended"
|
||||
dd:DragDrop.IsDragSource="True"
|
||||
dd:DragDrop.IsDropTarget="True"
|
||||
dd:DragDrop.DropHandler="{Binding}"
|
||||
ItemTemplate="{StaticResource DataTemplateListBoxItem}"
|
||||
ItemsSource="{Binding AvailableLeds}">
|
||||
<ListBox.GroupStyle>
|
||||
<StaticResource ResourceKey="StyleListBoxGroup" />
|
||||
</ListBox.GroupStyle>
|
||||
</ListBox>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox Grid.Column="2">
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,8"
|
||||
FontWeight="Bold"
|
||||
Text="Synchronized LEDS" />
|
||||
<ListBox SelectionMode="Extended"
|
||||
dd:DragDrop.IsDragSource="True"
|
||||
dd:DragDrop.IsDropTarget="True"
|
||||
dd:DragDrop.DropHandler="{Binding}"
|
||||
ItemTemplate="{StaticResource DataTemplateListBoxItem}"
|
||||
ItemsSource="{Binding SynchronizedLeds}">
|
||||
<ListBox.GroupStyle>
|
||||
<StaticResource ResourceKey="StyleListBoxGroup" />
|
||||
</ListBox.GroupStyle>
|
||||
</ListBox>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
</AdornerDecorator>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="Settings">
|
||||
<AdornerDecorator>
|
||||
<GroupBox VerticalAlignment="Top">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<Style BasedOn="{StaticResource StyleLabelForm}" TargetType="Label" />
|
||||
<Style BasedOn="{StaticResource StyleTextBlockForm}" TargetType="TextBlock" />
|
||||
<Style BasedOn="{StaticResource StyleListBoxForm}" TargetType="ListBox" />
|
||||
</Grid.Resources>
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<controls:Form Grid.Column="0">
|
||||
<Label controls:Form.IsLabel="True"
|
||||
Content="Version:" />
|
||||
<TextBlock Text="{Binding Version}" />
|
||||
|
||||
<Label controls:Form.IsLabel="True"
|
||||
Content="Update-Rate" />
|
||||
<Slider Minimum="1" Maximum="100" controls:Form.Fill="True" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="BottomRight"
|
||||
Value="{Binding UpdateRate}"
|
||||
attached:SliderValue.Unit="UPS"
|
||||
ToolTip="Defines how fast the data is updated.
Low values can reduce CPU-usage but might cause stuttering." />
|
||||
|
||||
<Label controls:Form.LineBreaks="1" controls:Form.IsLabel="True" Content="Devices:" />
|
||||
</controls:Form>
|
||||
</Grid>
|
||||
|
||||
<ItemsControl VerticalAlignment="Top" HorizontalAlignment="Left" Margin="120,-22,0,0" ItemsSource="{Binding Source={x:Static core:RGBSurface.Instance}, Path=Devices}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Style="{StaticResource StyleTextBlockForm}">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="> {0} {1} ({2})">
|
||||
<Binding Path="DeviceInfo.Manufacturer" />
|
||||
<Binding Path="DeviceInfo.Model" />
|
||||
<Binding Path="DeviceInfo.DeviceType" />
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</AdornerDecorator>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
</controls:BlurredDecorationWindow>
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using RGBSyncPlus.Controls;
|
||||
|
||||
namespace RGBSyncPlus.UI
|
||||
{
|
||||
public partial class ConfigurationWindow : BlurredDecorationWindow
|
||||
{
|
||||
public ConfigurationWindow() => InitializeComponent();
|
||||
|
||||
//DarthAffe 07.02.2018: This prevents the applicaiton from not shutting down and crashing afterwards if 'close' is selected in the taskbar-context-menu
|
||||
private void ConfigurationWindow_OnClosed(object sender, EventArgs e)
|
||||
{
|
||||
ApplicationManager.Instance.ExitCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user