// Yield each connected pad which is currently active for configuration. public static IEnumerable <Tuple <int, SMX.SMXConfig> > ActivePads(LoadFromConfigDelegateArgs args) { bool Pad1Connected = args.controller[0].info.connected; bool Pad2Connected = args.controller[1].info.connected; // If both pads are connected and a single pad is selected, ignore the deselected pad. if (Pad1Connected && Pad2Connected) { if (selectedPad == SelectedPad.P1) { Pad2Connected = false; } if (selectedPad == SelectedPad.P2) { Pad1Connected = false; } } if (Pad1Connected) { yield return(Tuple.Create(0, args.controller[0].config)); } if (Pad2Connected) { yield return(Tuple.Create(1, args.controller[1].config)); } }
void RefreshTrayIcon(LoadFromConfigDelegateArgs args, bool force = false) { if (trayIcon == null) { return; } bool EitherControllerConnected = false; for (int pad = 0; pad < 2; ++pad) { if (args.controller[pad].info.connected) { EitherControllerConnected = true; } } // Skip the refresh if the connected state didn't change. if (wasConnected == EitherControllerConnected && !force) { return; } wasConnected = EitherControllerConnected; trayIcon.Text = EitherControllerConnected? "StepManiaX (connected)":"StepManiaX (disconnected)"; // Set the tray icon. string filename = EitherControllerConnected? "window%20icon.ico":"window%20icon%20grey.ico"; Stream iconStream = GetResourceStream(new Uri("pack://application:,,,/Resources/" + filename)).Stream; trayIcon.Icon = new System.Drawing.Icon(iconStream); }
protected override void OnClick() { if (AdvancedModeEnabled) { // Stop forcing advanced mode on, and sync the thresholds so we exit advanced mode. ForcedOn = false; for (int pad = 0; pad < 2; ++pad) { SMX.SMXConfig config; if (!SMX.SMX.GetConfig(pad, out config)) { continue; } ConfigPresets.SyncUnifiedThresholds(ref config); SMX.SMX.SetConfig(pad, config); } CurrentSMXDevice.singleton.FireConfigurationChanged(this); } else { // Enable advanced mode. ForcedOn = true; } // Refresh the UI. LoadFromConfigDelegateArgs args = CurrentSMXDevice.singleton.GetState(); LoadUIFromConfig(args.controller[args.FirstController].config); }
void RefreshVisibility() { LoadFromConfigDelegateArgs args = CurrentSMXDevice.singleton.GetState(); SMX.SMXConfig config = args.controller[args.FirstController].config; this.Visibility = ShouldBeDisplayed(config)? Visibility.Visible:Visibility.Collapsed; }
// Update the selected color picker based on the value of selectedButton. private void RefreshSelectedColorPicker() { LoadFromConfigDelegateArgs args = CurrentSMXDevice.singleton.GetState(); ColorButton[] buttons = getColorPickerButtons(); // If our selected button isn't enabled (or no button is selected), try to select a // different one. if (selectedButton == null || !selectedButton.isEnabled(args)) { foreach (ColorButton button in buttons) { if (button.isEnabled(args)) { selectedButton = button; break; } } } // Tell the buttons which one is selected. foreach (ColorButton button in buttons) { button.IsSelected = button == selectedButton; } // Tell the color slider which button is selected. AutoLightsColor.colorButton = selectedButton; }
// Refresh which items are visible in the connected pads list, and which item is displayed as selected. private void RefreshConnectedPadList(LoadFromConfigDelegateArgs args) { 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; // 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; if (!TwoControllersConnected) { return; } // Set the current selection. ActivePad.SelectedPad selectedPad = ActivePad.selectedPad; switch (ActivePad.selectedPad) { case ActivePad.SelectedPad.P1: ConnectedPadList.SelectedItem = ConnectedPadList_P1; break; case ActivePad.SelectedPad.P2: ConnectedPadList.SelectedItem = ConnectedPadList_P2; break; case ActivePad.SelectedPad.Both: ConnectedPadList.SelectedItem = ConnectedPadList_Both; break; } }
// The floor color button is available if the firmware is v4 or greater. public override bool isEnabled(LoadFromConfigDelegateArgs args) { int pad = getPadNo(); SMX.SMXConfig config = args.controller[pad].config; return(config.masterVersion >= 4); }
public LoadFromConfigDelegateArgs GetState() { LoadFromConfigDelegateArgs args = new LoadFromConfigDelegateArgs(); args.controller = new LoadFromConfigDelegateArgsPerController[2]; for (int pad = 0; pad < 2; ++pad) { LoadFromConfigDelegateArgsPerController controller; controller.test_data = new SMX.SMXSensorTestModeData(); // Expand the inputs mask to an array. UInt16 Inputs = SMX.SMX.GetInputState(pad); controller.inputs = new bool[9]; for (int i = 0; i < 9; ++i) { controller.inputs[i] = (Inputs & (1 << i)) != 0; } SMX.SMX.GetInfo(pad, out controller.info); SMX.SMX.GetConfig(pad, out controller.config); SMX.SMX.GetTestData(pad, out controller.test_data); args.controller[pad] = controller; } return(args); }
private void LoadUIFromConfig(LoadFromConfigDelegateArgs args) { if (UpdatingUI || _colorButton == null) { return; } // Make sure SaveToConfig doesn't treat these as the user changing values. UpdatingUI = true; // Reverse the scaling we applied in SaveToConfig. Color rgb = _colorButton.getColor(); double h, s, v; Helpers.ToHSV(rgb, out h, out s, out v); // Check for white. Since the conversion through LightsScaleFactor may not round trip // back to exactly #FFFFFF, give some room for error in the value (brightness). if (s <= 0.001 && v >= .90) { // This is white, so set it to the white block at the left edge of the slider. HueSlider.Value = HueSlider.Minimum; } else { HueSlider.Value = h; } UpdatingUI = false; }
public void FireConfigurationChanged(object source) { LoadFromConfigDelegateArgs args = GetState(); args.ConfigurationChanged = true; args.source = source; ConfigurationChanged?.Invoke(args); }
private void ConfigurationChanged(LoadFromConfigDelegateArgs args) { if (args.ConfigurationChanged || (RefreshOnInputChange && args.InputChanged) || (RefreshOnTestDataChange && args.TestDataChanged)) { Callback(args); } }
private void LoadUIFromConfig(LoadFromConfigDelegateArgs args) { // Check the selected custom-sensors. List <ThresholdSettings.PanelAndSensor> customSensors = ThresholdSettings.GetCustomSensors(); for (int sensor = 0; sensor < 4; ++sensor) { SensorSelectionButtons[sensor].IsChecked = IsSensorEnabled(customSensors, sensor); } }
// Update which of the "Leave this application running", etc. blocks to display. private void RefreshUploadPadText(LoadFromConfigDelegateArgs args) { foreach (Tuple <int, SMX.SMXConfig> activePad in ActivePad.ActivePads()) { SMX.SMXConfig config = activePad.Item2; bool uploadsSupported = config.masterVersion >= 4; LeaveRunning.Visibility = uploadsSupported ? Visibility.Collapsed : Visibility.Visible; break; } }
// Set PanelColor. This widget doesn't change the color, it only reflects the current configuration. private void LoadUIFromConfig(LoadFromConfigDelegateArgs args) { SMX.SMXConfig config = args.controller[getPadNo()].config; // Hide disabled color buttons. Visibility = isEnabled(args)? Visibility.Visible:Visibility.Hidden; Color rgb = getColor(); PanelColor = new SolidColorBrush(rgb); }
// We know the selected pads are synced if there are two active, and when refreshing a // UI we just want one of them to set the UI to. For convenience, return the first one. public static SMX.SMXConfig GetFirstActivePadConfig(LoadFromConfigDelegateArgs args) { foreach (Tuple <int, SMX.SMXConfig> activePad in ActivePads(args)) { return(activePad.Item2); } // There aren't any pads connected. Just return a dummy config, since the UI // isn't visible. return(new SMX.SMXConfig()); }
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; P1Connected.IsEnabled = args.controller[0].info.connected; P2Connected.IsEnabled = args.controller[1].info.connected; PanelColorP1.Visibility = args.controller[0].info.connected? Visibility.Visible:Visibility.Collapsed; PanelColorP2.Visibility = args.controller[1].info.connected? Visibility.Visible:Visibility.Collapsed; }
// Update the selected diagnostics button based on the value of selectedButton. private void RefreshSelectedPanel() { LoadFromConfigDelegateArgs args = CurrentSMXDevice.singleton.GetState(); DiagnosticsPanelButton[] buttons = getPanelSelectionButtons(); // Tell the buttons which one is selected. foreach (DiagnosticsPanelButton button in buttons) { button.IsSelected = button.Panel == SelectedPanel; } }
// A panel is enabled if it's enabled in the panel mask, which can be // changed on the advanced tab. public override bool isEnabled(LoadFromConfigDelegateArgs args) { int pad = getPadNo(); SMX.SMXConfig config = args.controller[pad].config; if (!args.controller[pad].info.connected) { return(false); } int PanelIndex = Panel % 9; bool[] enabledPanels = config.GetEnabledPanels(); return(enabledPanels[PanelIndex]); }
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; RefreshConnectedPadList(args); // 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. if (args.ConfigurationChanged) { CheckConfiguringBothPads(args); } }
private void CheckForChanges() { LoadFromConfigDelegateArgs args = GetState(); // Mark which parts have changed. // // For configuration, we only check for connection state changes. Actual configuration // changes are fired by controls via FireConfigurationChanged. for (int pad = 0; pad < 2; ++pad) { LoadFromConfigDelegateArgsPerController controller = args.controller[pad]; if (WasConnected[pad] != controller.info.connected) { args.ConfigurationChanged = true; args.ConnectionsChanged = true; WasConnected[pad] = controller.info.connected; } if (LastInputs[pad] == null || !Enumerable.SequenceEqual(controller.inputs, LastInputs[pad])) { args.InputChanged = true; LastInputs[pad] = controller.inputs; } if (!controller.test_data.Equals(LastTestData[pad])) { args.TestDataChanged = true; LastTestData[pad] = controller.test_data; } } // Only fire the delegate if something has actually changed. if (args.ConfigurationChanged || args.InputChanged || args.TestDataChanged) { ConfigurationChanged?.Invoke(args); } }
// If the user selects "Both", or connects a second pad while on "Both", both pads need // to have the same configuration, since we're configuring them together. Check if the // configuration is out of sync, and ask the user before syncing them up so we don't // clobber P2's configuration if this wasn't intended. // // If the user cancels, change the pad selection to P1 so we don't clobber P2. private void CheckConfiguringBothPads(LoadFromConfigDelegateArgs args) { // Check if we're actually in "Both" mode with two controllers connected. If not, // we don't have to do anything. bool Pad1Connected = args.controller[0].info.connected; bool Pad2Connected = args.controller[1].info.connected; if (ActivePad.selectedPad != ActivePad.SelectedPad.Both || !Pad1Connected || !Pad2Connected) { return; } // If the two pads have the same configuration, there's nothing to do. SMX.SMXConfig config1 = args.controller[0].config; SMX.SMXConfig config2 = args.controller[1].config; if (ConfigurationsSynced(config1, config2)) { return; } string messageBoxText = "The two pads have different settings. Do you want to " + "match P2 settings to P1 and configure both pads together? (This won't affect panel colors.)"; MessageBoxResult result = MessageBox.Show(messageBoxText, "StepManiaX", MessageBoxButton.YesNo, MessageBoxImage.None); if (result == MessageBoxResult.Yes) { SyncP2FromP1(config1, config2); return; } else { // Switch to P1. ActivePad.selectedPad = ActivePad.SelectedPad.P1; RefreshConnectedPadList(CurrentSMXDevice.singleton.GetState()); } }
private void ConfigurationChanged(LoadFromConfigDelegateArgs args) { Callback(args); }
private void Refresh(LoadFromConfigDelegateArgs args) { // First, make sure a valid panel is selected. SMX.SMXConfig config = ActivePad.GetFirstActivePadConfig(args); SelectValidPanel(config); RefreshSelectedPanel(); // Make sure SetShowAllLights is disabled if the controller is disconnected, since // we can miss mouse up events. bool EitherControllerConnected = args.controller[0].info.connected || args.controller[1].info.connected; if (!EitherControllerConnected) { SetShowAllLights?.Invoke(false); } P1Diagnostics.Visibility = args.controller[0].info.connected? Visibility.Visible:Visibility.Collapsed; P2Diagnostics.Visibility = args.controller[1].info.connected? Visibility.Visible:Visibility.Collapsed; // Update the displayed DIP switch icons. int SelectedPad = SelectedPanel < 9? 0:1; int PanelIndex = SelectedPanel % 9; int dip = args.controller[SelectedPad].test_data.iDIPSwitchPerPanel[PanelIndex]; CurrentDIP.Frame = dip; ExpectedDIP.Frame = PanelIndex; // Show or hide the sensor error text. bool AnySensorsNotResponding = false, HaveIncorrectSensorDIP = false; if (args.controller[SelectedPad].test_data.bHaveDataFromPanel[PanelIndex]) { AnySensorsNotResponding = args.controller[SelectedPad].test_data.AnySensorsOnPanelNotResponding(PanelIndex); // Don't show both warnings. HaveIncorrectSensorDIP = !AnySensorsNotResponding && args.controller[SelectedPad].test_data.AnyBadJumpersOnPanel(PanelIndex); } NoResponseFromSensors.Visibility = AnySensorsNotResponding? Visibility.Visible:Visibility.Collapsed; BadSensorDIPSwitches.Visibility = HaveIncorrectSensorDIP? Visibility.Visible:Visibility.Collapsed; // Adjust the DIP labels to match the PCB. bool DIPLabelsOnLeft = config.masterVersion < 4; DIPLabelRight.Visibility = DIPLabelsOnLeft? Visibility.Collapsed:Visibility.Visible; DIPLabelLeft.Visibility = DIPLabelsOnLeft? Visibility.Visible:Visibility.Collapsed; // Update the level bar from the test mode data for the selected panel. for (int sensor = 0; sensor < 4; ++sensor) { var controllerData = args.controller[SelectedPad]; Int16 value = controllerData.test_data.sensorLevel[PanelIndex * 4 + sensor]; if (GetTestMode() == SMX.SMX.SensorTestMode.Noise) { // In noise mode, we receive standard deviation values squared. Display the square // root, since the panels don't do this for us. This makes the numbers different // than the configured value (square it to convert back), but without this we display // a bunch of 4 and 5-digit numbers that are too hard to read. value = (Int16)Math.Sqrt(value); } LevelBarText[sensor].Visibility = Visibility.Visible; if (!args.controller[SelectedPad].test_data.bHaveDataFromPanel[PanelIndex]) { LevelBars[sensor].Value = 0; LevelBarText[sensor].Visibility = Visibility.Hidden; LevelBarText[sensor].Content = "-"; LevelBars[sensor].Error = false; } else if (args.controller[SelectedPad].test_data.bBadSensorInput[PanelIndex * 4 + sensor]) { LevelBars[sensor].Value = 0; LevelBarText[sensor].Content = "!"; LevelBars[sensor].Error = true; } else { // Very slightly negative values happen due to noise. They don't indicate a // problem, but they're confusing in the UI, so clamp them away. if (value < 0 && value >= -10) { value = 0; } // Scale differently depending on if this is an FSR panel or a load cell panel. bool isFSR = controllerData.config.masterVersion >= 4 && (controllerData.config.configFlags & SMX.SMXConfigFlags.PlatformFlags_FSR) != 0; if (isFSR) { value >>= 2; } float maxValue = isFSR? 250:500; LevelBars[sensor].Value = value / maxValue; LevelBarText[sensor].Content = value; LevelBars[sensor].Error = false; } } NoResponseFromPanel.Visibility = Visibility.Collapsed; CurrentDIPGroup.Visibility = Visibility.Visible; if (!args.controller[SelectedPad].test_data.bHaveDataFromPanel[PanelIndex]) { NoResponseFromPanel.Visibility = Visibility.Visible; NoResponseFromSensors.Visibility = Visibility.Collapsed; CurrentDIPGroup.Visibility = Visibility.Hidden; return; } }
public MainWindow() { InitializeComponent(); onConfigChange = new OnConfigChange(this, delegate(LoadFromConfigDelegateArgs args) { LoadUIFromConfig(args); }); // If we're controlling GIF animations and the firmware doesn't support // doing animations internally, confirm exiting, since you can minimize // 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) { LoadFromConfigDelegateArgs args = CurrentSMXDevice.singleton.GetState(); // Don't use ActivePads here. Even if P1 is selected for configuration, // we can still be controlling animations for P2, so check both connected // pads. bool shouldConfirmExit = false; for (int pad = 0; pad < 2; ++pad) { SMX.SMXConfig config; if (!SMX.SMX.GetConfig(pad, out config)) { continue; } // If the firmware is version 4 or higher, it supports animations directly. // The user can upload GIF animations and doesn't need to leave us running // for them to work. You can still use this tool to drive animations, but // don't confirm exiting. if (config.masterVersion >= 4) { continue; } // If AutoLightingUsePressedAnimations isn't set, the panel is using step // coloring instead of pressed animations. All firmwares support this. // Don't confirm exiting for this mode. if ((config.configFlags & SMX.SMXConfigFlags.AutoLightingUsePressedAnimations) == 0) { continue; } shouldConfirmExit = true; } if (!shouldConfirmExit) { return; } MessageBoxResult result = MessageBox.Show( "Close StepManiaX configuration?\n\n" + "GIF animations will keep playing if the application is minimized.", "StepManiaX", System.Windows.MessageBoxButton.YesNo); if (result == MessageBoxResult.No) { e.Cancel = true; } }; }
private void LoadUIFromConfig(LoadFromConfigDelegateArgs args) { // Refresh whether LightsAnimation_SetAuto should be enabled. SMX.SMXConfig firstConfig = ActivePad.GetFirstActivePadConfig(); bool usePressedAnimationsEnabled = (firstConfig.configFlags & SMX.SMXConfigFlags.AutoLightingUsePressedAnimations) != 0; SMX.SMX.LightsAnimation_SetAuto(usePressedAnimationsEnabled); 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; EnableCenterTopSensorCheckbox.Visibility = P1_Floor.Visibility = P2_Floor.Visibility = 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()) { SMX.SMXConfig config = activePad.Item2; // If SMXConfigFlags_AutoLightingUsePressedAnimations is set, show the GIF UI. // 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; // Tell the color mode buttons which one is selected, to set the button highlight. PanelColorsButton.Selected = !usePressedAnimations; GIFAnimationsButton.Selected = usePressedAnimations; break; } RefreshConnectedPadList(args); RefreshUploadPadText(args); RefreshSelectedColorPicker(); // If a device has connected or disconnected, refresh the displayed threshold // sliders. Don't do this otherwise, or we'll do this when the sliders are // dragged. if (args.ConnectionsChanged) { CreateThresholdSliders(); } // Show the threshold warning explanation if any panels are showing the threshold warning icon. bool ShowThresholdWarningText = false; foreach (Tuple <int, SMX.SMXConfig> activePad in ActivePad.ActivePads()) { SMX.SMXConfig config = activePad.Item2; for (int panelIdx = 0; panelIdx < 9; ++panelIdx) { for (int sensor = 0; sensor < 4; ++sensor) { if (config.ShowThresholdWarning(panelIdx, sensor)) { ShowThresholdWarningText = true; } } } } 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. if (args.ConfigurationChanged) { CheckConfiguringBothPads(args); } }
private void Refresh(LoadFromConfigDelegateArgs args) { P1Diagnostics.Visibility = args.controller[0].info.connected? Visibility.Visible:Visibility.Collapsed; P2Diagnostics.Visibility = args.controller[1].info.connected? Visibility.Visible:Visibility.Collapsed; // Update the displayed DIP switch icons. int SelectedPad = SelectedPanel < 9? 0:1; int PanelIndex = SelectedPanel % 9; int dip = args.controller[SelectedPad].test_data.iDIPSwitchPerPanel[PanelIndex]; CurrentDIP.Frame = dip; ExpectedDIP.Frame = PanelIndex; // Show or hide the sensor error text. bool AnySensorsNotResponding = false; if (args.controller[SelectedPad].test_data.bHaveDataFromPanel[PanelIndex]) { AnySensorsNotResponding = args.controller[SelectedPad].test_data.AnySensorsOnPanelNotResponding(PanelIndex); } NoResponseFromSensors.Visibility = AnySensorsNotResponding? Visibility.Visible:Visibility.Collapsed; // Update the level bar from the test mode data for the selected panel. for (int sensor = 0; sensor < 4; ++sensor) { Int16 value = args.controller[SelectedPad].test_data.sensorLevel[PanelIndex * 4 + sensor]; if (GetTestMode() == SMX.SMX.SensorTestMode.Noise) { // In noise mode, we receive standard deviation values squared. Display the square // root, since the panels don't do this for us. This makes the numbers different // than the configured value (square it to convert back), but without this we display // a bunch of 4 and 5-digit numbers that are too hard to read. value = (Int16)Math.Sqrt(value); } LevelBarText[sensor].Visibility = Visibility.Visible; if (!args.controller[SelectedPad].test_data.bHaveDataFromPanel[PanelIndex]) { LevelBars[sensor].Value = 0; LevelBarText[sensor].Visibility = Visibility.Hidden; LevelBarText[sensor].Content = "-"; LevelBars[sensor].Error = false; } else if (args.controller[SelectedPad].test_data.bBadSensorInput[PanelIndex * 4 + sensor]) { LevelBars[sensor].Value = 0; LevelBarText[sensor].Content = "!"; LevelBars[sensor].Error = true; } else { // Very slightly negative values happen due to noise. They don't indicate a // problem, but they're confusing in the UI, so clamp them away. if (value < 0 && value >= -10) { value = 0; } LevelBars[sensor].Value = value / 500.0; LevelBarText[sensor].Content = value; LevelBars[sensor].Error = false; } } if (!args.controller[SelectedPad].test_data.bHaveDataFromPanel[PanelIndex]) { NoResponseFromPanel.Visibility = Visibility.Visible; NoResponseFromSensors.Visibility = Visibility.Collapsed; return; } NoResponseFromPanel.Visibility = Visibility.Collapsed; }
// Return true if this panel is enabled and should be selectable. public abstract bool isEnabled(LoadFromConfigDelegateArgs args);