217 lines
7.1 KiB
C#
217 lines
7.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Reactive.Linq;
|
|
using System.Reactive.Subjects;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using MassiveKnob.Core;
|
|
using MassiveKnob.Plugin;
|
|
|
|
namespace MassiveKnob.ViewModel
|
|
{
|
|
public class InputOutputViewModel : IDisposable, INotifyPropertyChanged
|
|
{
|
|
private readonly IMassiveKnobOrchestrator orchestrator;
|
|
private readonly MassiveKnobActionType actionType;
|
|
private readonly int index;
|
|
|
|
private ActionViewModel selectedAction;
|
|
private UserControl actionSettingsControl;
|
|
|
|
|
|
// ReSharper disable UnusedMember.Global - used by WPF Binding
|
|
public string DisplayName => string.Format(
|
|
actionType == MassiveKnobActionType.OutputAnalog || actionType == MassiveKnobActionType.OutputDigital
|
|
? Strings.OutputHeader
|
|
: Strings.InputHeader,
|
|
index + 1);
|
|
|
|
public IList<ActionViewModel> Actions { get; }
|
|
|
|
|
|
public ActionViewModel SelectedAction
|
|
{
|
|
get => selectedAction;
|
|
set
|
|
{
|
|
if (value == selectedAction)
|
|
return;
|
|
|
|
selectedAction = value == null || value.RepresentsNull ? null : value;
|
|
var actionInfo = orchestrator.SetAction(actionType, index, selectedAction?.Action);
|
|
|
|
OnPropertyChanged();
|
|
OnDependantPropertyChanged(nameof(DigitalToAnalogVisibility));
|
|
|
|
ActionSettingsControl = actionInfo?.Instance.CreateSettingsControl();
|
|
}
|
|
}
|
|
|
|
public UserControl ActionSettingsControl
|
|
{
|
|
get => actionSettingsControl;
|
|
set
|
|
{
|
|
if (value == actionSettingsControl)
|
|
return;
|
|
|
|
if (actionSettingsControl is IDisposable disposable)
|
|
disposable.Dispose();
|
|
|
|
actionSettingsControl = value;
|
|
OnPropertyChanged();
|
|
}
|
|
}
|
|
|
|
public Visibility DigitalToAnalogVisibility
|
|
{
|
|
get
|
|
{
|
|
// Design-time support
|
|
if (orchestrator == null)
|
|
return Visibility.Visible;
|
|
|
|
if (actionType != MassiveKnobActionType.OutputAnalog)
|
|
return Visibility.Collapsed;
|
|
|
|
if (SelectedAction == null || SelectedAction.RepresentsNull)
|
|
return Visibility.Collapsed;
|
|
|
|
return SelectedAction.Action.ActionType == MassiveKnobActionType.OutputDigital
|
|
? Visibility.Visible
|
|
: Visibility.Collapsed;
|
|
}
|
|
}
|
|
|
|
|
|
private readonly Subject<bool> throttledDigitalToAnalogChanged = new Subject<bool>();
|
|
private readonly IDisposable digitalToAnalogChangedSubscription;
|
|
|
|
private byte digitalToAnalogOn;
|
|
public byte DigitalToAnalogOn
|
|
{
|
|
get => digitalToAnalogOn;
|
|
set
|
|
{
|
|
if (actionType != MassiveKnobActionType.OutputAnalog || value == digitalToAnalogOn)
|
|
return;
|
|
|
|
digitalToAnalogOn = value;
|
|
OnPropertyChanged();
|
|
throttledDigitalToAnalogChanged.OnNext(true);
|
|
}
|
|
}
|
|
|
|
|
|
private byte digitalToAnalogOff;
|
|
public byte DigitalToAnalogOff
|
|
{
|
|
get => digitalToAnalogOff;
|
|
set
|
|
{
|
|
if (actionType != MassiveKnobActionType.OutputAnalog || value == digitalToAnalogOff)
|
|
return;
|
|
|
|
digitalToAnalogOff = value;
|
|
OnPropertyChanged();
|
|
throttledDigitalToAnalogChanged.OnNext(true);
|
|
}
|
|
}
|
|
// ReSharper restore UnusedMember.Global
|
|
|
|
|
|
public InputOutputViewModel(SettingsViewModel settingsViewModel, IMassiveKnobOrchestrator orchestrator, MassiveKnobActionType actionType, int index)
|
|
{
|
|
this.orchestrator = orchestrator;
|
|
this.actionType = actionType;
|
|
this.index = index;
|
|
|
|
|
|
// For design-time support
|
|
if (orchestrator == null)
|
|
{
|
|
DigitalToAnalogOn = 100;
|
|
return;
|
|
}
|
|
|
|
|
|
bool AllowAction(ActionViewModel actionViewModel)
|
|
{
|
|
if (actionViewModel.RepresentsNull)
|
|
return true;
|
|
|
|
if (actionViewModel.Action.ActionType == actionType)
|
|
return true;
|
|
|
|
// Allow digital actions to be assigned to analog outputs, extra conversion settings will be shown
|
|
return actionType == MassiveKnobActionType.OutputAnalog &&
|
|
actionViewModel.Action.ActionType == MassiveKnobActionType.OutputDigital;
|
|
}
|
|
|
|
|
|
Actions = settingsViewModel.Actions.Where(AllowAction).ToList();
|
|
|
|
var actionInfo = orchestrator.GetAction(actionType, index);
|
|
|
|
selectedAction = actionInfo != null
|
|
? Actions.SingleOrDefault(a => !a.RepresentsNull && a.Action.ActionId == actionInfo.Info.ActionId)
|
|
: Actions.Single(a => a.RepresentsNull);
|
|
|
|
actionSettingsControl = actionInfo?.Instance.CreateSettingsControl();
|
|
|
|
|
|
if (actionType != MassiveKnobActionType.OutputAnalog)
|
|
return;
|
|
|
|
var digitalToAnalogSettings = orchestrator.GetDigitalToAnalogSettings(index);
|
|
digitalToAnalogOn = digitalToAnalogSettings.OnValue;
|
|
digitalToAnalogOff = digitalToAnalogSettings.OffValue;
|
|
|
|
digitalToAnalogChangedSubscription = throttledDigitalToAnalogChanged
|
|
.Throttle(TimeSpan.FromMilliseconds(250))
|
|
.Subscribe(b =>
|
|
{
|
|
orchestrator?.UpdateDigitalToAnalogSettings(index, settings =>
|
|
{
|
|
settings.OnValue = digitalToAnalogOn;
|
|
settings.OffValue = digitalToAnalogOff;
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
public void Dispose()
|
|
{
|
|
if (ActionSettingsControl is IDisposable disposable)
|
|
disposable.Dispose();
|
|
|
|
digitalToAnalogChangedSubscription?.Dispose();
|
|
throttledDigitalToAnalogChanged.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 InputOutputViewModelDesignTime : InputOutputViewModel
|
|
{
|
|
public InputOutputViewModelDesignTime() : base(null, null, MassiveKnobActionType.OutputAnalog, 0)
|
|
{
|
|
}
|
|
}
|
|
}
|