Skip to content

File SelectorControl.xaml.cs

File List > PGRControls > SelectorControl.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 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 SpinnakerNET.GenApi;
using System.ComponentModel;
using System.Windows.Threading;

namespace SpinnakerNET.GUI
{
    namespace WPFControls
    {


        public sealed partial class SelectorControl : BaseClass
        {
#region FIELDS
            private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(SelectorControl));
            private IBool _selectorEnableNode; // ChunkEnable
            private IEnum _selectorEntryNode;  // ChunkSelector"
            private INodeMap _nodemap;
            private List<CheckBox>_checkboxes;
            private bool _skipCallback = false;
            private bool _disposed = false;

            // GenICam callback update thread
            BackgroundWorker _selectorEntryNodeUpdateWorker;
            BackgroundWorker _selectorEnableNodeUpdateWorker;

            public IBool SelectorEnable
            {
                get
                {
                    return _selectorEnableNode;
                }
            }

            public IEnum SelectorEntry
            {
                get
                {
                    return _selectorEntryNode;
                }
            }
#endregion

            public SelectorControl()
            {
                InitializeComponent();

                _selectorEntryNodeUpdateWorker = new BackgroundWorker();
                _selectorEntryNodeUpdateWorker.DoWork += selectorEntryNodeUpdateWorker_DoWork;

                _selectorEnableNodeUpdateWorker = new BackgroundWorker();
                _selectorEnableNodeUpdateWorker.DoWork += selectorEnableNodeUpdateWorker_DoWork;
                _selectorEnableNodeUpdateWorker.RunWorkerCompleted += selectorEnableNodeUpdateWorker_RunWorkerCompleted;
            }

            ~SelectorControl()
            {
                Disconnect();
            }

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

                    _disposed = true;
                }
                // Call Dispose in the base class.
                base.Dispose(disposing);
            }

