Add aux sensors.

master
Glenn Maynard 5 years ago
parent 3bb92a0b24
commit 883d87779a
  1. 3
      smx-config/App.config
  2. 83
      smx-config/Helpers.cs
  3. 5
      smx-config/MainWindow.xaml
  4. 106
      smx-config/MainWindow.xaml.cs
  5. 14
      smx-config/Properties/Settings.Designer.cs
  6. 3
      smx-config/Properties/Settings.settings
  7. 7
      smx-config/SMXConfig.csproj
  8. 102
      smx-config/SetAuxSensors.xaml
  9. 99
      smx-config/SetAuxSensors.xaml.cs

@ -13,6 +13,9 @@
<setting name="LaunchOnStartup" serializeAs="String">
<value>False</value>
</setting>
<setting name="AuxSensors" serializeAs="String">
<value />
</setting>
</smx_config.Properties.Settings>
</userSettings>
</configuration>

@ -381,6 +381,7 @@ namespace smx_config
// on the user's settings. This handles managing which sensors each slider controls.
static class ThresholdSettings
{
[Serializable]
public struct PanelAndSensor
{
public PanelAndSensor(int panel, int sensor)
@ -408,10 +409,75 @@ namespace smx_config
// are then synced to the other panels.
{ "cardinal", 7 },
{ "corner", 2 },
// The aux threshold allows giving a list of specific sensors different thresholds.
{ "aux", -1 },
};
// Save and load the list of aux sensors to settings. These aren't saved to the pad, we just
// keep them in application settings.
static List<PanelAndSensor> cachedAuxSensors;
static public void SetAuxSensors(List<PanelAndSensor> panelAndSensors)
{
List<object> result = new List<object>();
foreach(PanelAndSensor panelAndSensor in panelAndSensors)
{
List<int> panelAndSensorArray = new List<int>() { panelAndSensor.panel, panelAndSensor.sensor };
result.Add(panelAndSensorArray);
}
Properties.Settings.Default.AuxSensors = SerializeJSON.Serialize(result);
Properties.Settings.Default.Save();
// Clear the cache. Set it to null instead of assigning panelAndSensors to it to force
// it to re-parse at least once, to catch problems early.
cachedAuxSensors = null;
}
// Return the sensors that are controlled by the aux threshold slider. The other
// threshold sliders will leave these alone.
static public List<PanelAndSensor> GetAuxSensors()
{
// Properties.Settings.Default.AuxSensors = "[[0,0], [1,0]]";
// This is only ever changed with calls to SetSavedAuxSensors.
if(cachedAuxSensors != null)
return Helpers.DeepClone(cachedAuxSensors);
List<PanelAndSensor> result = new List<PanelAndSensor>();
if(Properties.Settings.Default.AuxSensors == "")
return result;
try {
// This is a list of [panel,sensor] arrays:
// [[0,0], [0,1], [1,0]]
List<object> sensors = SMXJSON.ParseJSON.Parse<List<object>>(Properties.Settings.Default.AuxSensors);
foreach(object panelAndSensorObj in sensors)
{
List<object> panelAndSensor = (List<object>) panelAndSensorObj;
int panel = panelAndSensor.Get(0, -1);
int sensor = panelAndSensor.Get(1, -1);
if(panel == -1 || sensor == -1)
continue;
result.Add(new PanelAndSensor(panel, sensor));
}
} catch(ParseError) {
return result;
}
cachedAuxSensors = result;
// SetAuxSensors(result); // XXX
// SetSavedAuxSensors(result);
return Helpers.DeepClone(cachedAuxSensors);
}
static public List<PanelAndSensor> GetControlledSensorsForSliderType(string Type, bool advancedMode)
{
// The aux threshold slider always controls the aux sensors.
if(Type == "aux")
return GetAuxSensors();
List<PanelAndSensor> result = new List<PanelAndSensor>();
// Check if this slider is shown in this mode.
@ -432,6 +498,7 @@ namespace smx_config
// If advanced mode is disabled, save to all panels this slider affects. The down arrow controls
// all four cardinal panels. (If advanced mode is enabled we'll never be a different cardinal
// direction, since those widgets won't exist.) If it's disabled, just write to our own panel.
List<PanelAndSensor> auxSensors = GetAuxSensors();
List<int> saveToPanels = new List<int>();
int ourPanelIdx = panelNameToIndex[Type];
saveToPanels.Add(ourPanelIdx);
@ -442,25 +509,17 @@ namespace smx_config
{
for(int sensor = 0; sensor < 4; ++sensor)
{
// Ignore sensors controlled by the aux threshold.
PanelAndSensor panelAndSensor = new PanelAndSensor(panelIdx, sensor);
if(auxSensors.Contains(panelAndSensor))
continue;
result.Add(panelAndSensor);
}
}
return result;
}
// Return the sensors that are controlled by the aux threshold slider. The other
// threshold sliders will leave these alone.
static public List<PanelAndSensor> GetAuxSensors()
{
List<PanelAndSensor> result = new List<PanelAndSensor>();
result.Add(new PanelAndSensor(1,0));
result.Add(new PanelAndSensor(1,1));
result.Add(new PanelAndSensor(1,2));
result.Add(new PanelAndSensor(1,3));
return result;
}
}
// This class just makes it easier to assemble binary command packets.

