Skip to content

File RadioButtonControl.xaml.cs

File List > PGRControls > RadioButtonControl.xaml.cs

Go to the documentation of this file

//=============================================================================
// Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR)
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================

using SpinnakerNET.GenApi;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Security;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace SpinnakerNET.GUI
{
    namespace WPFControls
    {



        public sealed partial class RadioButtonControl : BaseClass
        {
#region FIELDS
            private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(RadioButtonControl));
            private IEnum _enumNode;
            private Dictionary<string, long>_entryTable;
            private Dictionary<string, RadioButton>_buttonTable;
            private bool _disposed = false;

            // GenICam callback update thread
            BackgroundWorker _updateWorker;
#endregion

#region Constructor
            public RadioButtonControl()
            {
                InitializeComponent();
                _entryTable = new Dictionary<string, long>();
                _buttonTable = new Dictionary<string, RadioButton>();

                _updateWorker = new BackgroundWorker();
                _updateWorker.DoWork += _updateWorker_DoWork;
                _updateWorker.RunWorkerCompleted += _updateWorker_RunWorkerCompleted;
            }

            ~RadioButtonControl()
            {
                Disconnect();
            }

            internal RadioButtonControl(RadioButtonControl originalControl)
            {
                InitializeComponent();
                _entryTable = new Dictionary<string, long>();
                _buttonTable = new Dictionary<string, RadioButton>();

                _updateWorker = new BackgroundWorker();
                _updateWorker.DoWork += _updateWorker_DoWork;
                _updateWorker.RunWorkerCompleted += _updateWorker_RunWorkerCompleted;

                // Common Properties
                this.SetMapper(originalControl.GetMapper());
                this.Connect(
                    originalControl.NodeMap, originalControl.GetNodeToControl(), originalControl.GetControlNameLabel());
                this.SetNameLabelBoldness(originalControl.NameLabelBoldness);
                this.SetVisibility(originalControl.Visibility);
                this.SetControlID(originalControl.ControlID);
                this.SetMin(originalControl.GetMin());
                this.SetMax(originalControl.GetMax());
                this.SetControlNameLabel(originalControl.ControlNameLabel);
                this.SetNameLabelVisibility(originalControl.GetNameLabelVisibility());
                this.SetNameLabelBoldness(originalControl.GetNameLabelBoldness());
                try
                {
                    this.SetToolTip(originalControl.GetToolTip());
                }
                catch (System.Exception /*ex*/)
                {
                }
                this.SetMaximumControlSize(originalControl.GetMaximumControlSize());
                this.SetMinimumControlSize(originalControl.GetMinimumControlSize());
                this.SetControlHeight(originalControl.GetControlHeight());
                this.SetControlWidth(originalControl.GetControlWidth());
                this.SetRefreshTime(originalControl.GetRefreshTime());
                this.SetMargin(originalControl.GetMargin());
            }

            protected override void Dispose(bool disposing)
            {
                if (!_disposed)
                {
                    if (disposing)
                    {
                    }

                    // Consider GenICam callbacks as unmanaged resource
                    Disconnect();
                    _disposed = true;
                }
                // Call Dispose in the base class.
                base.Dispose(disposing);
            }
#endregion

#region ICAMERACONTROL
            public override void Connect(INodeMap nodemap, string nodename, string namelabel = "")
            {
                if (nodename.Length != 0 && nodemap != null)
                {
                    _initializing = true;

                    // Acquire device serial number
                    if (string.IsNullOrWhiteSpace(_serialNumber))
                    {
                        _serialNumber = RetrieveSerialNumber(nodemap);
                    }

                    // Acquire device model name
                    if (string.IsNullOrWhiteSpace(_deviceModelName))
                    {
                        _deviceModelName = RetrieveModelName(nodemap);
                    }

                    try
                    {
                        this._nodeMap = nodemap;
                        this._propertyToControl = nodename;

                        _enumNode = nodemap.GetNode<IEnum>(this._propertyToControl);

                        if (_enumNode == null)
                        {
                            throw new Exception("Feature not found");
                        }

                        this._nodeType = _enumNode.GetType();

                        if (namelabel.Length > 0)
                        {
                            SetControlNameLabel(namelabel);
                            SetNameLabelVisibility(System.Windows.Visibility.Visible);
                        }
                        else
                        {
                            SetControlNameLabel(_enumNode.DisplayName);
                        }

                        _enumNode.Updated += new NodeEventHandler(enumNode_Updated);

                        if (_enumNode != null && _enumNode.IsReadable)
                        {
                            CreateRadioButtons();
                        }

                        _featureAvailable = _enumNode.IsImplemented;

                        RegisterInterfaceEvents();
                    }
                    catch (System.Exception ex)
                    {
                        _featureAvailable = false;
                        log.Debug(
                            string.Format(
                                "{1}Problem accessing {0} node. {2}",
                                this._propertyToControl,
                                FormattedSerialNumber,
                                ex.Message),
                            ex);
                        throw new Exception(string.Format(
                            "{2}Problem accessing {0} node. {1}",
                            this._propertyToControl,
                            ex.Message,
                            FormattedSerialNumber));
                    }
                    finally
                    {
                        _initializing = false;
                    }
                }
                else
                {
                }
            }

            public override void Disconnect()
            {
                try
                {
                    if (_enumNode != null)
                    {
                        _enumNode.Updated -= new NodeEventHandler(enumNode_Updated);
                        _enumNode = null;
                    }
                    _mapper = null;
                    base.Disconnect();
                }
                catch (System.Exception /*ex*/)
                {
                }
            }

            public override void SetRefreshTime(int seconds)
            {
                this._refreshTime = seconds;

                // Start timer if an valid refresh time was provided
                if (this._refreshTime > 0)
                {
                    try
                    {
                        _timer = new System.Windows.Forms.Timer();
                        _timer.Interval = this._refreshTime;
                        _timer.Tick += new EventHandler(timer_Tick);
                        _timer.Start();
                    }
                    catch (System.Exception /*ex*/)
                    {
                    }
                }
            }

            public override void Refresh()
            {
                try
                {
                    _initializing = true;

                    _enumNode = _nodeMap.GetNode<IEnum>(this._propertyToControl);

                    if (_enumNode != null && _enumNode.IsReadable)
                    {
                        rootPanel.IsEnabled = true;
                        CreateRadioButtons();
                    }
                    else
                    {
                        rootPanel.IsEnabled = false;
                    }
                }
                catch (System.Exception /*ex*/)
                {
                }
                finally
                {
                    _initializing = false;
                }
            }

#endregion

#region EVENT_HANDLERS
            void timer_Tick(object sender, EventArgs e)
            {
                try
                {
                    Refresh();
                }
                catch (System.Exception /*ex*/)
                {
                    Debug.WriteLine(string.Format("Problem retrieving new value from {0} node", _propertyToControl));
                }
            }

            private void RadioButton_Click(object sender, RoutedEventArgs e)
            {
                if (_initializing)
                {
                    return;
                }

                if (_enumNode != null && _enumNode.IsWritable)
                {
                    RadioButton button = (RadioButton) sender;
                    long buttonValue = 0;
                    if (_entryTable.TryGetValue(button.Content.ToString(), out buttonValue))
                    {
                        // Unchecked all buttons
                        foreach(KeyValuePair<string, RadioButton>pair in _buttonTable)
                        {
                            pair.Value.IsChecked = false;
                        }

                        button.IsChecked = true;

                        //_skipCallback = true;
                        _enumNode.Value = buttonValue;
                        //_skipCallback = false;
                    }
                }
            }

            [HandleProcessCorruptedStateExceptions]
            [SecurityCritical]
            private void
            _updateWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                try
                {
                    _isUpdating = true;
                    _initializing = true;

                    INode node = e.Result as INode;
                    NodeStatus currentNodeStatus = new NodeStatus(node);
                    if (currentNodeStatus.ExceptionObject != null)
                    {
                        return;
                    }

                    string logMessage =
                        string.Format("Spinnaker Callback: Feature=\"{0}\"", currentNodeStatus.NodeName);

                    logMessage += string.Format(", Value=\"{0}\"", currentNodeStatus.CurrentStringValue);

                    LogNodeCallback(log, currentNodeStatus.NodeName, logMessage);

                    if (currentNodeStatus.IsReadable)
                    {
                        rootPanel.IsEnabled = true;
                        CreateRadioButtons();
                    }
                    else
                    {
                        rootPanel.IsEnabled = false;
                    }
                }
                catch (System.Exception ex)
                {
                    log.Debug(
                        string.Format(
                            "{1}Problem updating control for {0} node", _propertyToControl, FormattedSerialNumber),
                        ex);
                }
                finally
                {
                    _initializing = false;
                    _isUpdating = false;
                }

                if (!Dispatcher.CheckAccess())
                {
                    Dispatcher.BeginInvoke((Action)(() => { Refresh(); }), DispatcherPriority.Background, null);
                }
                else
                {
                    Refresh();
                }
            }

            private void _updateWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                // Limit the refresh rate
                Thread.Sleep(1000 / _maxRefreshRateHz);

                INode node = e.Argument as INode;
                e.Result = node;
            }

            void enumNode_Updated(INode node)
            {
                if (_nodeMap == null)
                {
                    return;
                }

                if (_updateWorker.IsBusy || _isUpdating)
                {
                    return;
                }

                if (!IsVisible)
                {
                    return;
                }

                _updateWorker.RunWorkerAsync(node);
            }