#region ICAMERACONTROL_INTERFACE
            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()
            {
                UpdateControlStatus();
            }

            public override System.Windows.Visibility GetNameLabelVisibility()
            {
                if (controlLabel.Content.ToString().Length > 0)
                {
                    return System.Windows.Visibility.Visible;
                }
                else
                {
                    return System.Windows.Visibility.Collapsed;
                }
            }

            public override void Connect(INodeMap nodemap, string nodename, string namelabel = "")
            {
                throw new NotImplementedException(
                    string.Format("See \"Connect(string EnableNode, string EntryNode, NodeMap nodemap)\""));
            }

            public void Connect(string EnableNode, string EntryNode, INodeMap nodemap)
            {
                if (nodemap == null)
                {
                    log.Error("Nodemap object is null");
                    throw new ArgumentNullException("Nodemap object is null");
                }

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

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

                if (EnableNode == null || EnableNode.Length == 0)
                {
                    log.Error(string.Format(
                        "{0}Selector Enable Node string can not be null nor empty", FormattedSerialNumber));
                    throw new ArgumentNullException("Selector Enable Node string can not be null nor empty");
                }

                if (EntryNode == null || EntryNode.Length == 0)
                {
                    log.Error(string.Format(
                        "{0}Selector Entry Node string can not be null nor empty", FormattedSerialNumber));
                    throw new ArgumentNullException("Selector Entry Node string can not be null nor empty");
                }

                try
                {
                    _nodemap = nodemap;

                    // connect to selector enable node
                    _selectorEnableNode = nodemap.GetNode<BoolNode>(EnableNode);

                    if (_selectorEnableNode == null || !_selectorEnableNode.IsImplemented)
                    {
                        _featureAvailable = false;
                        log.Debug(string.Format("{1}{0} is not implemented.", EnableNode, FormattedSerialNumber));
                        throw new InvalidOperationException(
                            string.Format("{1}{0} is not implemented.", EnableNode, FormattedSerialNumber));
                    }

                    // connect to selector entry node
                    _selectorEntryNode = nodemap.GetNode<Enumeration>(EntryNode);

                    if (_selectorEntryNode == null || !_selectorEntryNode.IsImplemented)
                    {
                        _featureAvailable = false;
                        log.Debug(string.Format("{1}{0} is not implemented.", EntryNode, FormattedSerialNumber));
                        throw new InvalidOperationException(
                            string.Format("{1}{0} is not implemented.", EntryNode, FormattedSerialNumber));
                    }
                }
                catch (Exception ex)
                {
                    log.Debug(
                        string.Format("{0}Problem creating Selector Control. {1}", FormattedSerialNumber, ex.Message));
                    throw new InvalidOperationException(
                        string.Format("{0}Problem creating Selector Control. {1}", FormattedSerialNumber, ex.Message));
                }

                try
                {
                    _featureAvailable = true;

                    // Set control label
                    controlLabel.Content = _selectorEnableNode.DisplayName;

                    expander.Header = _selectorEnableNode.DisplayName;

                    // Cache current enum value in entry node
                    long currentValue = _selectorEntryNode.Value.Int;

                    // Go through Selector Entries and create corresponding checkboxes
                    foreach(var node in _selectorEntryNode.Entries)
                    {

                        CheckBox checkbox = new CheckBox();
                        checkbox.Content = node.DisplayName;

                        if (_selectorEntryNode.IsWritable && _selectorEnableNode.IsReadable)
                        {
                            try
                            {
                                _selectorEntryNode.Value = node.Value;
                                checkbox.IsChecked = _selectorEnableNode.Value;
                            }
                            catch (System.Exception /*ex*/)
                            {
                                continue;
                            }
                        }

                        checkbox.Margin = new Thickness(3);

                        // Associate EnumEntryNode to Check box control
                        checkbox.Tag = node;

                        // Set tooltip
                        checkbox.ToolTip = string.Format("Toggle {0}", node.DisplayName);

                        // Register clicked event
                        checkbox.Click += new RoutedEventHandler(checkbox_Click);

                        // Add check box to stackpanel
                        itemContainer.Children.Add(checkbox);

                        if (_checkboxes == null)
                        {
                            _checkboxes = new List<CheckBox>();
                        }

                        // Keep track of the check box
                        _checkboxes.Add(checkbox);
                    }

                    RegisterInterfaceEvents();

                    // Re-select previous value
                    try
                    {
                        _selectorEntryNode.Value = currentValue;
                    }
                    catch (System.Exception ex)
                    {
                        log.Warn(string.Format("{0}Problem updating node value.", FormattedSerialNumber), ex);
                    }

                    // Register GenICam callbacks
                    _selectorEntryNode.Updated += selectorEntryNode_Updated;
                    _selectorEnableNode.Updated += selectorEnableNode_Updated;

                    _callbackRegistered = true;
                }
                catch (System.Exception ex)
                {
                    log.Error(string.Format("{0}Problem creating SelectorControl.", FormattedSerialNumber), ex);
                    throw new Exception(
                        string.Format("{1}Problem creating SelectorControl: {0}", ex.Message, FormattedSerialNumber));
                }
            }

            public override void Disconnect()
            {
                try
                {
                    if (_selectorEnableNode != null && _callbackRegistered)
                    {
                        _selectorEnableNode.Updated -= selectorEnableNode_Updated;
                    }

                    if (_selectorEntryNode != null && _callbackRegistered)
                    {
                        _selectorEntryNode.Updated -= selectorEntryNode_Updated;
                    }
                    _mapper = null;
                    base.Disconnect();
                }
                catch (System.Exception /*ex*/)
                {
                }
            }

            private void timer_Tick(object sender, EventArgs e)
            {
                Refresh();
            }