@ -931,6 +931,11 @@ instead of only panels with sensors.</TextBlock>
<Button Content="Import" Width="50" Padding="5,2" Margin="5,10" Click="ImportSettings" />
</StackPanel>
<Separator Margin="0,10,0,10" />
<TextBlock HorizontalAlignment="Center"
xml:space="preserve" FontSize="16">Aux sensors</TextBlock>
<Button Content="Set auxilliary sensors" Width="140" Margin="0 10 0 0" Padding="0 4" Click="SetAuxSensors_Click"/>
<Separator Margin="0,10,0,10" />
<TextBlock HorizontalAlignment="Center"
xml:space="preserve" FontSize="16">Reset all settings</TextBlock>

@ -17,7 +17,8 @@ namespace smx_config
{
InitializeComponent();
onConfigChange = new OnConfigChange(this, delegate(LoadFromConfigDelegateArgs args) {
onConfigChange = new OnConfigChange(this, delegate (LoadFromConfigDelegateArgs args)
{
LoadUIFromConfig(args);
});
@ -26,7 +27,7 @@ namespace smx_config
// to tray to keep playing animations. If we're not controlling animations,
// or the firmware supports doing them automatically, don't bug the user
// with a prompt.
Closing += delegate(object sender, System.ComponentModel.CancelEventArgs e)
Closing += delegate (object sender, System.ComponentModel.CancelEventArgs e)
{
LoadFromConfigDelegateArgs args = CurrentSMXDevice.singleton.GetState();
@ -70,10 +71,10 @@ namespace smx_config
List<string> thresholdSliderNames = new List<string>()
{
"up-left", "up", "up-right", "left", "center", "right", "down-left", "down", "down-right", "cardinal", "corner",
"up-left", "up", "up-right", "left", "center", "right", "down-left", "down", "down-right", "cardinal", "corner", "aux",
};
Dictionary<string,string> thresholdToIcon = new Dictionary<string, string>()
Dictionary<string, string> thresholdToIcon = new Dictionary<string, string>()
{
{ "up-left", "Resources/pad_up_left.png" },
{ "up", "Resources/pad_up.png" },
@ -86,11 +87,12 @@ namespace smx_config
{ "down-right","Resources/pad_down_right.png" },
{ "cardinal", "Resources/pad_cardinal.png" },
{ "corner", "Resources/pad_diagonal.png" },
{ "aux", "Resources/pad_diagonal.png" },
};
bool IsThresholdSliderShown(string type)
{
bool AdvancedModeEnabled = (bool) AdvancedModeEnabledCheckbox.IsChecked;
bool AdvancedModeEnabled = (bool)AdvancedModeEnabledCheckbox.IsChecked;
SMX.SMXConfig config = ActivePad.GetFirstActivePadConfig();
bool[] enabledPanels = config.GetEnabledPanels();
@ -108,20 +110,20 @@ namespace smx_config
// turned back on.
switch(type)
{
case "up-left": return enabledPanels[0];
case "up": return enabledPanels[1];
case "up-right": return enabledPanels[2];
case "left": return enabledPanels[3];
case "center": return enabledPanels[4];
case "right": return enabledPanels[5];
case "down-left": return enabledPanels[6];
case "down": return enabledPanels[7];
case "down-right": return enabledPanels[8];
case "up-left": return enabledPanels[0];
case "up": return enabledPanels[1];
case "up-right": return enabledPanels[2];
case "left": return enabledPanels[3];
case "center": return enabledPanels[4];
case "right": return enabledPanels[5];
case "down-left": return enabledPanels[6];
case "down": return enabledPanels[7];
case "down-right": return enabledPanels[8];
// Show cardinal and corner if at least one panel they affect is enabled.
case "cardinal": return enabledPanels[3] || enabledPanels[5] || enabledPanels[8];
case "corner": return enabledPanels[0] || enabledPanels[2] || enabledPanels[6] || enabledPanels[8];
default: return true;
case "cardinal": return enabledPanels[3] || enabledPanels[5] || enabledPanels[8];
case "corner": return enabledPanels[0] || enabledPanels[2] || enabledPanels[6] || enabledPanels[8];
default: return true;
}
}
@ -153,7 +155,7 @@ namespace smx_config
ThresholdSlider slider = CreateThresholdSlider(sliderName);
DockPanel.SetDock(slider, Dock.Top);
slider.Margin = new Thickness(0,8,0,0);
slider.Margin = new Thickness(0, 8, 0, 0);
ThresholdSliderContainer.Children.Add(slider);
}
}
@ -163,20 +165,20 @@ namespace smx_config
base.OnApplyTemplate();
// Add our WndProc hook.
HwndSource source = (HwndSource) PresentationSource.FromVisual(this);
HwndSource source = (HwndSource)PresentationSource.FromVisual(this);
source.AddHook(new HwndSourceHook(WndProcHook));
Version1.Content = "SMXConfig version " + SMX.SMX.Version();
Version2.Content = "SMXConfig version " + SMX.SMX.Version();
AutoLightsColor.StartedDragging += delegate() { showAutoLightsColor.Start(); };
AutoLightsColor.StoppedDragging += delegate() { showAutoLightsColor.Stop(); };
AutoLightsColor.StoppedDragging += delegate() { showAutoLightsColor.Stop(); };
AutoLightsColor.StartedDragging += delegate () { showAutoLightsColor.Start(); };
AutoLightsColor.StoppedDragging += delegate () { showAutoLightsColor.Stop(); };
AutoLightsColor.StoppedDragging += delegate () { showAutoLightsColor.Stop(); };
CreateThresholdSliders();
// This doesn't happen at the same time AutoLightsColor is used, since they're on different tabs.
Diagnostics.SetShowAllLights += delegate(bool on)
Diagnostics.SetShowAllLights += delegate (bool on)
{
if(on)
showAutoLightsColor.Start();
@ -184,7 +186,7 @@ namespace smx_config
showAutoLightsColor.Stop();
};
SetAllPanelsToCurrentColor.Click += delegate(object sender, RoutedEventArgs e)
SetAllPanelsToCurrentColor.Click += delegate (object sender, RoutedEventArgs e)
{
// Get the color of the selected color button, and apply it to all other buttons.
Color color = selectedButton.getColor();
@ -206,7 +208,7 @@ namespace smx_config
ColorButton[] buttons = getColorPickerButtons();
foreach(ColorButton button in buttons)
{
button.Click += delegate(object sender, RoutedEventArgs e)
button.Click += delegate (object sender, RoutedEventArgs e)
{
ColorButton clickedButton = sender as ColorButton;
selectedButton = clickedButton;
@ -221,7 +223,7 @@ namespace smx_config
// The user pressed either the "panel colors" or "GIF animations" button.
bool pressedPanelColors = sender == PanelColorsButton;
foreach(Tuple<int,SMX.SMXConfig> activePad in ActivePad.ActivePads())
foreach(Tuple<int, SMX.SMXConfig> activePad in ActivePad.ActivePads())
{
SMX.SMXConfig config = activePad.Item2;
@ -240,19 +242,19 @@ namespace smx_config
private void LoadUIFromConfig(LoadFromConfigDelegateArgs args)
{
bool EitherControllerConnected = args.controller[0].info.connected || args.controller[1].info.connected;
Main.Visibility = EitherControllerConnected? Visibility.Visible:Visibility.Hidden;
Searching.Visibility = EitherControllerConnected? Visibility.Hidden:Visibility.Visible;
ConnectedPads.Visibility = EitherControllerConnected? Visibility.Visible:Visibility.Hidden;
PanelColorP1.Visibility = args.controller[0].info.connected? Visibility.Visible:Visibility.Collapsed;
PanelColorP2.Visibility = args.controller[1].info.connected? Visibility.Visible:Visibility.Collapsed;
Main.Visibility = EitherControllerConnected ? Visibility.Visible : Visibility.Hidden;
Searching.Visibility = EitherControllerConnected ? Visibility.Hidden : Visibility.Visible;
ConnectedPads.Visibility = EitherControllerConnected ? Visibility.Visible : Visibility.Hidden;
PanelColorP1.Visibility = args.controller[0].info.connected ? Visibility.Visible : Visibility.Collapsed;
PanelColorP2.Visibility = args.controller[1].info.connected ? Visibility.Visible : Visibility.Collapsed;
EnableCenterTopSensorCheckbox.Visibility =
P1_Floor.Visibility =
P2_Floor.Visibility =
args.firmwareVersion() >= 5? Visibility.Visible:Visibility.Collapsed;
args.firmwareVersion() >= 5 ? Visibility.Visible : Visibility.Collapsed;
// Show the color slider or GIF UI depending on which one is set in flags.
// If both pads are turned on, just use the first one.
foreach(Tuple<int,SMX.SMXConfig> activePad in ActivePad.ActivePads())
foreach(Tuple<int, SMX.SMXConfig> activePad in ActivePad.ActivePads())
{
SMX.SMXConfig config = activePad.Item2;
@ -260,8 +262,8 @@ namespace smx_config
// If it's not set, show the color slider UI.
SMX.SMXConfigFlags flags = config.configFlags;
bool usePressedAnimations = (flags & SMX.SMXConfigFlags.AutoLightingUsePressedAnimations) != 0;
ColorPickerGroup.Visibility = usePressedAnimations? Visibility.Collapsed:Visibility.Visible;
GIFGroup.Visibility = usePressedAnimations? Visibility.Visible:Visibility.Collapsed;
ColorPickerGroup.Visibility = usePressedAnimations ? Visibility.Collapsed : Visibility.Visible;
GIFGroup.Visibility = usePressedAnimations ? Visibility.Visible : Visibility.Collapsed;
// Tell the color mode buttons which one is selected, to set the button highlight.
PanelColorsButton.Selected = !usePressedAnimations;
@ -294,7 +296,7 @@ namespace smx_config
}
}
}
ThresholdWarningText.Visibility = ShowThresholdWarningText? Visibility.Visible : Visibility.Hidden;
ThresholdWarningText.Visibility = ShowThresholdWarningText ? Visibility.Visible : Visibility.Hidden;
// If a second controller has connected and we're on Both, see if we need to prompt
// to sync configs. We only actually need to do this if a controller just connected.
@ -357,7 +359,7 @@ namespace smx_config
SMX.SMXConfig config = activePad.Item2;
bool uploadsSupported = config.masterVersion >= 4;
LeaveRunning.Visibility = uploadsSupported? Visibility.Collapsed:Visibility.Visible;
LeaveRunning.Visibility = uploadsSupported ? Visibility.Collapsed : Visibility.Visible;
break;
}
}
@ -455,12 +457,12 @@ namespace smx_config
bool TwoControllersConnected = args.controller[0].info.connected && args.controller[1].info.connected;
// Only show the dropdown if two controllers are connected.
ConnectedPadList.Visibility = TwoControllersConnected? Visibility.Visible:Visibility.Collapsed;
ConnectedPadList.Visibility = TwoControllersConnected ? Visibility.Visible : Visibility.Collapsed;
// Only show the P1/P2 text if only one controller is connected, since it takes the place
// of the dropdown.
P1Connected.Visibility = (!TwoControllersConnected && args.controller[0].info.connected)? Visibility.Visible:Visibility.Collapsed;
P2Connected.Visibility = (!TwoControllersConnected && args.controller[1].info.connected)? Visibility.Visible:Visibility.Collapsed;
P1Connected.Visibility = (!TwoControllersConnected && args.controller[0].info.connected) ? Visibility.Visible : Visibility.Collapsed;
P2Connected.Visibility = (!TwoControllersConnected && args.controller[1].info.connected) ? Visibility.Visible : Visibility.Collapsed;
if(!TwoControllersConnected)
return;
@ -478,7 +480,7 @@ namespace smx_config
private void FactoryReset_Click(object sender, RoutedEventArgs e)
{
foreach(Tuple<int,SMX.SMXConfig> activePad in ActivePad.ActivePads())
foreach(Tuple<int, SMX.SMXConfig> activePad in ActivePad.ActivePads())
{
int pad = activePad.Item1;
SMX.SMX.FactoryReset(pad);
@ -494,7 +496,7 @@ namespace smx_config
private void ExportSettings(object sender, RoutedEventArgs e)
{
// Save the current thresholds on the first available pad as a preset.
foreach(Tuple<int,SMX.SMXConfig> activePad in ActivePad.ActivePads())
foreach(Tuple<int, SMX.SMXConfig> activePad in ActivePad.ActivePads())
{
int pad = activePad.Item1;
SMX.SMXConfig config = activePad.Item2;
@ -505,7 +507,7 @@ namespace smx_config
dialog.DefaultExt = ".smxcfg";
dialog.Filter = "StepManiaX settings (.smxcfg)|*.smxcfg";
bool? result = dialog.ShowDialog();
if(result == null || !(bool) result)
if(result == null || !(bool)result)
return;
System.IO.File.WriteAllText(dialog.FileName, json);
@ -521,13 +523,13 @@ namespace smx_config
dialog.DefaultExt = ".smxcfg";
dialog.Filter = "StepManiaX settings (.smxcfg)|*.smxcfg";
bool? result = dialog.ShowDialog();
if(result == null || !(bool) result)
if(result == null || !(bool)result)
return;
string json = Helpers.ReadFile(dialog.FileName);
// Apply settings from the file to all active pads.
foreach(Tuple<int,SMX.SMXConfig> activePad in ActivePad.ActivePads())
foreach(Tuple<int, SMX.SMXConfig> activePad in ActivePad.ActivePads())
{
int pad = activePad.Item1;
SMX.SMXConfig config = activePad.Item2;
@ -551,13 +553,13 @@ namespace smx_config
dialog.DefaultExt = ".gif";
dialog.Filter = "Animated GIF (.gif)|*.gif";
bool? result = dialog.ShowDialog();
if(result == null || !(bool) result)
if(result == null || !(bool)result)
return;
byte[] buf = Helpers.ReadBinaryFile(dialog.FileName);
SMX.SMX.LightsType type = pressed? SMX.SMX.LightsType.LightsType_Pressed:SMX.SMX.LightsType.LightsType_Released;
SMX.SMX.LightsType type = pressed ? SMX.SMX.LightsType.LightsType_Pressed : SMX.SMX.LightsType.LightsType_Released;
foreach(Tuple<int,SMX.SMXConfig> activePad in ActivePad.ActivePads())
foreach(Tuple<int, SMX.SMXConfig> activePad in ActivePad.ActivePads())
{
int pad = activePad.Item1;
@ -583,7 +585,7 @@ namespace smx_config
// For firmwares that support it, upload the animation to the pad now. Otherwise,
// we'll run the animation directly.
foreach(Tuple<int,SMX.SMXConfig> activePad in ActivePad.ActivePads())
foreach(Tuple<int, SMX.SMXConfig> activePad in ActivePad.ActivePads())
{
int pad = activePad.Item1;
@ -598,6 +600,12 @@ namespace smx_config
}
}
private void SetAuxSensors_Click(object sender, RoutedEventArgs e)
{
SetAuxSensors dialog = new SetAuxSensors();
dialog.ShowDialog();
}
private void UploadLatestGIF()
{
// Create a progress window. Center it on top of the main window.

@ -12,7 +12,7 @@ namespace smx_config.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.6.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@ -34,5 +34,17 @@ namespace smx_config.Properties {
this["LaunchOnStartup"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string AuxSensors {
get {
return ((string)(this["AuxSensors"]));
}
set {
this["AuxSensors"] = value;
}
}
}
}

@ -5,5 +5,8 @@
<Setting Name="LaunchOnStartup" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="AuxSensors" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>

@ -105,6 +105,9 @@
<Compile Include="DiagnosticsWidgets.cs" />
<Compile Include="DoubleSlider.cs" />
<Compile Include="Helpers.cs" />
<Compile Include="SetAuxSensors.xaml.cs">
<DependentUpon>SetAuxSensors.xaml</DependentUpon>
</Compile>
<Compile Include="ProgressWindow.xaml.cs">
<DependentUpon>ProgressWindow.xaml</DependentUpon>
</Compile>
@ -123,6 +126,10 @@
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="SetAuxSensors.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="ProgressWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

@ -0,0 +1,102 @@
<Window x:Class="smx_config.SetAuxSensors"
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"
Icon="Resources/window icon.png"
Background="#DDD"
Height="418" Width="325" ResizeMode="NoResize"
xmlns:controls="clr-namespace:smx_config"
x:Name="root"
Title="Select Auxilliary Sensors"
UseLayoutRounding="True">
<Window.Resources>
<Style x:Key="SensorSelectionButton" TargetType="{x:Type ToggleButton}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Background" Value="#FFDDDDDD"/>
<Setter Property="BorderBrush" Value="#FF707070"/>
<Setter Property="Foreground" Value="#FFFFFF"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:SensorSelectionButton}">
<Border x:Name="border" BorderBrush="#000000" BorderThickness="1" SnapsToDevicePixels="true">
<ContentPresenter
SnapsToDevicePixels="true"
Focusable="False"
HorizontalAlignment="Center" VerticalAlignment="Center"
/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Background" TargetName="border" Value="#FF2020A0"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" TargetName="border" Value="#FF00F000"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type controls:SensorSelector}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:SensorSelector}">
<Border Padding="1">
<Grid Width="70" Height="70">
<!-- XXX: the order of these is wrong -->
<controls:SensorSelectionButton x:Name="Sensor0" Style="{StaticResource SensorSelectionButton}"
Width="40" Height="13" VerticalAlignment="Top" />
<controls:SensorSelectionButton x:Name="Sensor1" Style="{StaticResource SensorSelectionButton}"
Width="40" Height="13" VerticalAlignment="Bottom" />
<controls:SensorSelectionButton x:Name="Sensor2" Style="{StaticResource SensorSelectionButton}"
Width="13" Height="40" HorizontalAlignment="Left" />
<controls:SensorSelectionButton x:Name="Sensor3" Style="{StaticResource SensorSelectionButton}"
Width="13" Height="40" HorizontalAlignment="Right" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel Background="#FFE5E5E5">
<TextBlock xml:space="preserve" HorizontalAlignment="Center" Margin="0,15,0,10" TextAlignment="Center" FontSize="16">Select which sensors are controlled
by the auxilliary threshold.</TextBlock>
<Grid Width="250" Height="250" Background="#FFAAAAAA" Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<controls:SensorSelector Grid.Row="0" Grid.Column="0" Panel="0" Focusable="false" />
<controls:SensorSelector Grid.Row="0" Grid.Column="1" Panel="1" Focusable="false" />
<controls:SensorSelector Grid.Row="0" Grid.Column="2" Panel="2" Focusable="false" />
<controls:SensorSelector Grid.Row="1" Grid.Column="0" Panel="3" Focusable="false" />
<controls:SensorSelector Grid.Row="1" Grid.Column="1" Panel="4" Focusable="false" />
<controls:SensorSelector Grid.Row="1" Grid.Column="2" Panel="5" Focusable="false" />
<controls:SensorSelector Grid.Row="2" Grid.Column="0" Panel="6" Focusable="false" />
<controls:SensorSelector Grid.Row="2" Grid.Column="1" Panel="7" Focusable="false" />
<controls:SensorSelector Grid.Row="2" Grid.Column="2" Panel="8" Focusable="false" />
</Grid>
<Button x:Name="OK" Content="OK" IsDefault="True" Click="OK_Click" HorizontalAlignment="Center" FontSize="20" Padding="10,4" Margin="0,10,0,0" />
</StackPanel>
</Window>

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace smx_config
{
public class SensorSelectionButton: ToggleButton
{
}
// A control with one button for each of four sensors:
class SensorSelector: Control
{
// The panel we're editing (0-8).
public static readonly DependencyProperty PanelProperty = DependencyProperty.RegisterAttached("Panel",
typeof(int), typeof(SensorSelector), new FrameworkPropertyMetadata(0));
public int Panel {
get { return (int) this.GetValue(PanelProperty); }
set { this.SetValue(PanelProperty, value); }
}
ToggleButton[] SensorSelectionButtons = new ToggleButton[4];
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
for(int sensor = 0; sensor < 4; ++sensor)
{
int ThisSensor = sensor; // bind
SensorSelectionButtons[sensor] = GetTemplateChild("Sensor" + sensor) as ToggleButton;
SensorSelectionButtons[sensor].Click += delegate(object sender, RoutedEventArgs e)
{
ClickedSensorButton(ThisSensor);
};
}
// These settings are stored in the application settings, not on the pad. However,
// we treat changes to this as config changes, so we can use the same OnConfigChange
// method for updating.
OnConfigChange onConfigChange;
onConfigChange = new OnConfigChange(this, delegate(LoadFromConfigDelegateArgs args) {
LoadUIFromConfig(args);
});
}
private void ClickedSensorButton(int sensor)
{
// Toggle the clicked sensor.
Console.WriteLine("Clicked sensor " + sensor);
List<ThresholdSettings.PanelAndSensor> auxSensors = ThresholdSettings.GetAuxSensors();
bool enabled = !IsSensorEnabled(auxSensors, sensor);
if(enabled)
auxSensors.Add(new ThresholdSettings.PanelAndSensor(Panel, sensor));
else
auxSensors.Remove(new ThresholdSettings.PanelAndSensor(Panel, sensor));
ThresholdSettings.SetAuxSensors(auxSensors);
CurrentSMXDevice.singleton.FireConfigurationChanged(this);
}
// Return true if the given sensor is marked as an aux sensor.
bool IsSensorEnabled(List<ThresholdSettings.PanelAndSensor> auxSensors, int sensor)
{
foreach(ThresholdSettings.PanelAndSensor panelAndSensor in auxSensors)
{
if(panelAndSensor.panel == Panel && panelAndSensor.sensor == sensor)
return true;
}
return false;
}
private void LoadUIFromConfig(LoadFromConfigDelegateArgs args)
{
// Check the selected aux sensors.
List<ThresholdSettings.PanelAndSensor> auxSensors = ThresholdSettings.GetAuxSensors();
for(int sensor = 0; sensor < 4; ++sensor)
SensorSelectionButtons[sensor].IsChecked = IsSensorEnabled(auxSensors, sensor);
}
}
// This dialog sets which sensors are controlled by the auxilliary threshold. The actual
// work is done by SensorSelector above.
public partial class SetAuxSensors: Window
{
public SetAuxSensors()
{
InitializeComponent();
}
private void OK_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
}
Loading…
Cancel
Save