Skip to content

File CheckboxControl.xaml.cs

File List > PGRControls > CheckboxControl.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.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using SpinnakerNET.GenApi;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.ExceptionServices;
using System.Security;
using System.Threading;

namespace SpinnakerNET.GUI
{
    namespace WPFControls
    {


        public sealed partial class CheckboxControl : BaseClass
        {
            private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(CheckboxControl));
            private static readonly log4net.ILog analytics = log4net.LogManager.GetLogger("Analytics");

#region FIELDS
            private bool _labelAppearLeft = false;
            private bool _skipCallback = false;
            private bool _disposed = false;

            // GenICam callback update thread
            BackgroundWorker _updateWorker;

#endregion

#region PROPERTIES
            public bool LabelAppearLeft
            {
                get
                {
                    return _labelAppearLeft;
                }
                set
                {
                    _labelAppearLeft = value;
                    if (value)
                    {
                        this.checkbox.FlowDirection = FlowDirection.RightToLeft;
                    }
                    else
                    {
                        this.checkbox.FlowDirection = FlowDirection.LeftToRight;
                    }
                }
            }
#endregion

#region Constructor
            public CheckboxControl()
            {
                InitializeComponent();
                this.DataContext = this;
                _timer = new System.Windows.Forms.Timer();
                _dependencyStringList = new List<string>();
                _dependencyControlList = new CameraControlCollection();
                _updateWorker = new BackgroundWorker();
                _updateWorker.DoWork += _updateWorker_DoWork;
                _updateWorker.RunWorkerCompleted += _updateWorker_RunWorkerCompleted;
            }

            ~CheckboxControl()
            {
                Disconnect();
            }

            internal CheckboxControl(CheckboxControl originalControl)
            {
                InitializeComponent();
                this.DataContext = this;
                _timer = new System.Windows.Forms.Timer();
                _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.ControlVisibility);
                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)
                    {
                        Disconnect();
                    }

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

#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()
            {
                try
                {
                    _initializing = true;

                    if (_boolNode != null && _boolNode.IsReadable)
                    {
                        if (checkbox.IsChecked != _boolNode.Value)
                        {
                            _skipCallback = true;
                            checkbox.IsChecked = _boolNode.Value;
                            _skipCallback = false;
                        }
                    }
                    else
                    {
                        _skipCallback = true;
                        checkbox.IsChecked = null;
                        _skipCallback = false;
                    }

                    UpdateControlStatus();
                }
                catch (System.Exception /*ex*/)
                {
                    Debug.WriteLine(string.Format("Problem retrieving new value from {0} node", _propertyToControl));
                }
                finally
                {
                    _initializing = false;
                }
            }

            public override void SetControlNameLabel(string namelabel)
            {
                if (namelabel == null)
                {
                    return;
                }

                if (namelabel.Length > 0)
                {
                    ControlNameLabel = namelabel;
                }
                else
                {
                    if (_boolNode != null)
                    {
                        ControlNameLabel = _boolNode.DisplayName;
                    }
                }
            }

            public override void SetNameLabelVisibility(System.Windows.Visibility visibility)
            {
                if (visibility == System.Windows.Visibility.Collapsed || visibility == System.Windows.Visibility.Hidden)
                {
                    checkbox.Content = "";
                }
                else
                {
                    checkbox.Content = _controlNameLabel;
                }
            }

            public override System.Windows.Visibility GetNameLabelVisibility()
            {
                if (checkbox.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 = "")
            {
                if (nodename == string.Empty || nodemap == null)
                {
                    return;
                }

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

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

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

                try
                {
                    IValue node = nodemap.GetNode<IValue>(nodename);

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

                    if (node.GetType() != typeof (BoolNode))
                    {
                        _featureAvailable = false;
                        // Not a IBool node
                        log.Error(string.Format("{1}{0} is not a Bool node", nodename, FormattedSerialNumber));
                        throw new Exception(
                            string.Format("{1}{0} is not a Bool node", nodename, FormattedSerialNumber));
                    }

                    this._nodeType = node.GetType();

                    _boolNode = _nodeMap.GetNode<IBool>(nodename);

                    _featureAvailable = _boolNode.IsImplemented;

                    UpdateCheckBoxStatus(_boolNode);

                    // Update backstore
                    this.ControlNameLabel = namelabel;

                    // Push update to UI explicitly
                    SetControlNameLabel(ControlNameLabel);

                    SetToolTip(_boolNode.ToolTip.ToString());

                    UpdateControlStatus();

                    _boolNode.Updated += boolNode_Updated;

                    _callbackRegistered = true;

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

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

                    _boolNode = null;
                    _mapper = null;
                    _callbackRegistered = false;
                    base.Disconnect();
                }
                catch (System.Exception /*ex*/)
                {
                }
            }
#endregion

#region GENICAM_EVENTS
            [HandleProcessCorruptedStateExceptions]
            [SecurityCritical]
            private void
            _updateWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                bool refreshRequired = false;

                if (e.Cancelled)
                {
                    return;
                }

                if (_nodeMap == null)
                {
                    // Nodemap is no longer valid. Control must have been disconnected.
                    return;
                }

                try
                {
                    Dispatcher.Invoke(() => {
                        _initializing = true;
                        _skipCallback = true;
                        _isUpdating = 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);

                        ControlNameLabel = currentNodeStatus.NodeDisplayName;

                        // Update checkbox status
                        if (currentNodeStatus.IsReadable)
                        {
                            if (checkbox.IsChecked != currentNodeStatus.CurrentBooleanValue)
                            {
                                checkbox.Checked -= checkbox_Checked;
                                checkbox.IsChecked = currentNodeStatus.CurrentBooleanValue;
                                checkbox.Checked += checkbox_Checked;
                                refreshRequired = true;
                            }
                        }
                        else
                        {
                            checkbox.Checked -= checkbox_Checked;
                            checkbox.IsChecked = null;
                            checkbox.Checked += checkbox_Checked;
                            refreshRequired = true;
                        }

                        // Update UI Enabled Appearance
                        if (IsEditable && (!currentNodeStatus.IsImplemented || !currentNodeStatus.IsAvailable ||
                                           !currentNodeStatus.IsReadable))
                        {
                            IsEditable = false;
                            this.checkbox.IsEnabled = false;
                        }

                        // Node becomes non-writable
                        if (IsEditable && !currentNodeStatus.IsWritable)
                        {
                            IsEditable = false;
                            this.checkbox.IsEnabled = false;
                        }

                        // Node becomes writable
                        if (!IsEditable && currentNodeStatus.IsWritable)
                        {
                            IsEditable = true;

                            if (!this.checkbox.IsEnabled)
                            {
                                this.checkbox.IsEnabled = true;
                            }

                            refreshRequired = true;
                        }
                    });
                }
                catch (System.Exception ex)
                {
                    log.Debug(
                        string.Format(
                            "{1}Problem updating control for {0} node", _propertyToControl, FormattedSerialNumber),
                        ex);
                }
                finally
                {
                    _initializing = false;
                    _skipCallback = false;
                    _isUpdating = false;
                }