#endregion

            private void selectorEnableNodeUpdateWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                try
                {
                    _skipCallback = true;
                    NodeStatus currentNodeStatus = (NodeStatus) e.Result;

                    UpdateControlStatus(currentNodeStatus.CurrentNode);
                }
                catch (System.Exception /*ex*/)
                {
                }
                finally
                {
                    _skipCallback = false;
                }
            }

            private void selectorEntryNodeUpdateWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                INode node = e.Argument as INode;
                BackgroundWorker worker = sender as BackgroundWorker;
                NodeStatus currentNodeStatus = new NodeStatus(node);

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

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

                LogNodeCallback(log, currentNodeStatus.NodeName, logMessage);

                e.Result = currentNodeStatus;
            }

            private void selectorEnableNodeUpdateWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                INode node = e.Argument as INode;
                BackgroundWorker worker = sender as BackgroundWorker;
                NodeStatus currentNodeStatus = new NodeStatus(node);

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

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

                LogNodeCallback(log, currentNodeStatus.NodeName, logMessage);

                e.Result = currentNodeStatus;
            }

            void selectorEnableNode_Updated(INode node)
            {
                if (_skipCallback)
                {
                    return;
                }

                if (_nodeMap == null)
                {
                    return;
                }

                if (_selectorEnableNodeUpdateWorker.IsBusy)
                {
                    return;
                }

                if (!IsVisible)
                {
                    return;
                }

                _selectorEnableNodeUpdateWorker.RunWorkerAsync(node);
            }

            void selectorEntryNode_Updated(INode node)
            {
                if (_skipCallback)
                {
                    return;
                }

                if (_nodeMap == null)
                {
                    return;
                }

                if (_selectorEntryNodeUpdateWorker.IsBusy)
                {
                    return;
                }

                if (!IsVisible)
                {
                    return;
                }

                _selectorEntryNodeUpdateWorker.RunWorkerAsync(node);
            }

            void checkbox_Click(object sender, RoutedEventArgs e)
            {
                _skipCallback = true;

                try
                {
                    CheckBox checkbox = sender as CheckBox;

                    if (checkbox == null)
                    {
                        throw new ArgumentNullException("Item is not a check box");
                    }

                    if (!_selectorEnableNode.IsWritable || !_selectorEntryNode.IsWritable)
                    {
                        return;
                    }

                    EnumEntry node = checkbox.Tag as EnumEntry;

                    _skipCallback = true;
                    _selectorEntryNode.Value = node.Value;

                    _selectorEnableNode.Value = (bool) checkbox.IsChecked;
                    _skipCallback = false;
                }
                catch (System.Exception /*ex*/)
                {
                }
                finally
                {
                    _skipCallback = false;
                }
            }

            void UpdateControlStatus(INode nodeChanged = null)
            {
                if (_selectorEnableNode.IsReadable && _selectorEntryNode.IsWritable && _selectorEntryNode.IsReadable)
                {
                    _skipCallback = true;
                    long currentValue = _selectorEntryNode.Value.Int;

                    if (nodeChanged != null)
                    {
                        foreach(CheckBox checkbox in _checkboxes)
                        {
                            EnumEntry entryNode = checkbox.Tag as EnumEntry;
                            if (entryNode != null && entryNode.Symbolic == _selectorEntryNode.Value.String)
                            {
                                // Found corresponding checkbox for this node
                                try
                                {
                                    checkbox.IsChecked = _selectorEnableNode.Value;
                                }
                                catch (System.Exception /*ex*/)
                                {
                                }

                                break;
                            }
                        }
                    }
                    else
                    {
                        // Update IsChecked Status
                        foreach(CheckBox checkbox in _checkboxes)
                        {
                            try
                            {
                                EnumEntry node = checkbox.Tag as EnumEntry;
                                _selectorEntryNode.Value = node.Value;
                                checkbox.IsChecked = _selectorEnableNode.Value;
                            }
                            catch (System.Exception /*ex*/)
                            {
                            }
                        }
                    }
                }
                _skipCallback = false;
            }
        }

    }
}