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 override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            LevelBars    = new LevelBar[4];
            LevelBars[0] = Template.FindName("SensorBar1", this) as LevelBar;
            LevelBars[1] = Template.FindName("SensorBar2", this) as LevelBar;
            LevelBars[2] = Template.FindName("SensorBar3", this) as LevelBar;
            LevelBars[3] = Template.FindName("SensorBar4", this) as LevelBar;

            LevelBarText    = new Label[4];
            LevelBarText[0] = Template.FindName("SensorBarLevel1", this) as Label;
            LevelBarText[1] = Template.FindName("SensorBarLevel2", this) as Label;
            LevelBarText[2] = Template.FindName("SensorBarLevel3", this) as Label;
            LevelBarText[3] = Template.FindName("SensorBarLevel4", this) as Label;

            DiagnosticMode        = Template.FindName("DiagnosticMode", this) as ComboBox;
            CurrentDIP            = Template.FindName("CurrentDIP", this) as FrameImage;
            ExpectedDIP           = Template.FindName("ExpectedDIP", this) as FrameImage;
            NoResponseFromPanel   = Template.FindName("NoResponseFromPanel", this) as FrameworkElement;
            NoResponseFromSensors = Template.FindName("NoResponseFromSensors", this) as FrameworkElement;
            P1Diagnostics         = Template.FindName("P1Diagnostics", this) as FrameworkElement;
            P2Diagnostics         = Template.FindName("P2Diagnostics", this) as FrameworkElement;

            // Only show the mode dropdown in debug mode.  In regular use, just show calibrated values.
            DiagnosticMode.Visibility = Helpers.GetDebug()? Visibility.Visible:Visibility.Collapsed;

            Button Recalibrate = Template.FindName("Recalibrate", this) as Button;

            Recalibrate.Click += delegate(object sender, RoutedEventArgs e)
            {
                for (int pad = 0; pad < 2; ++pad)
                {
                    SMX.SMX.ForceRecalibration(pad);
                }
            };

            Button LightAll = Template.FindName("LightAll", this) as Button;

            LightAll.PreviewMouseDown += delegate(object sender, MouseButtonEventArgs e)
            {
                SetShowAllLights?.Invoke(true);
            };
            LightAll.PreviewMouseUp += delegate(object sender, MouseButtonEventArgs e)
            {
                SetShowAllLights?.Invoke(false);
            };

            // Update the test mode when the dropdown is changed.
            DiagnosticMode.AddHandler(ComboBox.SelectionChangedEvent, new RoutedEventHandler(delegate(object sender, RoutedEventArgs e)
            {
                for (int pad = 0; pad < 2; ++pad)
                {
                    SMX.SMX.SetTestMode(pad, GetTestMode());
                }
            }));

            OnConfigChange onConfigChange;

            onConfigChange = new OnConfigChange(this, delegate(LoadFromConfigDelegateArgs args) {
                Refresh(args);
            });
            onConfigChange.RefreshOnTestDataChange = true;

            Loaded += delegate(object sender, RoutedEventArgs e)
            {
                for (int pad = 0; pad < 2; ++pad)
                {
                    SMX.SMX.SetTestMode(pad, GetTestMode());
                }
            };

            Unloaded += delegate(object sender, RoutedEventArgs e)
            {
                for (int pad = 0; pad < 2; ++pad)
                {
                    SMX.SMX.SetTestMode(pad, SMX.SMX.SensorTestMode.Off);
                }
            };
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            LevelBars    = new LevelBar[4];
            LevelBars[0] = Template.FindName("SensorBar1", this) as LevelBar;
            LevelBars[1] = Template.FindName("SensorBar2", this) as LevelBar;
            LevelBars[2] = Template.FindName("SensorBar3", this) as LevelBar;
            LevelBars[3] = Template.FindName("SensorBar4", this) as LevelBar;

            LevelBarText    = new Label[4];
            LevelBarText[0] = Template.FindName("SensorBarLevel1", this) as Label;
            LevelBarText[1] = Template.FindName("SensorBarLevel2", this) as Label;
            LevelBarText[2] = Template.FindName("SensorBarLevel3", this) as Label;
            LevelBarText[3] = Template.FindName("SensorBarLevel4", this) as Label;

            DiagnosticMode        = Template.FindName("DiagnosticMode", this) as ComboBox;
            CurrentDIPGroup       = Template.FindName("CurrentDIPGroup", this) as Panel;
            CurrentDIP            = Template.FindName("CurrentDIP", this) as FrameImage;
            ExpectedDIP           = Template.FindName("ExpectedDIP", this) as FrameImage;
            NoResponseFromPanel   = Template.FindName("NoResponseFromPanel", this) as FrameworkElement;
            NoResponseFromSensors = Template.FindName("NoResponseFromSensors", this) as FrameworkElement;
            BadSensorDIPSwitches  = Template.FindName("BadSensorDIPSwitches", this) as FrameworkElement;
            P1Diagnostics         = Template.FindName("P1Diagnostics", this) as FrameworkElement;
            P2Diagnostics         = Template.FindName("P2Diagnostics", this) as FrameworkElement;

            DIPLabelRight = Template.FindName("DIPLabelRight", this) as FrameworkElement;
            DIPLabelLeft  = Template.FindName("DIPLabelLeft", this) as FrameworkElement;

            Button Recalibrate = Template.FindName("Recalibrate", this) as Button;

            Recalibrate.Click += delegate(object sender, RoutedEventArgs e)
            {
                for (int pad = 0; pad < 2; ++pad)
                {
                    SMX.SMX.ForceRecalibration(pad);
                }
            };

            // Note that we won't get a MouseUp if the display is hidden due to a controller
            // disconnection while the mouse is held.  We handle this in Refresh().
            Button LightAll = Template.FindName("LightAll", this) as Button;

            LightAll.PreviewMouseDown += delegate(object sender, MouseButtonEventArgs e)
            {
                SetShowAllLights?.Invoke(true);
            };
            LightAll.PreviewMouseUp += delegate(object sender, MouseButtonEventArgs e)
            {
                SetShowAllLights?.Invoke(false);
            };

            // Update the test mode when the dropdown is changed.
            DiagnosticMode.AddHandler(ComboBox.SelectionChangedEvent, new RoutedEventHandler(delegate(object sender, RoutedEventArgs e)
            {
                for (int pad = 0; pad < 2; ++pad)
                {
                    SMX.SMX.SetSensorTestMode(pad, GetTestMode());
                }
            }));

            OnConfigChange onConfigChange;

            onConfigChange = new OnConfigChange(this, delegate(LoadFromConfigDelegateArgs args) {
                Refresh(args);
            });
            onConfigChange.RefreshOnTestDataChange = true;

            Loaded += delegate(object sender, RoutedEventArgs e)
            {
                for (int pad = 0; pad < 2; ++pad)
                {
                    SMX.SMX.SetSensorTestMode(pad, GetTestMode());
                }
            };

            Unloaded += delegate(object sender, RoutedEventArgs e)
            {
                for (int pad = 0; pad < 2; ++pad)
                {
                    SMX.SMX.SetSensorTestMode(pad, SMX.SMX.SensorTestMode.Off);
                }
            };
        }