                if (!refreshRequired)
                {
                    return;
                }

                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;
            }

            private void boolNode_Updated(INode node)
            {
                if (_initializing || _skipCallback)
                {
                    return;
                }

                if (_nodeMap == null)
                {
                    return;
                }

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

                if (!IsVisible)
                {
                    return;
                }

                _updateWorker.RunWorkerAsync(node);
            }
#endregion

#region UI_UPDATE
            private void UpdateCheckBoxStatus(IBool node)
            {
                _initializing = true;

                try
                {
                    if (node != null && node.IsReadable)
                    {
                        _skipCallback = true;
                        checkbox.IsChecked = _boolNode.Value;
                        _skipCallback = false;
                    }
                }
                catch (System.Exception /*ex*/)
                {
                }
                finally
                {
                    _initializing = false;
                }
            }

            private void UpdateControlStatus()
            {
                if (_nodeMap == null)
                {
                    IsEditable = false;
                    this.checkbox.IsEnabled = false;
                    return;
                }

                try
                {
                    IValue node = _nodeMap.GetNode<IValue>(_propertyToControl);

                    if (node == null || !node.IsImplemented || !node.IsAvailable || !node.IsReadable)
                    {
                        IsEditable = false;
                        this.checkbox.IsEnabled = false;
                        return;
                    }

                    if (!node.IsWritable)
                    {
                        IsEditable = false;
                        this.checkbox.IsEnabled = false;
                        return;
                    }
                    else
                    {
                        IsEditable = true;

                        if (!this.checkbox.IsEnabled)
                        {
                            this.checkbox.IsEnabled = true;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Debug.Print("Problem updating Checkbox {0}: {1}", _propertyToControl, ex.Message);
                }
            }
#endregion

#region EVENT_HANDLER
            private void checkbox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                if (e.ClickCount == 2)
                {
                    e.Handled = true;
                }
            }

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

            private void checkbox_Checked(object sender, RoutedEventArgs e)
            {
                if (_initializing || _boolNode == null)
                {
                    return;
                }

                try
                {
                    _skipCallback = true;

                    // Log user initiated changes
                    LogNodeUpdateAction(log, _boolNode, "True");
                    AnalyticsNodeUpdateAction(analytics, _boolNode, "True");

                    _boolNode.Value = true;
                    _skipCallback = false;
                    // Update Dependency
                    if (_dependencyControlList != null && _dependencyControlList.Count > 0)
                    {
                        _dependencyControlList.Refresh();
                    }
                }
                catch (System.Exception /*ex*/)
                {
                    Debug.WriteLine("There was a problem writting to {0} node in PGRCheckBox", _propertyToControl);
                }
            }

            private void checkbox_Unchecked(object sender, RoutedEventArgs e)
            {
                if (_initializing || _boolNode == null)
                {
                    return;
                }

                try
                {
                    _skipCallback = true;

                    // Log user initiated changes
                    LogNodeUpdateAction(log, _boolNode, "False");
                    AnalyticsNodeUpdateAction(analytics, _boolNode, "False");

                    _boolNode.Value = false;
                    _skipCallback = false;
                    // Update Dependency
                    if (_dependencyControlList != null && _dependencyControlList.Count > 0)
                    {
                        _dependencyControlList.Refresh();
                    }
                }
                catch (System.Exception /*ex*/)
                {
                    Debug.WriteLine("There was a problem writting to {0} node in PGRCheckBox", _propertyToControl);
                }
            }
#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
        }

    }
}