Merge branch 'master' into develop
This commit is contained in:
commit
6f5e588e13
@ -0,0 +1,91 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{BB1E8BA4-7965-4E46-B1BE-D2A7C491A204}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>MassiveKnob.Plugin.RunProgram</RootNamespace>
|
||||||
|
<AssemblyName>MassiveKnob.Plugin.RunProgram</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xaml" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="MassiveKnobRunProgramPlugin.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="RunProgram\RunProgramSettingsView.xaml.cs">
|
||||||
|
<DependentUpon>RunProgramSettingsView.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="RunProgram\RunProgramAction.cs" />
|
||||||
|
<Compile Include="RunProgram\RunProgramSettings.cs" />
|
||||||
|
<Compile Include="RunProgram\RunProgramSettingsViewModel.cs" />
|
||||||
|
<Compile Include="Strings.Designer.cs">
|
||||||
|
<DependentUpon>Strings.resx</DependentUpon>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="MassiveKnobPlugin.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MassiveKnob.Plugin\MassiveKnob.Plugin.csproj">
|
||||||
|
<Project>{A1298BE4-1D23-416C-8C56-FC9264487A95}</Project>
|
||||||
|
<Name>MassiveKnob.Plugin</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Strings.resx">
|
||||||
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Strings.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="System.Threading.Tasks.Extensions">
|
||||||
|
<Version>4.5.4</Version>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Include="RunProgram\RunProgramSettingsView.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"EntryAssembly": "MassiveKnob.Plugin.RunProgram.dll"
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using MassiveKnob.Plugin.RunProgram.RunProgram;
|
||||||
|
|
||||||
|
namespace MassiveKnob.Plugin.RunProgram
|
||||||
|
{
|
||||||
|
[MassiveKnobPlugin]
|
||||||
|
public class MassiveKnobRunProgramPlugin : IMassiveKnobActionPlugin
|
||||||
|
{
|
||||||
|
public Guid PluginId { get; } = new Guid("10537f2a-6876-48b8-8ef9-8d05f185fa62");
|
||||||
|
public string Name { get; } = Strings.PluginName;
|
||||||
|
public string Description { get; } = Strings.PluginDescription;
|
||||||
|
public string Author { get; } = "Mark van Renswoude <mark@x2software.net>";
|
||||||
|
public string Url { get; } = "https://www.github.com/MvRens/MassiveKnob/";
|
||||||
|
|
||||||
|
public IEnumerable<IMassiveKnobAction> Actions { get; } = new IMassiveKnobAction[]
|
||||||
|
{
|
||||||
|
new RunProgramAction()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("MassiveKnob.Plugin.RunProgram")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("MassiveKnob.Plugin.RunProgram")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("bb1e8ba4-7965-4e46-b1be-d2a7c491a204")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace MassiveKnob.Plugin.RunProgram.RunProgram
|
||||||
|
{
|
||||||
|
public class RunProgramAction : IMassiveKnobAction
|
||||||
|
{
|
||||||
|
public Guid ActionId { get; } = new Guid("c3a79015-4b8f-414d-9682-02307de8639c");
|
||||||
|
public MassiveKnobActionType ActionType { get; } = MassiveKnobActionType.InputDigital;
|
||||||
|
public string Name { get; } = Strings.RunProgramName;
|
||||||
|
public string Description { get; } = Strings.RunProgramDescription;
|
||||||
|
|
||||||
|
|
||||||
|
public IMassiveKnobActionInstance Create(ILogger logger)
|
||||||
|
{
|
||||||
|
return new Instance(logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class Instance : IMassiveKnobDigitalAction
|
||||||
|
{
|
||||||
|
private readonly ILogger logger;
|
||||||
|
private IMassiveKnobActionContext actionContext;
|
||||||
|
private RunProgramSettings settings;
|
||||||
|
|
||||||
|
|
||||||
|
public Instance(ILogger logger)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Initialize(IMassiveKnobActionContext context)
|
||||||
|
{
|
||||||
|
actionContext = context;
|
||||||
|
settings = context.GetSettings<RunProgramSettings>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public UserControl CreateSettingsControl()
|
||||||
|
{
|
||||||
|
var viewModel = new RunProgramSettingsViewModel(settings);
|
||||||
|
viewModel.PropertyChanged += (sender, args) =>
|
||||||
|
{
|
||||||
|
actionContext.SetSettings(settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
return new RunProgramSettingsView(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ValueTask DigitalChanged(bool on)
|
||||||
|
{
|
||||||
|
if (!on)
|
||||||
|
return default;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(settings.Filename))
|
||||||
|
return default;
|
||||||
|
|
||||||
|
logger.LogInformation("Run program: filename = {filename}, arguments = {arguments}", settings.Filename, settings.Arguments);
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = settings.Filename,
|
||||||
|
Arguments = settings.Arguments,
|
||||||
|
UseShellExecute = true,
|
||||||
|
Verb = "open"
|
||||||
|
});
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
namespace MassiveKnob.Plugin.RunProgram.RunProgram
|
||||||
|
{
|
||||||
|
public class RunProgramSettings
|
||||||
|
{
|
||||||
|
public string Filename { get; set; }
|
||||||
|
public string Arguments { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<UserControl x:Class="MassiveKnob.Plugin.RunProgram.RunProgram.RunProgramSettingsView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:strings="clr-namespace:MassiveKnob.Plugin.RunProgram"
|
||||||
|
xmlns:runProgram="clr-namespace:MassiveKnob.Plugin.RunProgram.RunProgram"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="200" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance runProgram:RunProgramSettingsViewModel}">
|
||||||
|
<StackPanel Orientation="Vertical">
|
||||||
|
<TextBlock Text="{x:Static strings:Strings.SettingFilename}" />
|
||||||
|
<DockPanel>
|
||||||
|
<Button Click="ButtonBrowseClick" DockPanel.Dock="Right" Padding="4,0,4,0">...</Button>
|
||||||
|
<TextBox Text="{Binding Filename}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<TextBlock Text="{x:Static strings:Strings.SettingArguments}" Margin="0,8,0,0" />
|
||||||
|
<TextBox Text="{Binding Arguments}" />
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
@ -0,0 +1,27 @@
|
|||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace MassiveKnob.Plugin.RunProgram.RunProgram
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for RunProgramSettingsView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class RunProgramSettingsView
|
||||||
|
{
|
||||||
|
public RunProgramSettingsView(RunProgramSettingsViewModel viewModel)
|
||||||
|
{
|
||||||
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ButtonBrowseClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var dialog = new Microsoft.Win32.OpenFileDialog
|
||||||
|
{
|
||||||
|
Filter = Strings.FilenameDialogFilter
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dialog.ShowDialog().GetValueOrDefault())
|
||||||
|
((RunProgramSettingsViewModel) DataContext).Filename = dialog.FileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace MassiveKnob.Plugin.RunProgram.RunProgram
|
||||||
|
{
|
||||||
|
public class RunProgramSettingsViewModel : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private readonly RunProgramSettings settings;
|
||||||
|
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
||||||
|
public string Filename
|
||||||
|
{
|
||||||
|
get => settings.Filename;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == settings.Filename)
|
||||||
|
return;
|
||||||
|
|
||||||
|
settings.Filename = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Arguments
|
||||||
|
{
|
||||||
|
get => settings.Arguments;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == settings.Arguments)
|
||||||
|
return;
|
||||||
|
|
||||||
|
settings.Arguments = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
|
public RunProgramSettingsViewModel(RunProgramSettings settings)
|
||||||
|
{
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
126
Windows/MassiveKnob.Plugin.RunProgram/Strings.Designer.cs
generated
Normal file
126
Windows/MassiveKnob.Plugin.RunProgram/Strings.Designer.cs
generated
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace MassiveKnob.Plugin.RunProgram {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
public class Strings {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Strings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
public static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MassiveKnob.Plugin.RunProgram.Strings", typeof(Strings).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
public static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Executable files (*.exe, *.bat, *.cmd)|*.exe,*.bat,*.cmd|All files (*.*)|*.*.
|
||||||
|
/// </summary>
|
||||||
|
public static string FilenameDialogFilter {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("FilenameDialogFilter", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Provides an action to run an application when a button is pressed..
|
||||||
|
/// </summary>
|
||||||
|
public static string PluginDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PluginDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Run Program.
|
||||||
|
/// </summary>
|
||||||
|
public static string PluginName {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PluginName", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Runs an application when a button is pressed..
|
||||||
|
/// </summary>
|
||||||
|
public static string RunProgramDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("RunProgramDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Run program.
|
||||||
|
/// </summary>
|
||||||
|
public static string RunProgramName {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("RunProgramName", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Optional arguments passed to the executable.
|
||||||
|
/// </summary>
|
||||||
|
public static string SettingArguments {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SettingArguments", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Executable, file or URL to open.
|
||||||
|
/// </summary>
|
||||||
|
public static string SettingFilename {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SettingFilename", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
141
Windows/MassiveKnob.Plugin.RunProgram/Strings.resx
Normal file
141
Windows/MassiveKnob.Plugin.RunProgram/Strings.resx
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="FilenameDialogFilter" xml:space="preserve">
|
||||||
|
<value>Executable files (*.exe, *.bat, *.cmd)|*.exe,*.bat,*.cmd|All files (*.*)|*.*</value>
|
||||||
|
</data>
|
||||||
|
<data name="PluginDescription" xml:space="preserve">
|
||||||
|
<value>Provides an action to run an application when a button is pressed.</value>
|
||||||
|
</data>
|
||||||
|
<data name="PluginName" xml:space="preserve">
|
||||||
|
<value>Run Program</value>
|
||||||
|
</data>
|
||||||
|
<data name="RunProgramDescription" xml:space="preserve">
|
||||||
|
<value>Runs an application when a button is pressed.</value>
|
||||||
|
</data>
|
||||||
|
<data name="RunProgramName" xml:space="preserve">
|
||||||
|
<value>Run program</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingArguments" xml:space="preserve">
|
||||||
|
<value>Optional arguments passed to the executable</value>
|
||||||
|
</data>
|
||||||
|
<data name="SettingFilename" xml:space="preserve">
|
||||||
|
<value>Executable, file or URL to open</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
@ -1,7 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global - public API
|
|
||||||
|
|
||||||
namespace MassiveKnob.Plugin
|
namespace MassiveKnob.Plugin
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MassiveKnob.Plugin.VoiceMee
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Voicemeeter", "VoicemeeterRemote\Voicemeeter\Voicemeeter.csproj", "{F35DD8E5-91FA-403E-B6F6-8D2B4AE84198}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Voicemeeter", "VoicemeeterRemote\Voicemeeter\Voicemeeter.csproj", "{F35DD8E5-91FA-403E-B6F6-8D2B4AE84198}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MassiveKnob.Plugin.RunProgram", "MassiveKnob.Plugin.RunProgram\MassiveKnob.Plugin.RunProgram.csproj", "{BB1E8BA4-7965-4E46-B1BE-D2A7C491A204}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -63,6 +65,10 @@ Global
|
|||||||
{F35DD8E5-91FA-403E-B6F6-8D2B4AE84198}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{F35DD8E5-91FA-403E-B6F6-8D2B4AE84198}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F35DD8E5-91FA-403E-B6F6-8D2B4AE84198}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{F35DD8E5-91FA-403E-B6F6-8D2B4AE84198}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F35DD8E5-91FA-403E-B6F6-8D2B4AE84198}.Release|Any CPU.Build.0 = Release|Any CPU
|
{F35DD8E5-91FA-403E-B6F6-8D2B4AE84198}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BB1E8BA4-7965-4E46-B1BE-D2A7C491A204}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BB1E8BA4-7965-4E46-B1BE-D2A7C491A204}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BB1E8BA4-7965-4E46-B1BE-D2A7C491A204}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BB1E8BA4-7965-4E46-B1BE-D2A7C491A204}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
using System.Diagnostics;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using Hardcodet.Wpf.TaskbarNotification;
|
using Hardcodet.Wpf.TaskbarNotification;
|
||||||
using MassiveKnob.View;
|
using MassiveKnob.View;
|
||||||
|
using Serilog;
|
||||||
using SimpleInjector;
|
using SimpleInjector;
|
||||||
|
using WpfBindingErrors;
|
||||||
|
|
||||||
namespace MassiveKnob
|
namespace MassiveKnob
|
||||||
{
|
{
|
||||||
@ -28,6 +31,9 @@ namespace MassiveKnob
|
|||||||
{
|
{
|
||||||
base.OnStartup(e);
|
base.OnStartup(e);
|
||||||
|
|
||||||
|
// Do not let WPF swallow exceptions in bindings
|
||||||
|
BindingExceptionThrower.Attach();
|
||||||
|
|
||||||
notifyIcon = (TaskbarIcon)FindResource("NotifyIcon");
|
notifyIcon = (TaskbarIcon)FindResource("NotifyIcon");
|
||||||
Debug.Assert(notifyIcon != null, nameof(notifyIcon) + " != null");
|
Debug.Assert(notifyIcon != null, nameof(notifyIcon) + " != null");
|
||||||
}
|
}
|
||||||
|
48
Windows/MassiveKnob/ContainerBuilder.cs
Normal file
48
Windows/MassiveKnob/ContainerBuilder.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using MassiveKnob.View;
|
||||||
|
using MassiveKnob.View.Settings;
|
||||||
|
using MassiveKnob.ViewModel;
|
||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
using SimpleInjector;
|
||||||
|
|
||||||
|
namespace MassiveKnob
|
||||||
|
{
|
||||||
|
public static class ContainerBuilder
|
||||||
|
{
|
||||||
|
public static Container Create()
|
||||||
|
{
|
||||||
|
var container = new Container();
|
||||||
|
container.Options.EnableAutoVerification = false;
|
||||||
|
|
||||||
|
container.Register<App>();
|
||||||
|
|
||||||
|
container.Register<SettingsWindow>();
|
||||||
|
container.Register<SettingsViewModel>();
|
||||||
|
|
||||||
|
container.Register<SettingsDeviceView>();
|
||||||
|
container.Register<SettingsDeviceViewModel>();
|
||||||
|
|
||||||
|
container.Register<SettingsAnalogInputsView>();
|
||||||
|
container.Register<SettingsAnalogInputsViewModel>();
|
||||||
|
|
||||||
|
container.Register<SettingsDigitalInputsView>();
|
||||||
|
container.Register<SettingsDigitalInputsViewModel>();
|
||||||
|
|
||||||
|
container.Register<SettingsAnalogOutputsView>();
|
||||||
|
container.Register<SettingsAnalogOutputsViewModel>();
|
||||||
|
|
||||||
|
container.Register<SettingsDigitalOutputsView>();
|
||||||
|
container.Register<SettingsDigitalOutputsViewModel>();
|
||||||
|
|
||||||
|
container.Register<SettingsLoggingView>();
|
||||||
|
container.Register<SettingsLoggingViewModel>();
|
||||||
|
|
||||||
|
container.Register<SettingsStartupView>();
|
||||||
|
container.Register<SettingsStartupViewModel>();
|
||||||
|
|
||||||
|
container.Register<SettingsPluginsView>();
|
||||||
|
container.Register<SettingsPluginsViewModel>();
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,16 @@ namespace MassiveKnob.Core
|
|||||||
{
|
{
|
||||||
public interface IPluginManager
|
public interface IPluginManager
|
||||||
{
|
{
|
||||||
|
IEnumerable<IMassiveKnobPluginInfo> GetPlugins();
|
||||||
|
|
||||||
IEnumerable<IMassiveKnobDevicePlugin> GetDevicePlugins();
|
IEnumerable<IMassiveKnobDevicePlugin> GetDevicePlugins();
|
||||||
IEnumerable<IMassiveKnobActionPlugin> GetActionPlugins();
|
IEnumerable<IMassiveKnobActionPlugin> GetActionPlugins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IMassiveKnobPluginInfo
|
||||||
|
{
|
||||||
|
string Filename { get; }
|
||||||
|
IMassiveKnobPlugin Plugin { get; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ namespace MassiveKnob.Core
|
|||||||
public class PluginManager : IPluginManager
|
public class PluginManager : IPluginManager
|
||||||
{
|
{
|
||||||
private readonly ILogger logger;
|
private readonly ILogger logger;
|
||||||
private readonly List<IMassiveKnobPlugin> plugins = new List<IMassiveKnobPlugin>();
|
private readonly List<IMassiveKnobPluginInfo> plugins = new List<IMassiveKnobPluginInfo>();
|
||||||
|
|
||||||
|
|
||||||
public PluginManager(ILogger logger)
|
public PluginManager(ILogger logger)
|
||||||
@ -43,14 +43,19 @@ namespace MassiveKnob.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<IMassiveKnobPluginInfo> GetPlugins()
|
||||||
|
{
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<IMassiveKnobDevicePlugin> GetDevicePlugins()
|
public IEnumerable<IMassiveKnobDevicePlugin> GetDevicePlugins()
|
||||||
{
|
{
|
||||||
return plugins.Where(p => p is IMassiveKnobDevicePlugin).Cast<IMassiveKnobDevicePlugin>();
|
return plugins.Where(p => p.Plugin is IMassiveKnobDevicePlugin).Select(p => (IMassiveKnobDevicePlugin)p.Plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IMassiveKnobActionPlugin> GetActionPlugins()
|
public IEnumerable<IMassiveKnobActionPlugin> GetActionPlugins()
|
||||||
{
|
{
|
||||||
return plugins.Where(p => p is IMassiveKnobActionPlugin).Cast<IMassiveKnobActionPlugin>();
|
return plugins.Where(p => p.Plugin is IMassiveKnobActionPlugin).Select(p => (IMassiveKnobActionPlugin)p.Plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -190,7 +195,7 @@ namespace MassiveKnob.Core
|
|||||||
logger.Information("Found plugin with Id {pluginId}: {name}", plugin.PluginId, plugin.Name);
|
logger.Information("Found plugin with Id {pluginId}: {name}", plugin.PluginId, plugin.Name);
|
||||||
|
|
||||||
ValidateRegistration(filename, plugin, registeredIds);
|
ValidateRegistration(filename, plugin, registeredIds);
|
||||||
plugins.Add((IMassiveKnobPlugin)pluginInstance);
|
plugins.Add(new PluginInfo(filename, (IMassiveKnobPlugin)pluginInstance));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,5 +285,19 @@ namespace MassiveKnob.Core
|
|||||||
// ReSharper disable once UnusedAutoPropertyAccessor.Local - for JSON deserialization
|
// ReSharper disable once UnusedAutoPropertyAccessor.Local - for JSON deserialization
|
||||||
public string EntryAssembly { get; set; }
|
public string EntryAssembly { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class PluginInfo : IMassiveKnobPluginInfo
|
||||||
|
{
|
||||||
|
public string Filename { get; }
|
||||||
|
public IMassiveKnobPlugin Plugin { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public PluginInfo(string filename, IMassiveKnobPlugin plugin)
|
||||||
|
{
|
||||||
|
Filename = filename;
|
||||||
|
Plugin = plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
<Reference Include="WindowsBase" />
|
<Reference Include="WindowsBase" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="ContainerBuilder.cs" />
|
||||||
<Compile Include="Helpers\ComboBoxTemplateSelector.cs" />
|
<Compile Include="Helpers\ComboBoxTemplateSelector.cs" />
|
||||||
<Compile Include="Helpers\ComparisonConverter.cs" />
|
<Compile Include="Helpers\ComparisonConverter.cs" />
|
||||||
<Compile Include="Helpers\SerialQueue.cs" />
|
<Compile Include="Helpers\SerialQueue.cs" />
|
||||||
@ -72,10 +73,17 @@
|
|||||||
<Compile Include="ViewModel\DeviceViewModel.cs" />
|
<Compile Include="ViewModel\DeviceViewModel.cs" />
|
||||||
<Compile Include="ViewModel\InputOutputViewModel.cs" />
|
<Compile Include="ViewModel\InputOutputViewModel.cs" />
|
||||||
<Compile Include="ViewModel\MenuItemProperties.cs" />
|
<Compile Include="ViewModel\MenuItemProperties.cs" />
|
||||||
|
<Compile Include="ViewModel\PluginViewModel.cs" />
|
||||||
<Compile Include="ViewModel\SettingsViewModel.cs" />
|
<Compile Include="ViewModel\SettingsViewModel.cs" />
|
||||||
<Compile Include="View\InputOutputView.xaml.cs">
|
<Compile Include="ViewModel\Settings\SettingsAnalogOutputsViewModel.cs" />
|
||||||
<DependentUpon>InputOutputView.xaml</DependentUpon>
|
<Compile Include="ViewModel\Settings\SettingsDigitalOutputsViewModel.cs" />
|
||||||
</Compile>
|
<Compile Include="ViewModel\Settings\SettingsDigitalInputsViewModel.cs" />
|
||||||
|
<Compile Include="ViewModel\Settings\SettingsAnalogInputsViewModel.cs" />
|
||||||
|
<Compile Include="ViewModel\Settings\SettingsDeviceViewModel.cs" />
|
||||||
|
<Compile Include="ViewModel\Settings\BaseSettingsInputOutputViewModel.cs" />
|
||||||
|
<Compile Include="ViewModel\Settings\SettingsLoggingViewModel.cs" />
|
||||||
|
<Compile Include="ViewModel\Settings\SettingsPluginsViewModel.cs" />
|
||||||
|
<Compile Include="ViewModel\Settings\SettingsStartupViewModel.cs" />
|
||||||
<Compile Include="View\SettingsWindow.xaml.cs">
|
<Compile Include="View\SettingsWindow.xaml.cs">
|
||||||
<DependentUpon>SettingsWindow.xaml</DependentUpon>
|
<DependentUpon>SettingsWindow.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@ -88,26 +96,24 @@
|
|||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<DependentUpon>Strings.resx</DependentUpon>
|
<DependentUpon>Strings.resx</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="View\Settings\AnalogInputsView.xaml.cs">
|
<Compile Include="View\Settings\BaseSettingsInputOutputView.xaml.cs">
|
||||||
<DependentUpon>AnalogInputsView.xaml</DependentUpon>
|
<DependentUpon>BaseSettingsInputOutputView.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="View\Settings\AnalogOutputsView.xaml.cs">
|
<Compile Include="View\Settings\SettingsAnalogOutputsView.cs" />
|
||||||
<DependentUpon>AnalogOutputsView.xaml</DependentUpon>
|
<Compile Include="View\Settings\SettingsDigitalOutputsView.cs" />
|
||||||
|
<Compile Include="View\Settings\SettingsDigitalInputsView.cs" />
|
||||||
|
<Compile Include="View\Settings\SettingsAnalogInputsView.cs" />
|
||||||
|
<Compile Include="View\Settings\SettingsPluginsView.xaml.cs">
|
||||||
|
<DependentUpon>SettingsPluginsView.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="View\Settings\StartupView.xaml.cs">
|
<Compile Include="View\Settings\SettingsStartupView.xaml.cs">
|
||||||
<DependentUpon>StartupView.xaml</DependentUpon>
|
<DependentUpon>SettingsStartupView.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="View\Settings\LoggingView.xaml.cs">
|
<Compile Include="View\Settings\SettingsLoggingView.xaml.cs">
|
||||||
<DependentUpon>LoggingView.xaml</DependentUpon>
|
<DependentUpon>SettingsLoggingView.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="View\Settings\DigitalInputsView.xaml.cs">
|
<Compile Include="View\Settings\SettingsDeviceView.xaml.cs">
|
||||||
<DependentUpon>DigitalInputsView.xaml</DependentUpon>
|
<DependentUpon>SettingsDeviceView.xaml</DependentUpon>
|
||||||
</Compile>
|
|
||||||
<Compile Include="View\Settings\DigitalOutputsView.xaml.cs">
|
|
||||||
<DependentUpon>DigitalOutputsView.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="View\Settings\DeviceView.xaml.cs">
|
|
||||||
<DependentUpon>DeviceView.xaml</DependentUpon>
|
|
||||||
</Compile>
|
</Compile>
|
||||||
<EmbeddedResource Include="Strings.resx">
|
<EmbeddedResource Include="Strings.resx">
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
@ -158,6 +164,9 @@
|
|||||||
<PackageReference Include="System.Reactive">
|
<PackageReference Include="System.Reactive">
|
||||||
<Version>5.0.0</Version>
|
<Version>5.0.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="WpfBindingErrors">
|
||||||
|
<Version>1.1.0</Version>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Resource Include="Resources\MainIcon.ico" />
|
<Resource Include="Resources\MainIcon.ico" />
|
||||||
@ -192,35 +201,31 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Resources\Plugins.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
<Page Include="Resources\Startup.xaml">
|
<Page Include="Resources\Startup.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="View\Settings\AnalogInputsView.xaml">
|
<Page Include="View\Settings\BaseSettingsInputOutputView.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="View\Settings\AnalogOutputsView.xaml">
|
<Page Include="View\Settings\SettingsPluginsView.xaml">
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="View\Settings\StartupView.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="View\Settings\LoggingView.xaml">
|
<Page Include="View\Settings\SettingsStartupView.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="View\Settings\DigitalInputsView.xaml">
|
<Page Include="View\Settings\SettingsLoggingView.xaml">
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
|
||||||
<Page Include="View\Settings\DigitalOutputsView.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="View\Settings\DeviceView.xaml">
|
<Page Include="View\Settings\SettingsDeviceView.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
@ -230,10 +235,6 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="View\InputOutputView.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="View\SettingsWindow.xaml">
|
<Page Include="View\SettingsWindow.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
@ -4,10 +4,7 @@ using System.Text;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using MassiveKnob.Core;
|
using MassiveKnob.Core;
|
||||||
using MassiveKnob.Settings;
|
using MassiveKnob.Settings;
|
||||||
using MassiveKnob.View;
|
|
||||||
using MassiveKnob.ViewModel;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using SimpleInjector;
|
|
||||||
|
|
||||||
namespace MassiveKnob
|
namespace MassiveKnob
|
||||||
{
|
{
|
||||||
@ -19,23 +16,40 @@ namespace MassiveKnob
|
|||||||
{
|
{
|
||||||
var settings = MassiveKnobSettingsJsonSerializer.Deserialize();
|
var settings = MassiveKnobSettingsJsonSerializer.Deserialize();
|
||||||
|
|
||||||
|
|
||||||
var loggingSwitch = new LoggingSwitch();
|
var loggingSwitch = new LoggingSwitch();
|
||||||
loggingSwitch.SetLogging(settings.Log.Enabled, settings.Log.Level);
|
loggingSwitch.SetLogging(settings.Log.Enabled, settings.Log.Level);
|
||||||
|
|
||||||
|
var logFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"MassiveKnob", @"Logs");
|
||||||
|
|
||||||
var logger = new LoggerConfiguration()
|
var logger = new LoggerConfiguration()
|
||||||
.MinimumLevel.Verbose()
|
.MinimumLevel.Verbose()
|
||||||
.Filter.ByIncludingOnly(loggingSwitch.IsIncluded)
|
.Filter.ByIncludingOnly(loggingSwitch.IsIncluded)
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
.WriteTo.File(
|
.WriteTo.File(
|
||||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"MassiveKnob", @"Logs", @".log"),
|
Path.Combine(logFilePath, @".log"),
|
||||||
rollingInterval: RollingInterval.Day,
|
rollingInterval: RollingInterval.Day,
|
||||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{@Context}{NewLine}{Exception}")
|
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{@Context}{NewLine}{Exception}")
|
||||||
.CreateLogger();
|
.CreateLogger();
|
||||||
|
|
||||||
|
|
||||||
logger.Information("MassiveKnob starting");
|
logger.Information("MassiveKnob starting");
|
||||||
var pluginManager = new PluginManager(logger);
|
|
||||||
|
|
||||||
|
|
||||||
|
AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
|
||||||
|
{
|
||||||
|
var e = (Exception)args.ExceptionObject;
|
||||||
|
logger.Error(e, "Unhandled exception: {message}", e.Message);
|
||||||
|
|
||||||
|
MessageBox.Show(
|
||||||
|
"Oops, something went very wrong. Please notify the developer and include this message, you can copy it using Ctrl-C. " +
|
||||||
|
"Preferably also include the log file which can be found at:" + Environment.NewLine + logFilePath +
|
||||||
|
Environment.NewLine + Environment.NewLine +
|
||||||
|
e.Message, "Massive Knob - Fatal error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var pluginManager = new PluginManager(logger);
|
||||||
var messages = new StringBuilder();
|
var messages = new StringBuilder();
|
||||||
pluginManager.Load((exception, filename) =>
|
pluginManager.Load((exception, filename) =>
|
||||||
{
|
{
|
||||||
@ -48,23 +62,17 @@ namespace MassiveKnob
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var orchestrator = new MassiveKnobOrchestrator(pluginManager, logger, settings);
|
var orchestrator = new MassiveKnobOrchestrator(pluginManager, logger, settings);
|
||||||
orchestrator.Load();
|
orchestrator.Load();
|
||||||
|
|
||||||
|
|
||||||
var container = new Container();
|
var container = ContainerBuilder.Create();
|
||||||
container.Options.EnableAutoVerification = false;
|
container.RegisterInstance<ILogger>(logger);
|
||||||
|
|
||||||
container.RegisterInstance(logger);
|
|
||||||
container.RegisterInstance<ILoggingSwitch>(loggingSwitch);
|
container.RegisterInstance<ILoggingSwitch>(loggingSwitch);
|
||||||
container.RegisterInstance<IPluginManager>(pluginManager);
|
container.RegisterInstance<IPluginManager>(pluginManager);
|
||||||
container.RegisterInstance<IMassiveKnobOrchestrator>(orchestrator);
|
container.RegisterInstance<IMassiveKnobOrchestrator>(orchestrator);
|
||||||
|
|
||||||
container.Register<App>();
|
|
||||||
container.Register<SettingsWindow>();
|
|
||||||
container.Register<SettingsViewModel>();
|
|
||||||
|
|
||||||
|
|
||||||
var app = container.GetInstance<App>();
|
var app = container.GetInstance<App>();
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
||||||
|
17
Windows/MassiveKnob/Resources/Plugins.xaml
Normal file
17
Windows/MassiveKnob/Resources/Plugins.xaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
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"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Viewbox Stretch="Uniform" x:Key="Plugins" x:Shared="False">
|
||||||
|
<Canvas Width="24" Height="24">
|
||||||
|
<Canvas.Resources>
|
||||||
|
<ResourceDictionary Source="IconStyle.xaml" />
|
||||||
|
</Canvas.Resources>
|
||||||
|
<Polygon Points="12 2 2 7 12 12 22 7 12 2" FillRule="NonZero" Style="{StaticResource IconStroke}" />
|
||||||
|
<Polyline Points="2 17 12 22 22 17" FillRule="NonZero" Style="{StaticResource IconStroke}" />
|
||||||
|
<Polyline Points="2 12 12 17 22 12" FillRule="NonZero" Style="{StaticResource IconStroke}" />
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
</ResourceDictionary>
|
@ -15,7 +15,8 @@ namespace MassiveKnob.Settings
|
|||||||
AnalogOutputs,
|
AnalogOutputs,
|
||||||
DigitalOutputs,
|
DigitalOutputs,
|
||||||
Logging,
|
Logging,
|
||||||
Startup
|
Startup,
|
||||||
|
Plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
9
Windows/MassiveKnob/Strings.Designer.cs
generated
9
Windows/MassiveKnob/Strings.Designer.cs
generated
@ -303,6 +303,15 @@ namespace MassiveKnob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Plugins.
|
||||||
|
/// </summary>
|
||||||
|
public static string MenuItemPlugins {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("MenuItemPlugins", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Startup.
|
/// Looks up a localized string similar to Startup.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -198,6 +198,9 @@
|
|||||||
<data name="MenuItemLogging" xml:space="preserve">
|
<data name="MenuItemLogging" xml:space="preserve">
|
||||||
<value>Logging</value>
|
<value>Logging</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MenuItemPlugins" xml:space="preserve">
|
||||||
|
<value>Plugins</value>
|
||||||
|
</data>
|
||||||
<data name="MenuItemStartup" xml:space="preserve">
|
<data name="MenuItemStartup" xml:space="preserve">
|
||||||
<value>Startup</value>
|
<value>Startup</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
<Setter Property="Margin" Value="0,0,0,4" />
|
<Setter Property="Margin" Value="0,0,0,4" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style TargetType="StackPanel" x:Key="Content">
|
<Style x:Key="Content">
|
||||||
<Setter Property="Margin" Value="8" />
|
<Setter Property="Control.Margin" Value="8" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style TargetType="ContentControl" x:Key="SettingsControl">
|
<Style TargetType="ContentControl" x:Key="SettingsControl">
|
||||||
@ -41,4 +41,30 @@
|
|||||||
<Style TargetType="TextBlock" x:Key="SubLabel">
|
<Style TargetType="TextBlock" x:Key="SubLabel">
|
||||||
<Setter Property="Foreground" Value="#808080" />
|
<Setter Property="Foreground" Value="#808080" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBlock" x:Key="PluginName">
|
||||||
|
<Setter Property="FontWeight" Value="Bold" />
|
||||||
|
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBlock" x:Key="PluginDescription">
|
||||||
|
<Setter Property="TextWrapping" Value="Wrap" />
|
||||||
|
<Setter Property="Margin" Value="0,0,0,8" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBlock" x:Key="PluginFilename">
|
||||||
|
<Setter Property="TextWrapping" Value="Wrap" />
|
||||||
|
<Setter Property="Foreground" Value="#808080" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBlock" x:Key="PluginAuthor">
|
||||||
|
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
|
||||||
|
<Setter Property="Margin" Value="0,8,0,0" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBlock" x:Key="PluginUrl">
|
||||||
|
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
|
||||||
|
<Setter Property="Foreground" Value="Navy" />
|
||||||
|
<Setter Property="Margin" Value="0,0,0,8" />
|
||||||
|
</Style>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
@ -1,65 +0,0 @@
|
|||||||
<UserControl x:Class="MassiveKnob.View.InputOutputView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:helpers="clr-namespace:MassiveKnob.Helpers"
|
|
||||||
xmlns:viewModel="clr-namespace:MassiveKnob.ViewModel"
|
|
||||||
xmlns:massiveKnob="clr-namespace:MassiveKnob"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="300" d:DesignWidth="600"
|
|
||||||
d:DataContext="{d:DesignInstance viewModel:InputOutputViewModelDesignTime, IsDesignTimeCreatable=True}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="../Style.xaml"></ResourceDictionary>
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
|
|
||||||
<DataTemplate x:Key="ActionDropdownItem">
|
|
||||||
<StackPanel Orientation="Vertical" d:DataContext="{d:DesignInstance Type=viewModel:ActionViewModel}">
|
|
||||||
<TextBlock Text="{Binding Name}" />
|
|
||||||
<TextBlock Text="{Binding Description}" Style="{StaticResource ComboBoxDescription}" Visibility="{Binding DescriptionVisibility}" />
|
|
||||||
</StackPanel>
|
|
||||||
</DataTemplate>
|
|
||||||
|
|
||||||
<DataTemplate x:Key="ActionSelectedItem">
|
|
||||||
<TextBlock Text="{Binding Name}" d:DataContext="{d:DesignInstance Type=viewModel:ActionViewModel}" />
|
|
||||||
</DataTemplate>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
<StackPanel Orientation="Vertical" Style="{StaticResource Content}">
|
|
||||||
<TextBlock Text="{Binding DisplayName}" Style="{StaticResource SubHeader}"></TextBlock>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical">
|
|
||||||
<ComboBox
|
|
||||||
ItemsSource="{Binding Actions}"
|
|
||||||
SelectedItem="{Binding SelectedAction}"
|
|
||||||
IsSynchronizedWithCurrentItem="False"
|
|
||||||
ItemTemplateSelector="{helpers:ComboBoxTemplateSelector
|
|
||||||
SelectedItemTemplate={StaticResource ActionSelectedItem},
|
|
||||||
DropdownItemsTemplate={StaticResource ActionDropdownItem}}" />
|
|
||||||
|
|
||||||
<ContentControl Focusable="False" Content="{Binding ActionSettingsControl}" Style="{StaticResource SettingsControl}" />
|
|
||||||
|
|
||||||
<Grid Margin="0,24,0,0" Visibility="{Binding DigitalToAnalogVisibility}">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition />
|
|
||||||
<RowDefinition />
|
|
||||||
<RowDefinition />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Text="{x:Static massiveKnob:Strings.DigitalToAnalogDescription}" TextWrapping="Wrap" />
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0" Margin="0,8,8,8" VerticalAlignment="Center" Text="{x:Static massiveKnob:Strings.DigitalToAnalogOn}" />
|
|
||||||
<Slider Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Value="{Binding DigitalToAnalogOn}" Minimum="0" Maximum="100" />
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="2" Grid.Column="0" Margin="0,8,8,8" VerticalAlignment="Center" Text="{x:Static massiveKnob:Strings.DigitalToAnalogOff}" />
|
|
||||||
<Slider Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Value="{Binding DigitalToAnalogOff}" Minimum="0" Maximum="100" />
|
|
||||||
</Grid>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
|
||||||
</UserControl>
|
|
@ -1,13 +0,0 @@
|
|||||||
namespace MassiveKnob.View
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for InputOutputView.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class InputOutputView
|
|
||||||
{
|
|
||||||
public InputOutputView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
<UserControl x:Class="MassiveKnob.View.Settings.AnalogInputsView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:viewModel="clr-namespace:MassiveKnob.ViewModel"
|
|
||||||
xmlns:view="clr-namespace:MassiveKnob.View"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="300" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance Type=viewModel:SettingsViewModelDesignTime, IsDesignTimeCreatable=True}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="../../Style.xaml" />
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" SnapsToDevicePixels="True" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display">
|
|
||||||
<ItemsControl ItemsSource="{Binding AnalogInputs}">
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<view:InputOutputView />
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
|
|
||||||
</StackPanel>
|
|
||||||
</UserControl>
|
|
@ -1,13 +0,0 @@
|
|||||||
namespace MassiveKnob.View.Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for AnalogInputsView.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class AnalogInputsView
|
|
||||||
{
|
|
||||||
public AnalogInputsView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
<UserControl x:Class="MassiveKnob.View.Settings.AnalogOutputsView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:viewModel="clr-namespace:MassiveKnob.ViewModel"
|
|
||||||
xmlns:view="clr-namespace:MassiveKnob.View"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="300" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance Type=viewModel:SettingsViewModelDesignTime, IsDesignTimeCreatable=True}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="../../Style.xaml" />
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" SnapsToDevicePixels="True" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display">
|
|
||||||
<ItemsControl ItemsSource="{Binding AnalogOutputs}">
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<view:InputOutputView />
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
</StackPanel>
|
|
||||||
</UserControl>
|
|
@ -1,13 +0,0 @@
|
|||||||
namespace MassiveKnob.View.Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for AnalogOutputsView.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class AnalogOutputsView
|
|
||||||
{
|
|
||||||
public AnalogOutputsView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,75 @@
|
|||||||
|
<UserControl x:Class="MassiveKnob.View.Settings.BaseSettingsInputOutputView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:settings="clr-namespace:MassiveKnob.ViewModel.Settings"
|
||||||
|
xmlns:viewModel="clr-namespace:MassiveKnob.ViewModel"
|
||||||
|
xmlns:massiveKnob="clr-namespace:MassiveKnob"
|
||||||
|
xmlns:helpers="clr-namespace:MassiveKnob.Helpers"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="300" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance Type=settings:BaseSettingsInputOutputViewModelDesignTime, IsDesignTimeCreatable=True}">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="../../Style.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
|
||||||
|
<DataTemplate x:Key="ActionDropdownItem">
|
||||||
|
<StackPanel Orientation="Vertical" d:DataContext="{d:DesignInstance Type=viewModel:ActionViewModel}">
|
||||||
|
<TextBlock Text="{Binding Name}" />
|
||||||
|
<TextBlock Text="{Binding Description}" Style="{StaticResource ComboBoxDescription}" Visibility="{Binding DescriptionVisibility}" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
|
||||||
|
<DataTemplate x:Key="ActionSelectedItem">
|
||||||
|
<TextBlock Text="{Binding Name}" d:DataContext="{d:DesignInstance Type=viewModel:ActionViewModel}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</UserControl.Resources>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" SnapsToDevicePixels="True" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display">
|
||||||
|
<ItemsControl ItemsSource="{Binding InputOutputs}">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Vertical" Style="{StaticResource Content}">
|
||||||
|
<TextBlock Text="{Binding DisplayName}" Style="{StaticResource SubHeader}"></TextBlock>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical">
|
||||||
|
<ComboBox
|
||||||
|
ItemsSource="{Binding Actions}"
|
||||||
|
SelectedItem="{Binding SelectedAction}"
|
||||||
|
IsSynchronizedWithCurrentItem="False"
|
||||||
|
ItemTemplateSelector="{helpers:ComboBoxTemplateSelector
|
||||||
|
SelectedItemTemplate={StaticResource ActionSelectedItem},
|
||||||
|
DropdownItemsTemplate={StaticResource ActionDropdownItem}}" />
|
||||||
|
|
||||||
|
<ContentControl Focusable="False" Content="{Binding ActionSettingsControl}" Style="{StaticResource SettingsControl}" />
|
||||||
|
|
||||||
|
<Grid Margin="0,24,0,0" Visibility="{Binding DigitalToAnalogVisibility}">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Text="{x:Static massiveKnob:Strings.DigitalToAnalogDescription}" TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0" Margin="0,8,8,8" VerticalAlignment="Center" Text="{x:Static massiveKnob:Strings.DigitalToAnalogOn}" />
|
||||||
|
<Slider Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Value="{Binding DigitalToAnalogOn}" Minimum="0" Maximum="100" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="2" Grid.Column="0" Margin="0,8,8,8" VerticalAlignment="Center" Text="{x:Static massiveKnob:Strings.DigitalToAnalogOff}" />
|
||||||
|
<Slider Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Value="{Binding DigitalToAnalogOff}" Minimum="0" Maximum="100" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
@ -0,0 +1,16 @@
|
|||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for BaseSettingsInputOutputView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class BaseSettingsInputOutputView
|
||||||
|
{
|
||||||
|
public BaseSettingsInputOutputView(BaseSettingsInputOutputViewModel viewModel)
|
||||||
|
{
|
||||||
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +0,0 @@
|
|||||||
namespace MassiveKnob.View.Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for DeviceView.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class DeviceView
|
|
||||||
{
|
|
||||||
public DeviceView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
<UserControl x:Class="MassiveKnob.View.Settings.DigitalInputsView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:viewModel="clr-namespace:MassiveKnob.ViewModel"
|
|
||||||
xmlns:view="clr-namespace:MassiveKnob.View"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="300" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance Type=viewModel:SettingsViewModelDesignTime, IsDesignTimeCreatable=True}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="../../Style.xaml" />
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" SnapsToDevicePixels="True" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display">
|
|
||||||
<ItemsControl ItemsSource="{Binding DigitalInputs}">
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<view:InputOutputView />
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
</StackPanel>
|
|
||||||
</UserControl>
|
|
@ -1,13 +0,0 @@
|
|||||||
namespace MassiveKnob.View.Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for DigitalInputsView.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class DigitalInputsView
|
|
||||||
{
|
|
||||||
public DigitalInputsView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
<UserControl x:Class="MassiveKnob.View.Settings.DigitalOutputsView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:viewModel="clr-namespace:MassiveKnob.ViewModel"
|
|
||||||
xmlns:view="clr-namespace:MassiveKnob.View"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="300" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance Type=viewModel:SettingsViewModelDesignTime, IsDesignTimeCreatable=True}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="../../Style.xaml" />
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" SnapsToDevicePixels="True" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display">
|
|
||||||
<ItemsControl ItemsSource="{Binding DigitalOutputs}">
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<view:InputOutputView />
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
</StackPanel>
|
|
||||||
</UserControl>
|
|
@ -1,13 +0,0 @@
|
|||||||
namespace MassiveKnob.View.Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for DigitalOutputsView.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class DigitalOutputsView
|
|
||||||
{
|
|
||||||
public DigitalOutputsView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
namespace MassiveKnob.View.Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for LoggingView.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class LoggingView
|
|
||||||
{
|
|
||||||
public LoggingView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,12 @@
|
|||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
public class SettingsAnalogInputsView : BaseSettingsInputOutputView
|
||||||
|
{
|
||||||
|
// ReSharper disable once SuggestBaseTypeForParameter - required for injection
|
||||||
|
public SettingsAnalogInputsView(SettingsAnalogInputsViewModel viewModel) : base(viewModel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
public class SettingsAnalogOutputsView : BaseSettingsInputOutputView
|
||||||
|
{
|
||||||
|
// ReSharper disable once SuggestBaseTypeForParameter - required for injection
|
||||||
|
public SettingsAnalogOutputsView(SettingsAnalogOutputsViewModel viewModel) : base(viewModel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,14 @@
|
|||||||
<UserControl x:Class="MassiveKnob.View.Settings.DeviceView"
|
<UserControl x:Class="MassiveKnob.View.Settings.SettingsDeviceView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:viewModel="clr-namespace:MassiveKnob.ViewModel"
|
xmlns:viewModel="clr-namespace:MassiveKnob.ViewModel"
|
||||||
xmlns:helpers="clr-namespace:MassiveKnob.Helpers"
|
xmlns:helpers="clr-namespace:MassiveKnob.Helpers"
|
||||||
|
xmlns:settings="clr-namespace:MassiveKnob.ViewModel.Settings"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="200" d:DesignWidth="800"
|
d:DesignHeight="200" d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance Type=viewModel:SettingsViewModelDesignTime, IsDesignTimeCreatable=True}">
|
d:DataContext="{d:DesignInstance Type=settings:SettingsDeviceViewModelDesignTime, IsDesignTimeCreatable=True}">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
16
Windows/MassiveKnob/View/Settings/SettingsDeviceView.xaml.cs
Normal file
16
Windows/MassiveKnob/View/Settings/SettingsDeviceView.xaml.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for SettingsDeviceView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class SettingsDeviceView
|
||||||
|
{
|
||||||
|
public SettingsDeviceView(SettingsDeviceViewModel viewModel)
|
||||||
|
{
|
||||||
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
public class SettingsDigitalInputsView : BaseSettingsInputOutputView
|
||||||
|
{
|
||||||
|
// ReSharper disable once SuggestBaseTypeForParameter - required for injection
|
||||||
|
public SettingsDigitalInputsView(SettingsDigitalInputsViewModel viewModel) : base(viewModel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
public class SettingsDigitalOutputsView : BaseSettingsInputOutputView
|
||||||
|
{
|
||||||
|
// ReSharper disable once SuggestBaseTypeForParameter - required for injection
|
||||||
|
public SettingsDigitalOutputsView(SettingsDigitalOutputsViewModel viewModel) : base(viewModel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
<UserControl x:Class="MassiveKnob.View.Settings.LoggingView"
|
<UserControl x:Class="MassiveKnob.View.Settings.SettingsLoggingView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
@ -0,0 +1,16 @@
|
|||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for SettingsLoggingView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class SettingsLoggingView
|
||||||
|
{
|
||||||
|
public SettingsLoggingView(SettingsLoggingViewModel viewModel)
|
||||||
|
{
|
||||||
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
Windows/MassiveKnob/View/Settings/SettingsPluginsView.xaml
Normal file
31
Windows/MassiveKnob/View/Settings/SettingsPluginsView.xaml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<UserControl x:Class="MassiveKnob.View.Settings.SettingsPluginsView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:settings="clr-namespace:MassiveKnob.ViewModel.Settings"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="200" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance Type=settings:SettingsPluginsViewModelDesignTime, IsDesignTimeCreatable=True}">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="../../Style.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</UserControl.Resources>
|
||||||
|
|
||||||
|
<ItemsControl ItemsSource="{Binding Plugins}" SnapsToDevicePixels="True" UseLayoutRounding="True" TextOptions.TextFormattingMode="Display" Style="{StaticResource Content}">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Vertical" Margin="0,0,0,24">
|
||||||
|
<TextBlock Text="{Binding Name}" Style="{StaticResource PluginName}" />
|
||||||
|
<TextBlock Text="{Binding Description}" Visibility="{Binding DescriptionVisibility}" Style="{StaticResource PluginDescription}" />
|
||||||
|
<TextBlock Text="{Binding Author}" Visibility="{Binding AuthorVisibility}" Style="{StaticResource PluginAuthor}" />
|
||||||
|
<TextBlock Text="{Binding Url}" Cursor="{x:Static Cursors.Hand}" MouseDown="UrlMouseDown" Visibility="{Binding UrlVisibility}" Style="{StaticResource PluginUrl}" />
|
||||||
|
<TextBlock Text="{Binding Filename}" Style="{StaticResource PluginFilename}" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</UserControl>
|
@ -0,0 +1,31 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using MassiveKnob.ViewModel;
|
||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for SettingsPluginsView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class SettingsPluginsView
|
||||||
|
{
|
||||||
|
public SettingsPluginsView(SettingsPluginsViewModel viewModel)
|
||||||
|
{
|
||||||
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UrlMouseDown(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
var dataContext = ((FrameworkElement) e.Source).DataContext;
|
||||||
|
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = ((PluginViewModel) dataContext).Url,
|
||||||
|
Verb = "open"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
<UserControl x:Class="MassiveKnob.View.Settings.StartupView"
|
<UserControl x:Class="MassiveKnob.View.Settings.SettingsStartupView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
@ -0,0 +1,16 @@
|
|||||||
|
using MassiveKnob.ViewModel.Settings;
|
||||||
|
|
||||||
|
namespace MassiveKnob.View.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for SettingsStartupView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class SettingsStartupView
|
||||||
|
{
|
||||||
|
public SettingsStartupView(SettingsStartupViewModel viewModel)
|
||||||
|
{
|
||||||
|
DataContext = viewModel;
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +0,0 @@
|
|||||||
namespace MassiveKnob.View.Settings
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Interaction logic for StartupView.xaml
|
|
||||||
/// </summary>
|
|
||||||
public partial class StartupView
|
|
||||||
{
|
|
||||||
public StartupView()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -23,6 +23,7 @@
|
|||||||
<ResourceDictionary Source="../Resources/Logging.xaml" />
|
<ResourceDictionary Source="../Resources/Logging.xaml" />
|
||||||
<ResourceDictionary Source="../Resources/Device.xaml" />
|
<ResourceDictionary Source="../Resources/Device.xaml" />
|
||||||
<ResourceDictionary Source="../Resources/Startup.xaml" />
|
<ResourceDictionary Source="../Resources/Startup.xaml" />
|
||||||
|
<ResourceDictionary Source="../Resources/Plugins.xaml" />
|
||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
|
||||||
<helpers:ComparisonConverter x:Key="ComparisonConverter" />
|
<helpers:ComparisonConverter x:Key="ComparisonConverter" />
|
||||||
@ -81,6 +82,7 @@
|
|||||||
<TextBlock Style="{StaticResource MenuGroup}" Text="{x:Static massiveKnob:Strings.MenuGroupSettings}" />
|
<TextBlock Style="{StaticResource MenuGroup}" Text="{x:Static massiveKnob:Strings.MenuGroupSettings}" />
|
||||||
<RadioButton Style="{StaticResource MenuItem}" viewModel:MenuItemProperties.Text="{x:Static massiveKnob:Strings.MenuItemLogging}" viewModel:MenuItemProperties.Icon="{StaticResource Logging}" IsChecked="{Binding Path=SelectedMenuItem, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static settings:SettingsMenuItem.Logging}}"/>
|
<RadioButton Style="{StaticResource MenuItem}" viewModel:MenuItemProperties.Text="{x:Static massiveKnob:Strings.MenuItemLogging}" viewModel:MenuItemProperties.Icon="{StaticResource Logging}" IsChecked="{Binding Path=SelectedMenuItem, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static settings:SettingsMenuItem.Logging}}"/>
|
||||||
<RadioButton Style="{StaticResource MenuItem}" viewModel:MenuItemProperties.Text="{x:Static massiveKnob:Strings.MenuItemStartup}" viewModel:MenuItemProperties.Icon="{StaticResource Startup}" IsChecked="{Binding Path=SelectedMenuItem, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static settings:SettingsMenuItem.Startup}}"/>
|
<RadioButton Style="{StaticResource MenuItem}" viewModel:MenuItemProperties.Text="{x:Static massiveKnob:Strings.MenuItemStartup}" viewModel:MenuItemProperties.Icon="{StaticResource Startup}" IsChecked="{Binding Path=SelectedMenuItem, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static settings:SettingsMenuItem.Startup}}"/>
|
||||||
|
<RadioButton Style="{StaticResource MenuItem}" viewModel:MenuItemProperties.Text="{x:Static massiveKnob:Strings.MenuItemPlugins}" viewModel:MenuItemProperties.Icon="{StaticResource Plugins}" IsChecked="{Binding Path=SelectedMenuItem, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static settings:SettingsMenuItem.Plugins}}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
// ReSharper restore UnusedMember.Global
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
public InputOutputViewModel(SettingsViewModel settingsViewModel, IMassiveKnobOrchestrator orchestrator,
|
public InputOutputViewModel(IEnumerable<ActionViewModel> allActions, IMassiveKnobOrchestrator orchestrator,
|
||||||
MassiveKnobActionType actionType, int index)
|
MassiveKnobActionType actionType, int index)
|
||||||
{
|
{
|
||||||
this.orchestrator = orchestrator;
|
this.orchestrator = orchestrator;
|
||||||
@ -155,7 +155,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Actions = settingsViewModel.Actions.Where(AllowAction).ToList();
|
Actions = allActions.Where(AllowAction).ToList();
|
||||||
|
|
||||||
var actionInfo = orchestrator.GetAction(actionType, index);
|
var actionInfo = orchestrator.GetAction(actionType, index);
|
||||||
|
|
||||||
|
29
Windows/MassiveKnob/ViewModel/PluginViewModel.cs
Normal file
29
Windows/MassiveKnob/ViewModel/PluginViewModel.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel
|
||||||
|
{
|
||||||
|
public class PluginViewModel
|
||||||
|
{
|
||||||
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
||||||
|
public string Name { get; }
|
||||||
|
public string Description { get; }
|
||||||
|
public string Filename { get; }
|
||||||
|
public string Author { get; }
|
||||||
|
public string Url { get; }
|
||||||
|
|
||||||
|
public Visibility DescriptionVisibility => string.IsNullOrEmpty(Description) ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
public Visibility AuthorVisibility => string.IsNullOrEmpty(Author) ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
public Visibility UrlVisibility => string.IsNullOrEmpty(Url) ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
|
public PluginViewModel(string name, string description, string filename, string author, string url)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Description = description;
|
||||||
|
Filename = filename;
|
||||||
|
Author = author;
|
||||||
|
Url = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Windows;
|
||||||
|
using MassiveKnob.Core;
|
||||||
|
using MassiveKnob.Plugin;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class BaseSettingsInputOutputViewModel : IDisposable, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private readonly IMassiveKnobOrchestrator orchestrator;
|
||||||
|
|
||||||
|
private readonly MassiveKnobActionType inputOutputType;
|
||||||
|
private DeviceSpecs? specs;
|
||||||
|
private readonly IDisposable activeDeviceSubscription;
|
||||||
|
private IEnumerable<InputOutputViewModel> inputOutputs;
|
||||||
|
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
||||||
|
public IList<ActionViewModel> Actions { get; }
|
||||||
|
|
||||||
|
public DeviceSpecs? Specs
|
||||||
|
{
|
||||||
|
get => specs;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
specs = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
|
||||||
|
DisposeInputOutputViewModels();
|
||||||
|
int inputOutputCount;
|
||||||
|
|
||||||
|
switch (inputOutputType)
|
||||||
|
{
|
||||||
|
case MassiveKnobActionType.InputAnalog:
|
||||||
|
inputOutputCount = specs?.AnalogInputCount ?? 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MassiveKnobActionType.InputDigital:
|
||||||
|
inputOutputCount = specs?.DigitalInputCount ?? 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MassiveKnobActionType.OutputAnalog:
|
||||||
|
inputOutputCount = specs?.AnalogOutputCount ?? 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MassiveKnobActionType.OutputDigital:
|
||||||
|
inputOutputCount = specs?.DigitalOutputCount ?? 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
InputOutputs = Enumerable
|
||||||
|
.Range(0, inputOutputCount)
|
||||||
|
.Select(i => new InputOutputViewModel(Actions, orchestrator, inputOutputType, i))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<InputOutputViewModel> InputOutputs
|
||||||
|
{
|
||||||
|
get => inputOutputs;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
inputOutputs = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
|
public BaseSettingsInputOutputViewModel(IPluginManager pluginManager, IMassiveKnobOrchestrator orchestrator, MassiveKnobActionType inputOutputType)
|
||||||
|
{
|
||||||
|
this.orchestrator = orchestrator;
|
||||||
|
this.inputOutputType = inputOutputType;
|
||||||
|
|
||||||
|
// For design-time support
|
||||||
|
if (orchestrator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
var allActions = new List<ActionViewModel>
|
||||||
|
{
|
||||||
|
new ActionViewModel(null, null)
|
||||||
|
};
|
||||||
|
|
||||||
|
allActions.AddRange(
|
||||||
|
pluginManager.GetActionPlugins()
|
||||||
|
.SelectMany(ap => ap.Actions.Select(a => new ActionViewModel(ap, a)))
|
||||||
|
.OrderBy(a => a.Name.ToLower()));
|
||||||
|
|
||||||
|
Actions = allActions;
|
||||||
|
|
||||||
|
|
||||||
|
activeDeviceSubscription = orchestrator.ActiveDeviceSubject.Subscribe(info =>
|
||||||
|
{
|
||||||
|
Application.Current?.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
Specs = info.Specs;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (orchestrator.ActiveDevice != null)
|
||||||
|
Specs = orchestrator.ActiveDevice.Specs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
DisposeInputOutputViewModels();
|
||||||
|
activeDeviceSubscription?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void DisposeInputOutputViewModels()
|
||||||
|
{
|
||||||
|
if (inputOutputs == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var viewModel in inputOutputs)
|
||||||
|
viewModel.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class BaseSettingsInputOutputViewModelDesignTime : BaseSettingsInputOutputViewModel
|
||||||
|
{
|
||||||
|
public BaseSettingsInputOutputViewModelDesignTime()
|
||||||
|
: base(null, null, MassiveKnobActionType.InputAnalog)
|
||||||
|
{
|
||||||
|
Specs = new DeviceSpecs(2, 2, 2, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using MassiveKnob.Core;
|
||||||
|
using MassiveKnob.Plugin;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class SettingsAnalogInputsViewModel : BaseSettingsInputOutputViewModel
|
||||||
|
{
|
||||||
|
public SettingsAnalogInputsViewModel(IPluginManager pluginManager, IMassiveKnobOrchestrator orchestrator)
|
||||||
|
: base(pluginManager, orchestrator, MassiveKnobActionType.InputAnalog)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using MassiveKnob.Core;
|
||||||
|
using MassiveKnob.Plugin;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class SettingsAnalogOutputsViewModel : BaseSettingsInputOutputViewModel
|
||||||
|
{
|
||||||
|
public SettingsAnalogOutputsViewModel(IPluginManager pluginManager, IMassiveKnobOrchestrator orchestrator)
|
||||||
|
: base(pluginManager, orchestrator, MassiveKnobActionType.OutputAnalog)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,165 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using MassiveKnob.Core;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class SettingsDeviceViewModel : IDisposable, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private readonly IMassiveKnobOrchestrator orchestrator;
|
||||||
|
private DeviceViewModel selectedDevice;
|
||||||
|
private UserControl settingsControl;
|
||||||
|
|
||||||
|
private readonly IDisposable deviceStatusSubscription;
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
||||||
|
public IList<DeviceViewModel> Devices { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public DeviceViewModel SelectedDevice
|
||||||
|
{
|
||||||
|
get => selectedDevice;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == selectedDevice)
|
||||||
|
return;
|
||||||
|
|
||||||
|
selectedDevice = value;
|
||||||
|
var deviceInfo = orchestrator?.SetActiveDevice(value?.Device);
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
|
||||||
|
SettingsControl = deviceInfo?.Instance.CreateSettingsControl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserControl SettingsControl
|
||||||
|
{
|
||||||
|
get => settingsControl;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == settingsControl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (settingsControl is IDisposable disposable)
|
||||||
|
disposable.Dispose();
|
||||||
|
|
||||||
|
settingsControl = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string ConnectionStatusText
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (orchestrator == null)
|
||||||
|
return "Design-time";
|
||||||
|
|
||||||
|
switch (orchestrator.DeviceStatus)
|
||||||
|
{
|
||||||
|
case MassiveKnobDeviceStatus.Disconnected:
|
||||||
|
return Strings.DeviceStatusDisconnected;
|
||||||
|
|
||||||
|
case MassiveKnobDeviceStatus.Connecting:
|
||||||
|
return Strings.DeviceStatusConnecting;
|
||||||
|
|
||||||
|
case MassiveKnobDeviceStatus.Connected:
|
||||||
|
return Strings.DeviceStatusConnected;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Brush ConnectionStatusColor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (orchestrator == null)
|
||||||
|
return Brushes.Fuchsia;
|
||||||
|
|
||||||
|
switch (orchestrator.DeviceStatus)
|
||||||
|
{
|
||||||
|
case MassiveKnobDeviceStatus.Disconnected:
|
||||||
|
return Brushes.DarkRed;
|
||||||
|
|
||||||
|
case MassiveKnobDeviceStatus.Connecting:
|
||||||
|
return Brushes.Orange;
|
||||||
|
|
||||||
|
case MassiveKnobDeviceStatus.Connected:
|
||||||
|
return Brushes.ForestGreen;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
|
public SettingsDeviceViewModel(IPluginManager pluginManager, IMassiveKnobOrchestrator orchestrator)
|
||||||
|
{
|
||||||
|
this.orchestrator = orchestrator;
|
||||||
|
|
||||||
|
// For design-time support
|
||||||
|
if (orchestrator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
deviceStatusSubscription = orchestrator.DeviceStatusSubject.Subscribe(status =>
|
||||||
|
{
|
||||||
|
OnDependantPropertyChanged(nameof(ConnectionStatusColor));
|
||||||
|
OnDependantPropertyChanged(nameof(ConnectionStatusText));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Devices = pluginManager.GetDevicePlugins()
|
||||||
|
.SelectMany(dp => dp.Devices.Select(d => new DeviceViewModel(dp, d)))
|
||||||
|
.OrderBy(d => d.Name.ToLower())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (orchestrator.ActiveDevice == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
selectedDevice = Devices.Single(d => d.Device.DeviceId == orchestrator.ActiveDevice.Info.DeviceId);
|
||||||
|
SettingsControl = orchestrator.ActiveDevice.Instance.CreateSettingsControl();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (SettingsControl is IDisposable disposable)
|
||||||
|
disposable.Dispose();
|
||||||
|
|
||||||
|
deviceStatusSubscription?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnDependantPropertyChanged(string propertyName)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class SettingsDeviceViewModelDesignTime : SettingsDeviceViewModel
|
||||||
|
{
|
||||||
|
public SettingsDeviceViewModelDesignTime() : base(null, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using MassiveKnob.Core;
|
||||||
|
using MassiveKnob.Plugin;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class SettingsDigitalInputsViewModel : BaseSettingsInputOutputViewModel
|
||||||
|
{
|
||||||
|
public SettingsDigitalInputsViewModel(IPluginManager pluginManager, IMassiveKnobOrchestrator orchestrator)
|
||||||
|
: base(pluginManager, orchestrator, MassiveKnobActionType.InputDigital)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using MassiveKnob.Core;
|
||||||
|
using MassiveKnob.Plugin;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class SettingsDigitalOutputsViewModel : BaseSettingsInputOutputViewModel
|
||||||
|
{
|
||||||
|
public SettingsDigitalOutputsViewModel(IPluginManager pluginManager, IMassiveKnobOrchestrator orchestrator)
|
||||||
|
: base(pluginManager, orchestrator, MassiveKnobActionType.OutputDigital)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using MassiveKnob.Core;
|
||||||
|
using MassiveKnob.Settings;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class SettingsLoggingViewModel : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private readonly IMassiveKnobOrchestrator orchestrator;
|
||||||
|
private readonly ILoggingSwitch loggingSwitch;
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
||||||
|
public IList<LoggingLevelViewModel> LoggingLevels { get; }
|
||||||
|
|
||||||
|
private LoggingLevelViewModel selectedLoggingLevel;
|
||||||
|
public LoggingLevelViewModel SelectedLoggingLevel
|
||||||
|
{
|
||||||
|
get => selectedLoggingLevel;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == selectedLoggingLevel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
selectedLoggingLevel = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
|
||||||
|
ApplyLoggingSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool loggingEnabled;
|
||||||
|
public bool LoggingEnabled
|
||||||
|
{
|
||||||
|
get => loggingEnabled;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == loggingEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
loggingEnabled = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
|
||||||
|
ApplyLoggingSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO (code quality) do not hardcode path here
|
||||||
|
public string LoggingOutputPath { get; } = string.Format(Strings.LoggingOutputPath,
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"MassiveKnob",
|
||||||
|
@"Logs"));
|
||||||
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
|
public SettingsLoggingViewModel(IMassiveKnobOrchestrator orchestrator, ILoggingSwitch loggingSwitch)
|
||||||
|
{
|
||||||
|
this.orchestrator = orchestrator;
|
||||||
|
this.loggingSwitch = loggingSwitch;
|
||||||
|
|
||||||
|
// For design-time support
|
||||||
|
if (orchestrator == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
var logSettings = orchestrator.GetSettings().Log;
|
||||||
|
LoggingLevels = new List<LoggingLevelViewModel>
|
||||||
|
{
|
||||||
|
new LoggingLevelViewModel(LogEventLevel.Error, Strings.LoggingLevelError, Strings.LoggingLevelErrorDescription),
|
||||||
|
new LoggingLevelViewModel(LogEventLevel.Warning, Strings.LoggingLevelWarning, Strings.LoggingLevelWarningDescription),
|
||||||
|
new LoggingLevelViewModel(LogEventLevel.Information, Strings.LoggingLevelInformation, Strings.LoggingLevelInformationDescription),
|
||||||
|
new LoggingLevelViewModel(LogEventLevel.Verbose, Strings.LoggingLevelVerbose, Strings.LoggingLevelVerboseDescription)
|
||||||
|
};
|
||||||
|
|
||||||
|
selectedLoggingLevel = LoggingLevels.SingleOrDefault(l => l.Level == logSettings.Level)
|
||||||
|
?? LoggingLevels.Single(l => l.Level == LogEventLevel.Information);
|
||||||
|
loggingEnabled = logSettings.Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void ApplyLoggingSettings()
|
||||||
|
{
|
||||||
|
orchestrator?.UpdateSettings(settings =>
|
||||||
|
{
|
||||||
|
settings.Log.Enabled = LoggingEnabled;
|
||||||
|
settings.Log.Level = SelectedLoggingLevel.Level;
|
||||||
|
});
|
||||||
|
|
||||||
|
loggingSwitch?.SetLogging(LoggingEnabled, selectedLoggingLevel.Level);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using MassiveKnob.Core;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class SettingsPluginsViewModel
|
||||||
|
{
|
||||||
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
||||||
|
public IEnumerable<PluginViewModel> Plugins { get; protected set; }
|
||||||
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
|
public SettingsPluginsViewModel(IPluginManager pluginManager)
|
||||||
|
{
|
||||||
|
// Design-time support
|
||||||
|
if (pluginManager == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Plugins = pluginManager.GetPlugins()
|
||||||
|
.Select(p => new PluginViewModel(p.Plugin.Name, p.Plugin.Description, p.Filename, p.Plugin.Author, p.Plugin.Url))
|
||||||
|
.OrderBy(p => p.Name, StringComparer.CurrentCultureIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class SettingsPluginsViewModelDesignTime : SettingsPluginsViewModel
|
||||||
|
{
|
||||||
|
public SettingsPluginsViewModelDesignTime()
|
||||||
|
: base(null)
|
||||||
|
{
|
||||||
|
Plugins = new[]
|
||||||
|
{
|
||||||
|
new PluginViewModel("Plugin without description", null, "D:\\Does\\Not\\Exist.dll", "Some Massive Knob <massive@knob.org>", "https://lmgtfy.app/?q=Massive+Knob"),
|
||||||
|
new PluginViewModel("Design-time plugin", "Fake plugin only visible at design-time.", "C:\\Does\\Not\\Exist.dll", null, null)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace MassiveKnob.ViewModel.Settings
|
||||||
|
{
|
||||||
|
public class SettingsStartupViewModel : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public const string RunKey = @"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
|
||||||
|
public const string RunValue = @"MassiveKnob";
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
||||||
|
private bool runAtStartup;
|
||||||
|
public bool RunAtStartup
|
||||||
|
{
|
||||||
|
get => runAtStartup;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == runAtStartup)
|
||||||
|
return;
|
||||||
|
|
||||||
|
runAtStartup = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
|
||||||
|
ApplyRunAtStartup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
|
public SettingsStartupViewModel()
|
||||||
|
{
|
||||||
|
var runKey = Registry.CurrentUser.OpenSubKey(RunKey, false);
|
||||||
|
runAtStartup = runKey?.GetValue(RunValue) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void ApplyRunAtStartup()
|
||||||
|
{
|
||||||
|
var runKey = Registry.CurrentUser.OpenSubKey(RunKey, true);
|
||||||
|
Debug.Assert(runKey != null, nameof(runKey) + " != null");
|
||||||
|
|
||||||
|
if (RunAtStartup)
|
||||||
|
{
|
||||||
|
var entryAssembly = Assembly.GetEntryAssembly();
|
||||||
|
Debug.Assert(entryAssembly != null, nameof(entryAssembly) + " != null");
|
||||||
|
|
||||||
|
runKey.SetValue(RunValue, new Uri(entryAssembly.CodeBase).LocalPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
runKey.DeleteValue(RunValue, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,55 +1,39 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
|
||||||
using MassiveKnob.Core;
|
using MassiveKnob.Core;
|
||||||
using MassiveKnob.Plugin;
|
using MassiveKnob.Plugin;
|
||||||
using MassiveKnob.Settings;
|
using MassiveKnob.Settings;
|
||||||
using MassiveKnob.View.Settings;
|
using MassiveKnob.View.Settings;
|
||||||
using Microsoft.Win32;
|
|
||||||
using Serilog.Events;
|
|
||||||
|
|
||||||
namespace MassiveKnob.ViewModel
|
namespace MassiveKnob.ViewModel
|
||||||
{
|
{
|
||||||
// TODO (code quality) split ViewModel for individual views, create viewmodel using container
|
|
||||||
// TODO (nice to have) installed plugins list
|
|
||||||
public class SettingsViewModel : IDisposable, INotifyPropertyChanged
|
public class SettingsViewModel : IDisposable, INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
private readonly Dictionary<SettingsMenuItem, Type> menuItemControls = new Dictionary<SettingsMenuItem, Type>
|
private readonly Dictionary<SettingsMenuItem, Type> menuItemControls = new Dictionary<SettingsMenuItem, Type>
|
||||||
{
|
{
|
||||||
{ SettingsMenuItem.Device, typeof(DeviceView) },
|
{ SettingsMenuItem.Device, typeof(SettingsDeviceView) },
|
||||||
{ SettingsMenuItem.AnalogInputs, typeof(AnalogInputsView) },
|
{ SettingsMenuItem.AnalogInputs, typeof(SettingsAnalogInputsView) },
|
||||||
{ SettingsMenuItem.DigitalInputs, typeof(DigitalInputsView) },
|
{ SettingsMenuItem.DigitalInputs, typeof(SettingsDigitalInputsView) },
|
||||||
{ SettingsMenuItem.AnalogOutputs, typeof(AnalogOutputsView) },
|
{ SettingsMenuItem.AnalogOutputs, typeof(SettingsAnalogOutputsView) },
|
||||||
{ SettingsMenuItem.DigitalOutputs, typeof(DigitalOutputsView) },
|
{ SettingsMenuItem.DigitalOutputs, typeof(SettingsDigitalOutputsView) },
|
||||||
{ SettingsMenuItem.Logging, typeof(LoggingView) },
|
{ SettingsMenuItem.Logging, typeof(SettingsLoggingView) },
|
||||||
{ SettingsMenuItem.Startup, typeof(StartupView) }
|
{ SettingsMenuItem.Startup, typeof(SettingsStartupView) },
|
||||||
|
{ SettingsMenuItem.Plugins, typeof(SettingsPluginsView) }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private readonly SimpleInjector.Container container;
|
||||||
private readonly IMassiveKnobOrchestrator orchestrator;
|
private readonly IMassiveKnobOrchestrator orchestrator;
|
||||||
private readonly ILoggingSwitch loggingSwitch;
|
|
||||||
private DeviceViewModel selectedDevice;
|
|
||||||
private UserControl selectedView;
|
private UserControl selectedView;
|
||||||
private SettingsMenuItem selectedMenuItem;
|
private SettingsMenuItem selectedMenuItem;
|
||||||
private UserControl settingsControl;
|
|
||||||
|
|
||||||
private DeviceSpecs? specs;
|
private DeviceSpecs? specs;
|
||||||
private IEnumerable<InputOutputViewModel> analogInputs;
|
|
||||||
private IEnumerable<InputOutputViewModel> digitalInputs;
|
|
||||||
private IEnumerable<InputOutputViewModel> analogOutputs;
|
|
||||||
private IEnumerable<InputOutputViewModel> digitalOutputs;
|
|
||||||
|
|
||||||
private readonly IDisposable activeDeviceSubscription;
|
private readonly IDisposable activeDeviceSubscription;
|
||||||
private readonly IDisposable deviceStatusSubscription;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
||||||
public SettingsMenuItem SelectedMenuItem
|
public SettingsMenuItem SelectedMenuItem
|
||||||
@ -64,7 +48,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
|
|
||||||
if (menuItemControls.TryGetValue(selectedMenuItem, out var viewType))
|
if (menuItemControls.TryGetValue(selectedMenuItem, out var viewType))
|
||||||
SelectedView = (UserControl) Activator.CreateInstance(viewType);
|
SelectedView = (UserControl)container?.GetInstance(viewType);
|
||||||
|
|
||||||
orchestrator?.UpdateSettings(settings =>
|
orchestrator?.UpdateSettings(settings =>
|
||||||
{
|
{
|
||||||
@ -88,42 +72,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public IList<DeviceViewModel> Devices { get; }
|
//public IList<ActionViewModel> Actions { get; }
|
||||||
public IList<ActionViewModel> Actions { get; }
|
|
||||||
|
|
||||||
|
|
||||||
public DeviceViewModel SelectedDevice
|
|
||||||
{
|
|
||||||
get => selectedDevice;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == selectedDevice)
|
|
||||||
return;
|
|
||||||
|
|
||||||
selectedDevice = value;
|
|
||||||
var deviceInfo = orchestrator?.SetActiveDevice(value?.Device);
|
|
||||||
|
|
||||||
OnPropertyChanged();
|
|
||||||
|
|
||||||
SettingsControl = deviceInfo?.Instance.CreateSettingsControl();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserControl SettingsControl
|
|
||||||
{
|
|
||||||
get => settingsControl;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == settingsControl)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (settingsControl is IDisposable disposable)
|
|
||||||
disposable.Dispose();
|
|
||||||
|
|
||||||
settingsControl = value;
|
|
||||||
OnPropertyChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceSpecs? Specs
|
public DeviceSpecs? Specs
|
||||||
{
|
{
|
||||||
@ -136,7 +85,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
OnDependantPropertyChanged("DigitalInputVisibility");
|
OnDependantPropertyChanged("DigitalInputVisibility");
|
||||||
OnDependantPropertyChanged("AnalogOutputVisibility");
|
OnDependantPropertyChanged("AnalogOutputVisibility");
|
||||||
OnDependantPropertyChanged("DigitalOutputVisibility");
|
OnDependantPropertyChanged("DigitalOutputVisibility");
|
||||||
|
/*
|
||||||
DisposeInputOutputViewModels(AnalogInputs);
|
DisposeInputOutputViewModels(AnalogInputs);
|
||||||
DisposeInputOutputViewModels(DigitalInputs);
|
DisposeInputOutputViewModels(DigitalInputs);
|
||||||
DisposeInputOutputViewModels(AnalogOutputs);
|
DisposeInputOutputViewModels(AnalogOutputs);
|
||||||
@ -161,6 +110,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
.Range(0, specs?.DigitalOutputCount ?? 0)
|
.Range(0, specs?.DigitalOutputCount ?? 0)
|
||||||
.Select(i => new InputOutputViewModel(this, orchestrator, MassiveKnobActionType.OutputDigital, i))
|
.Select(i => new InputOutputViewModel(this, orchestrator, MassiveKnobActionType.OutputDigital, i))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +119,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
? Visibility.Visible
|
? Visibility.Visible
|
||||||
: Visibility.Collapsed;
|
: Visibility.Collapsed;
|
||||||
|
|
||||||
|
/*
|
||||||
public IEnumerable<InputOutputViewModel> AnalogInputs
|
public IEnumerable<InputOutputViewModel> AnalogInputs
|
||||||
{
|
{
|
||||||
get => analogInputs;
|
get => analogInputs;
|
||||||
@ -178,11 +129,13 @@ namespace MassiveKnob.ViewModel
|
|||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public Visibility DigitalInputVisibility => specs.HasValue && specs.Value.DigitalInputCount > 0
|
public Visibility DigitalInputVisibility => specs.HasValue && specs.Value.DigitalInputCount > 0
|
||||||
? Visibility.Visible
|
? Visibility.Visible
|
||||||
: Visibility.Collapsed;
|
: Visibility.Collapsed;
|
||||||
|
|
||||||
|
/*
|
||||||
public IEnumerable<InputOutputViewModel> DigitalInputs
|
public IEnumerable<InputOutputViewModel> DigitalInputs
|
||||||
{
|
{
|
||||||
get => digitalInputs;
|
get => digitalInputs;
|
||||||
@ -192,11 +145,13 @@ namespace MassiveKnob.ViewModel
|
|||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public Visibility AnalogOutputVisibility => specs.HasValue && specs.Value.AnalogOutputCount > 0
|
public Visibility AnalogOutputVisibility => specs.HasValue && specs.Value.AnalogOutputCount > 0
|
||||||
? Visibility.Visible
|
? Visibility.Visible
|
||||||
: Visibility.Collapsed;
|
: Visibility.Collapsed;
|
||||||
|
|
||||||
|
/*
|
||||||
public IEnumerable<InputOutputViewModel> AnalogOutputs
|
public IEnumerable<InputOutputViewModel> AnalogOutputs
|
||||||
{
|
{
|
||||||
get => analogOutputs;
|
get => analogOutputs;
|
||||||
@ -206,11 +161,13 @@ namespace MassiveKnob.ViewModel
|
|||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public Visibility DigitalOutputVisibility => specs.HasValue && specs.Value.DigitalOutputCount > 0
|
public Visibility DigitalOutputVisibility => specs.HasValue && specs.Value.DigitalOutputCount > 0
|
||||||
? Visibility.Visible
|
? Visibility.Visible
|
||||||
: Visibility.Collapsed;
|
: Visibility.Collapsed;
|
||||||
|
|
||||||
|
/*
|
||||||
public IEnumerable<InputOutputViewModel> DigitalOutputs
|
public IEnumerable<InputOutputViewModel> DigitalOutputs
|
||||||
{
|
{
|
||||||
get => digitalOutputs;
|
get => digitalOutputs;
|
||||||
@ -221,7 +178,6 @@ namespace MassiveKnob.ViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public IList<LoggingLevelViewModel> LoggingLevels { get; }
|
public IList<LoggingLevelViewModel> LoggingLevels { get; }
|
||||||
|
|
||||||
private LoggingLevelViewModel selectedLoggingLevel;
|
private LoggingLevelViewModel selectedLoggingLevel;
|
||||||
@ -281,62 +237,15 @@ namespace MassiveKnob.ViewModel
|
|||||||
ApplyRunAtStartup();
|
ApplyRunAtStartup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public string ConnectionStatusText
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (orchestrator == null)
|
|
||||||
return "Design-time";
|
|
||||||
|
|
||||||
switch (orchestrator.DeviceStatus)
|
|
||||||
{
|
|
||||||
case MassiveKnobDeviceStatus.Disconnected:
|
|
||||||
return Strings.DeviceStatusDisconnected;
|
|
||||||
|
|
||||||
case MassiveKnobDeviceStatus.Connecting:
|
|
||||||
return Strings.DeviceStatusConnecting;
|
|
||||||
|
|
||||||
case MassiveKnobDeviceStatus.Connected:
|
|
||||||
return Strings.DeviceStatusConnected;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Brush ConnectionStatusColor
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (orchestrator == null)
|
|
||||||
return Brushes.Fuchsia;
|
|
||||||
|
|
||||||
switch (orchestrator.DeviceStatus)
|
|
||||||
{
|
|
||||||
case MassiveKnobDeviceStatus.Disconnected:
|
|
||||||
return Brushes.DarkRed;
|
|
||||||
|
|
||||||
case MassiveKnobDeviceStatus.Connecting:
|
|
||||||
return Brushes.Orange;
|
|
||||||
|
|
||||||
case MassiveKnobDeviceStatus.Connected:
|
|
||||||
return Brushes.ForestGreen;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ReSharper restore UnusedMember.Global
|
// ReSharper restore UnusedMember.Global
|
||||||
|
|
||||||
|
|
||||||
public SettingsViewModel(IPluginManager pluginManager, IMassiveKnobOrchestrator orchestrator, ILoggingSwitch loggingSwitch)
|
public SettingsViewModel(SimpleInjector.Container container, /*IPluginManager pluginManager, */IMassiveKnobOrchestrator orchestrator/*, ILoggingSwitch loggingSwitch*/)
|
||||||
{
|
{
|
||||||
|
this.container = container;
|
||||||
this.orchestrator = orchestrator;
|
this.orchestrator = orchestrator;
|
||||||
this.loggingSwitch = loggingSwitch;
|
//this.loggingSwitch = loggingSwitch;
|
||||||
|
|
||||||
// For design-time support
|
// For design-time support
|
||||||
if (orchestrator == null)
|
if (orchestrator == null)
|
||||||
@ -348,6 +257,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
|
|
||||||
SelectedMenuItem = activeMenuItem;
|
SelectedMenuItem = activeMenuItem;
|
||||||
|
|
||||||
|
|
||||||
activeDeviceSubscription = orchestrator.ActiveDeviceSubject.Subscribe(info =>
|
activeDeviceSubscription = orchestrator.ActiveDeviceSubject.Subscribe(info =>
|
||||||
{
|
{
|
||||||
Application.Current?.Dispatcher.Invoke(() =>
|
Application.Current?.Dispatcher.Invoke(() =>
|
||||||
@ -355,18 +265,12 @@ namespace MassiveKnob.ViewModel
|
|||||||
Specs = info.Specs;
|
Specs = info.Specs;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
deviceStatusSubscription = orchestrator.DeviceStatusSubject.Subscribe(status =>
|
|
||||||
{
|
if (orchestrator.ActiveDevice != null)
|
||||||
OnDependantPropertyChanged(nameof(ConnectionStatusColor));
|
Specs = orchestrator.ActiveDevice.Specs;
|
||||||
OnDependantPropertyChanged(nameof(ConnectionStatusText));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Devices = pluginManager.GetDevicePlugins()
|
/*
|
||||||
.SelectMany(dp => dp.Devices.Select(d => new DeviceViewModel(dp, d)))
|
|
||||||
.OrderBy(d => d.Name.ToLower())
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var allActions = new List<ActionViewModel>
|
var allActions = new List<ActionViewModel>
|
||||||
{
|
{
|
||||||
new ActionViewModel(null, null)
|
new ActionViewModel(null, null)
|
||||||
@ -379,12 +283,6 @@ namespace MassiveKnob.ViewModel
|
|||||||
|
|
||||||
Actions = allActions;
|
Actions = allActions;
|
||||||
|
|
||||||
if (orchestrator.ActiveDevice != null)
|
|
||||||
{
|
|
||||||
selectedDevice = Devices.Single(d => d.Device.DeviceId == orchestrator.ActiveDevice.Info.DeviceId);
|
|
||||||
SettingsControl = orchestrator.ActiveDevice.Instance.CreateSettingsControl();
|
|
||||||
Specs = orchestrator.ActiveDevice.Specs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var logSettings = orchestrator.GetSettings().Log;
|
var logSettings = orchestrator.GetSettings().Log;
|
||||||
@ -403,24 +301,23 @@ namespace MassiveKnob.ViewModel
|
|||||||
|
|
||||||
var runKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", false);
|
var runKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", false);
|
||||||
runAtStartup = runKey?.GetValue("MassiveKnob") != null;
|
runAtStartup = runKey?.GetValue("MassiveKnob") != null;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (SettingsControl is IDisposable disposable)
|
/*
|
||||||
disposable.Dispose();
|
|
||||||
|
|
||||||
DisposeInputOutputViewModels(AnalogInputs);
|
DisposeInputOutputViewModels(AnalogInputs);
|
||||||
DisposeInputOutputViewModels(DigitalInputs);
|
DisposeInputOutputViewModels(DigitalInputs);
|
||||||
DisposeInputOutputViewModels(AnalogOutputs);
|
DisposeInputOutputViewModels(AnalogOutputs);
|
||||||
DisposeInputOutputViewModels(DigitalOutputs);
|
DisposeInputOutputViewModels(DigitalOutputs);
|
||||||
|
*/
|
||||||
|
|
||||||
activeDeviceSubscription?.Dispose();
|
activeDeviceSubscription?.Dispose();
|
||||||
deviceStatusSubscription?.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
private void ApplyLoggingSettings()
|
private void ApplyLoggingSettings()
|
||||||
{
|
{
|
||||||
orchestrator?.UpdateSettings(settings =>
|
orchestrator?.UpdateSettings(settings =>
|
||||||
@ -460,6 +357,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
foreach (var viewModel in viewModels)
|
foreach (var viewModel in viewModels)
|
||||||
viewModel.Dispose();
|
viewModel.Dispose();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
@ -478,7 +376,7 @@ namespace MassiveKnob.ViewModel
|
|||||||
|
|
||||||
public class SettingsViewModelDesignTime : SettingsViewModel
|
public class SettingsViewModelDesignTime : SettingsViewModel
|
||||||
{
|
{
|
||||||
public SettingsViewModelDesignTime() : base(null, null, null)
|
public SettingsViewModelDesignTime() : base(null, null)
|
||||||
{
|
{
|
||||||
Specs = new DeviceSpecs(2, 2, 2, 2);
|
Specs = new DeviceSpecs(2, 2, 2, 2);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ Name: essentialplugins; Description: "Essential plugins"; Types: full custom
|
|||||||
Name: essentialplugins\serialdevice; Description: "Serial device"; Types: full custom
|
Name: essentialplugins\serialdevice; Description: "Serial device"; Types: full custom
|
||||||
Name: essentialplugins\coreaudio; Description: "Windows Core Audio actions"; Types: full custom
|
Name: essentialplugins\coreaudio; Description: "Windows Core Audio actions"; Types: full custom
|
||||||
Name: optionalplugins; Description: "Optional plugins"; Types: full custom
|
Name: optionalplugins; Description: "Optional plugins"; Types: full custom
|
||||||
|
Name: optionalplugins\runprogram; Description: "Run program"; Types: full custom
|
||||||
Name: optionalplugins\emulatordevice; Description: "Emulator device"; Types: full custom
|
Name: optionalplugins\emulatordevice; Description: "Emulator device"; Types: full custom
|
||||||
Name: optionalplugins\voicemeeter; Description: "VoiceMeeter actions"; Types: full custom
|
Name: optionalplugins\voicemeeter; Description: "VoiceMeeter actions"; Types: full custom
|
||||||
|
|
||||||
@ -65,6 +66,10 @@ Source: {#BasePath}\MassiveKnob.Plugin.EmulatorDevice\bin\Release\*.dll; DestDir
|
|||||||
Source: {#BasePath}\MassiveKnob.Plugin.VoiceMeeter\bin\Release\MassiveKnobPlugin.json; DestDir: "{app}\Plugins\VoiceMeeter"; Flags: ignoreversion; Components: optionalplugins\voicemeeter
|
Source: {#BasePath}\MassiveKnob.Plugin.VoiceMeeter\bin\Release\MassiveKnobPlugin.json; DestDir: "{app}\Plugins\VoiceMeeter"; Flags: ignoreversion; Components: optionalplugins\voicemeeter
|
||||||
Source: {#BasePath}\MassiveKnob.Plugin.VoiceMeeter\bin\Release\*.dll; DestDir: "{app}\Plugins\VoiceMeeter"; Flags: ignoreversion; Components: optionalplugins\voicemeeter
|
Source: {#BasePath}\MassiveKnob.Plugin.VoiceMeeter\bin\Release\*.dll; DestDir: "{app}\Plugins\VoiceMeeter"; Flags: ignoreversion; Components: optionalplugins\voicemeeter
|
||||||
|
|
||||||
|
; Run Program plugin
|
||||||
|
Source: {#BasePath}\MassiveKnob.Plugin.RunProgram\bin\Release\MassiveKnobPlugin.json; DestDir: "{app}\Plugins\RunProgram"; Flags: ignoreversion; Components: optionalplugins\runprogram
|
||||||
|
Source: {#BasePath}\MassiveKnob.Plugin.RunProgram\bin\Release\*.dll; DestDir: "{app}\Plugins\RunProgram"; Flags: ignoreversion; Components: optionalplugins\runprogram
|
||||||
|
|
||||||
[Dirs]
|
[Dirs]
|
||||||
Name: "{localappdata}\MassiveKnob"
|
Name: "{localappdata}\MassiveKnob"
|
||||||
Name: "{localappdata}\MassiveKnob\Logs"
|
Name: "{localappdata}\MassiveKnob\Logs"
|
||||||
|
Loading…
Reference in New Issue
Block a user