#endregion

#region HELPER
            void CreateRadioButtons()
            {
                string[] symbolics = _enumNode.Symbolics;

                _entryTable.Clear();
                _buttonTable.Clear();
                rootPanel.Children.Clear();

                for (int i = 0; i < _enumNode.Entries.Length; i++)
                {
                    // Keep track of all possible entries and their Node value
                    _entryTable.Add(_enumNode.Entries[i], _enumNode.Entries[i].Value);
                }

                foreach(var s in _enumNode.Entries)
                {

                    RadioButton button = new RadioButton();
                    button.Content = s.Symbolic;
                    if (s.ToolTip != null && s.ToolTip.Length > 0)
                    {
                        button.ToolTip = s.ToolTip;
                    }
                    button.Click += new RoutedEventHandler(RadioButton_Click);
                    _buttonTable.Add(s, button);
                    rootPanel.Children.Add(button);

                    // Entry could be unavailable on device
                    // Let's check Symbolic array to verify
                    if (symbolics.Contains(s.Symbolic))
                    {
                        button.IsEnabled = true;
                    }
                    else
                    {
                        button.IsEnabled = false;
                    }
                }

                // Entries and Symbolic sometimes do not contain
                // same number of items. As a result, we need to
                // search symbolic list to find corresponding index
                // for current node value
                int index = 0;
                foreach(string s in symbolics)
                {
                    if (_enumNode.Value.String.Equals(s))
                    {
                        RadioButton tempButton = new RadioButton();
                        if (_buttonTable.TryGetValue(s, out tempButton))
                        {
                            tempButton.IsChecked = true;
                        }

                        break;
                    }
                    index++;
                }
            }
#endregion

#region ORIENTATION_CONTROL
            public override Orientation ContentOrientation
            {
                get
                {
                    return rootLayout.Orientation;
                }
                set
                {
                    rootLayout.Orientation = value;
                }
            }

            public void SetContentOrientation(Orientation newOrientation)
            {
                this.ContentOrientation = newOrientation;
            }

            public Orientation GetContentOrientation()
            {
                return this.ContentOrientation;
            }
#endregion
        }

    }
}