Skip to content

File PropertyGridControl.xaml.cs

File List > PGRControls > PropertyGridControl.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.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Controls;
using System.Windows.Input;
using System.Diagnostics;
using SpinnakerNET.GenApi;
using System.Windows.Threading;
using System.Collections.Generic;

namespace SpinnakerNET.GUI
{
    namespace WPFControls
    {


        public partial class PropertyGridControl : System.Windows.Controls.UserControl, IDisposable
        {
#region Fields
            private uint m_serialNumber = 0;
            private PropertyGridInternal m_grid;
            private string _serialNumber;
            private bool _isConnected = false;
            private ManagedSystem _system;
            private InterfaceEventListener _eventListener;
            private List<IManagedInterface>_infList;
            private INodeMap _nodeMap;
            private bool _nodesExpanded = true;
            private bool disposed = false;
            private SortMethods _sortMethod = SortMethods.XML;
            private bool _enablePolling = false;
            private SpinnakerNET.GenApi.Visibility _visibility = GenApi.Visibility.Guru;
            private int _pollingFrequency = 5000;
            private bool _interfaceEventRegistered = false;

            PersistentSettings _settings;
            bool _applyingSettings = false;
            bool _initializing = false;
#endregion

#region Properties
            public SortMethods TreeViewSortMethod
            {
                get
                {
                    return GetSortMethod();
                }
                set
                {
                    SetSortMethod(value);

                    SaveSettings();
                }
            }

            public bool PollingEnabled
            {
                get
                {
                    return GetPollingStatus();
                }
                set
                {
                    SetPollingStatus(value);

                    SaveSettings();
                }
            }

            public int PollingFrequency
            {
                get
                {
                    return GetPollingFrequency();
                }
                set
                {
                    SetPollingFrequency(value);

                    SaveSettings();
                }
            }

            public SpinnakerNET.GenApi.Visibility FeatureVisibility
            {
                get
                {
                    return GetVisibility();
                }
                set
                {
                    SetVisibility(value);

                    SaveSettings();
                }
            }
#endregion

            public PropertyGridControl()
            {
                _initializing = true;
                InitializeComponent();
                _settings = PersistentSettings.Instance;
                _initializing = false;
            }

            void m_grid_OnSettingsChanged()
            {
                SaveSettings();
            }

            ~PropertyGridControl()
            {
                Dispose(false);
            }

#region IDisposable
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }

            protected virtual void Dispose(bool disposing)
            {
                if (!disposed)
                {
                    if (disposing)
                    {
                    }

                    if (this.Dispatcher.CheckAccess())
                    {
                        if (_isConnected)
                        {
                            Disconnect();
                        }

                        UnregisterInterfaceEvents();
                    }
                    else
                    {
                        DispatcherOperation operation = this.Dispatcher.BeginInvoke(
                            (Action)(() => {
                                if (_isConnected)
                                {
                                    Disconnect();
                                }

                                UnregisterInterfaceEvents();
                            }),
                            DispatcherPriority.Background,
                            null);
                    }

                    disposed = true;
                }
            }
#endregion

            public void ApplySettings(PersistentSettings settings)
            {
                try
                {
                    _applyingSettings = true;
                    TreeViewSortMethod = settings.PropertyTreeViewPersistentSettings.TreeViewSortMethod;
                    PollingEnabled = settings.PropertyTreeViewPersistentSettings.PollingEnabled;
                    FeatureVisibility = settings.PropertyTreeViewPersistentSettings.TreeViewVisibility;
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(
                        ex.Message, "Problem Applying Settings", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                finally
                {
                    _applyingSettings = false;
                }
            }

            public void FetchSettings(PersistentSettings settings)
            {
                try
                {
                    settings.PropertyTreeViewPersistentSettings.TreeViewSortMethod = TreeViewSortMethod;
                    settings.PropertyTreeViewPersistentSettings.PollingEnabled = PollingEnabled;
                    settings.PropertyTreeViewPersistentSettings.PollingFrequency = PollingFrequency;
                    settings.PropertyTreeViewPersistentSettings.TreeViewVisibility = FeatureVisibility;
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(
                        ex.Message, "Problem Fetch Settings", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }

            public void SaveSettings()
            {
                if (_initializing || _applyingSettings)
                {
                    return;
                }

                _settings.LoadPersistentSettings();
                FetchSettings(_settings);
                _settings.SavePersistentSettings();
            }

            private void RegisterInterfaceEvents()
            {
                if (_interfaceEventRegistered)
                {
                    return;
                }

                // check to see if its an interface object
                try
                {
                    if (_nodeMap == null)
                    {
                        return;
                    }
                    IString interfaceID = _nodeMap.GetNode<IString>("InterfaceID");

                    if (interfaceID != null)
                    {
                        // InterfaceID is only available on an interface
                        // and there are no removal events for interfaces
                        return;
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }

                try
                {
                    if(_nodeMap == null)
                    {
                        return;
                    }
                    IString serialNode = _nodeMap.GetNode<IString>("DeviceSerialNumber");
                    if (serialNode != null && serialNode.IsReadable)
                    {
                        _serialNumber = serialNode.Value;
                    }
                }
                catch (Exception ex)
                {
                    // Without a serial number, removal event won't work property. Abort.
                    Debug.WriteLine(ex.Message);
                    return;
                }

                _eventListener = new InterfaceEventListener();
                _eventListener.DeviceRemovalHandler += OnDeviceRemoval;

                if (_system == null)
                {
                    _system = new ManagedSystem();
                }

                if (_infList == null)
                {
                    _infList = _system.GetInterfaces();
                }

                try
                {
                    foreach (var inf in _infList)
                    {
                        inf.RegisterEventHandler(_eventListener);
                    }

                    _interfaceEventRegistered = true;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }

            private void UnregisterInterfaceEvents()
            {
                if (!_interfaceEventRegistered)
                {
                    return;
                }

                if (_eventListener != null && _system != null && _infList != null)
                {
                    foreach(var inf in _infList)
                    {
                        inf.UnregisterEventHandler(_eventListener);
                    }

                    if (_eventListener != null)
                    {
                        _eventListener.DeviceRemovalHandler -= OnDeviceRemoval;
                        _eventListener = null;
                    }

                    _interfaceEventRegistered = false;
                }
            }

            private void OnDeviceRemoval(IManagedCamera camera)
            {
                if (_nodeMap == null)
                {
                    return;
                }

                string serial = camera.GetDeviceSerialNumber();

                try
                {
                    if (serial == _serialNumber)
                    {
                        // Device has been removed
                        Dispatcher.BeginInvoke((ThreadStart) Disconnect);
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }

            public bool Connect(IManagedCamera camera)
            {
                _initializing = true;

                panel.Children.Clear();

                m_grid = new PropertyGridInternal();

                m_grid.OnSettingsChanged += m_grid_OnSettingsChanged;

                if (camera == null)
                {
                    return false;
                }

                // Get handle to device nodemap so interface events can be registered
                _nodeMap = camera.GetNodeMap();

                // Pass GUIXML to internal control
                m_grid.Tag = this.Tag;

                m_grid.Connect(camera);

                // Register for bus removal event
                RegisterInterfaceEvents();

                // Use Dispatcher to catch the closing event
                Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;

                panel.Children.Add(m_grid);
                panel.LastChildFill = true;

                // Apply settings
                m_grid.SetSortMethod(_sortMethod);
                m_grid.SetVisibility(_visibility);

                m_grid.MatchCase = (bool) chk_matchCases.IsChecked;
                m_grid.SearchDescriptionArea = (bool) chk_searchDescription.IsChecked;
                m_grid.SearchWholeWords = (bool) chk_searchWholeWords.IsChecked;

                _isConnected = true;

                _initializing = false;

                return true;
            }

            public bool Connect(INodeMap nodeMap)
            {
                _initializing = true;

                panel.Children.Clear();

                m_grid = new PropertyGridInternal();

                m_grid.OnSettingsChanged += m_grid_OnSettingsChanged;

                if (nodeMap == null)
                {
                    return false;
                }

                _nodeMap = nodeMap;

                // Pass GUIXML to internal control
                m_grid.Tag = this.Tag;

                if (!m_grid.Connect(nodeMap))
                {
                    return false;
                }

                // Register for bus removal event
                RegisterInterfaceEvents();

                // Use Dispatcher to catch the closing event
                Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;

                panel.Children.Add(m_grid);
                panel.LastChildFill = true;

                // Apply settings
                m_grid.SetSortMethod(_sortMethod);
                m_grid.PollingEnabled = _enablePolling;
                m_grid.SetPollingFrequency(_pollingFrequency);
                m_grid.SetVisibility(_visibility);
                m_grid.MatchCase = (bool) chk_matchCases.IsChecked;
                m_grid.SearchDescriptionArea = (bool) chk_searchDescription.IsChecked;
                m_grid.SearchWholeWords = (bool) chk_searchWholeWords.IsChecked;

                _isConnected = true;

                _initializing = false;

                return true;
            }

            public bool Connect(List<INodeMap>nodeMaps)
            {
                _initializing = true;

                panel.Children.Clear();

                m_grid = new PropertyGridInternal();

                m_grid.OnSettingsChanged += m_grid_OnSettingsChanged;

                if (nodeMaps == null || nodeMaps.Count == 0)
                {
                    return false;
                }

                // Pass GUIXML to internal control
                m_grid.Tag = this.Tag;

                if (!m_grid.Connect(nodeMaps))
                {
                    return false;
                }

                // Register for bus removal event
                RegisterInterfaceEvents();

                // Use Dispatcher to catch the closing event
                Dispatcher.ShutdownStarted += new EventHandler(Dispatcher_ShutdownStarted);

                panel.Children.Add(m_grid);
                panel.LastChildFill = true;

                // Apply settings
                m_grid.SetSortMethod(_sortMethod);
                m_grid.PollingEnabled = _enablePolling;
                m_grid.SetPollingFrequency(_pollingFrequency);
                m_grid.SetVisibility(_visibility);
                m_grid.MatchCase = (bool) chk_matchCases.IsChecked;
                m_grid.SearchDescriptionArea = (bool) chk_searchDescription.IsChecked;
                m_grid.SearchWholeWords = (bool) chk_searchWholeWords.IsChecked;

                _isConnected = true;

                _initializing = false;

                return true;
            }

            public void Disconnect()
            {
                if (m_grid != null)
                {
                    m_grid.Disconnect();
                }

                if (panel.Children != null)
                {
                    panel.Children.Clear();
                }

                if (_system != null)
                {
                    _system = null;
                }

                if (_infList != null)
                {
                    foreach(var inf in _infList)
                    {
                        inf.Dispose();
                    }

                    _infList = null;
                }

                _isConnected = false;
                m_grid = null;
            }

            public void SetPollingStatus(bool status)
            {
                _enablePolling = status;

                if (_isConnected && m_grid != null)
                {
                    m_grid.PollingEnabled = status;
                }
            }

            public bool GetPollingStatus()
            {
                if (_isConnected && m_grid != null)
                {
                    _enablePolling = m_grid.PollingEnabled;
                }

                return _enablePolling;
            }

            public int GetPollingFrequency()
            {
                if (_isConnected && m_grid != null)
                {
                    _pollingFrequency = m_grid.GetPollingFrequency();
                }

                return _pollingFrequency;
            }

            public void SetPollingFrequency(int frequencyInMS)
            {
                _pollingFrequency = frequencyInMS;

                if (_isConnected && m_grid != null)
                {
                    m_grid.SetPollingFrequency(_pollingFrequency);
                }
            }

            public void FocusSearchBar()
            {
                if (txtSearch != null)
                {
                    txtSearch.Focus();
                    txtSearch.Select(txtSearch.Text.Length, 0);
                }
            }

            public SortMethods GetSortMethod()
            {
                if (_isConnected && m_grid != null)
                {
                    _sortMethod = m_grid.CurrentSortMethod;
                }

                return _sortMethod;
            }

            public void SetSortMethod(SortMethods method)
            {
                _sortMethod = method;

                if (_isConnected && m_grid != null)
                {
                    m_grid.CurrentSortMethod = _sortMethod;

                    Dispatcher.BeginInvoke(
                        (Action)(() => {
                            switch (method)
                            {
                                case SortMethods.Alphabetical:
                                    btn_alphabetical.IsChecked = true;
                                    btn_categories.IsChecked = false;
                                    btn_xml.IsChecked = false;
                                    break;
                                case SortMethods.SelectorBased:
                                    btn_alphabetical.IsChecked = false;
                                    btn_categories.IsChecked = true;
                                    btn_xml.IsChecked = false;
                                    break;
                                case SortMethods.XML:
                                    btn_alphabetical.IsChecked = false;
                                    btn_categories.IsChecked = false;
                                    btn_xml.IsChecked = true;
                                    break;
                            }
                        }),
                        DispatcherPriority.Render,
                        null);
                }
            }

            public void SetVisibility(SpinnakerNET.GenApi.Visibility visibility)
            {
                _visibility = visibility;

                if (m_grid != null && _isConnected)
                {
                    m_grid.SetVisibility(_visibility);
                }
            }

            public SpinnakerNET.GenApi.Visibility GetVisibility()
            {
                if (m_grid != null && _isConnected)
                {
                    _visibility = m_grid.GetVisibility();
                }

                return _visibility;
            }

            public void ExpandAllNodes()
            {
                m_grid.ExpandAll();
            }

            public void CollapseAllNodes()
            {
                m_grid.CollapseAll();
            }

            public bool IsConnected()
            {
                return _isConnected;
            }

            public void RefreshProperties()
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.RefreshProperties();
                }
            }

            private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
            {
                UnregisterCallbacks();
                // m_grid.DeinitializeNodeInformationWindow();
            }

            private void UnregisterCallbacks()
            {
                // try
                //{
                //    m_busMgr.UnregisterCallback(m_busRemovalHandle);
                //}
                // catch (FC2Exception ex)
                //{
                //    string error = string.Format("Failed to unregister bus removal callback. (Callback Type:Removal)
                //    {0}", ex.Message); Console.WriteLine(error);
                //}
            }

            private void RegisterCallBack(ManagedCameraBase camera)
            {
                // try
                //{
                //    CameraInfo info = camera.GetCameraInfo();
                //    m_serialNumber = info.serialNumber;
                //    m_busRemovalHandle = m_busMgr.RegisterCallback(OnBusRemoval,
                //    SpinnakerNET.ManagedCallbackType.Removal, IntPtr.Zero);
                //}
                // catch (FC2Exception ex)
                //{
                //    if (ex.Type != SpinnakerNET.ErrorType.Ok)
                //    {
                //        string error = string.Format("Failed to register callback. (Callback Type:Removal) {0}",
                //        ex.Message); Console.WriteLine(error);
                //    }
                //}
            }

            private void OnBusRemoval(System.IntPtr ptr, uint serialNumber)
            {
                Console.WriteLine("{0} - *** BUS REMOVAL ({1})***", DateTime.Now.ToString(), serialNumber);
                if (serialNumber == m_serialNumber)
                {
                    Disconnect();
                }
            }

            private void txtSearch_TextChanged(object sender, TextChangedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.KeyWords = txtSearch.Text;

                    // Clearing keywords left all nodes expanded by default
                    if (string.IsNullOrEmpty(txtSearch.Text))
                    {
                        _nodesExpanded = true;
                    }
                }
            }

            private void btnClear_Click(object sender, RoutedEventArgs e)
            {
                txtSearch.Text = "";
            }

            private void chk_searchDescription_Checked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.SearchDescriptionArea = true;
                    if (txtSearch.Text != "")
                    {
                        m_grid.KeyWords = txtSearch.Text;
                    }
                }
            }

            private void chk_searchDescription_Unchecked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.SearchDescriptionArea = false;
                    if (txtSearch.Text != "")
                    {
                        m_grid.KeyWords = txtSearch.Text;
                    }
                }
            }

            private void chk_searchWholeWords_Checked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.SearchWholeWords = true;
                    if (txtSearch.Text != "")
                    {
                        m_grid.KeyWords = txtSearch.Text;
                    }
                }
            }

            private void chk_searchWholeWords_Unchecked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.SearchWholeWords = false;
                    if (txtSearch.Text != "")
                    {
                        m_grid.KeyWords = txtSearch.Text;
                    }
                }
            }

            private void chk_matchCases_Checked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.MatchCase = true;
                    if (txtSearch.Text != "")
                    {
                        m_grid.KeyWords = txtSearch.Text;
                    }
                }
            }

            private void chk_matchCases_Unchecked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.MatchCase = false;
                    if (txtSearch.Text != "")
                    {
                        m_grid.KeyWords = txtSearch.Text;
                    }
                }
            }

            private void txtSearch_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    // Search operation automatically expands all nodes
                    _nodesExpanded = true;

                    if (e.Key == System.Windows.Input.Key.Enter)
                    {
                        m_grid.KeyWords = txtSearch.Text;
                    }
                }
            }

            private void btn_categories_Checked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.SetSortMethod(SortMethods.SelectorBased);
                    btn_alphabetical.IsChecked = false;
                    btn_xml.IsChecked = false;
                }
            }

            private void btn_alphabetical_Checked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.SetSortMethod(SortMethods.Alphabetical);
                    btn_categories.IsChecked = false;
                    btn_xml.IsChecked = false;
                }
            }

            private void btn_xml_Checked(object sender, RoutedEventArgs e)
            {
                if (m_grid != null && _isConnected)
                {
                    m_grid.SetSortMethod(SortMethods.XML);
                    btn_categories.IsChecked = false;
                    btn_alphabetical.IsChecked = false;
                }
            }

            private void btn_xml_Click(object sender, RoutedEventArgs e)
            {
                if (btn_xml.IsChecked == true)
                {
                    e.Handled = true;
                    return;
                }
                else
                {
                    btn_xml.IsChecked = true;
                }
            }

            private void btn_categories_Click(object sender, RoutedEventArgs e)
            {
                if (btn_categories.IsChecked == true)
                {
                    e.Handled = true;
                    return;
                }
                else
                {
                    btn_categories.IsChecked = true;
                }
            }

            private void btn_alphabetical_Click(object sender, RoutedEventArgs e)
            {
                if (btn_alphabetical.IsChecked == true)
                {
                    e.Handled = true;
                    return;
                }
                else
                {
                    btn_alphabetical.IsChecked = true;
                }
            }

            private void Expander_Expanded(object sender, RoutedEventArgs e)
            {
                txtSearch.Select(txtSearch.Text.Length, 0);
                txtSearch.Focus();
            }

            private void UserControl_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
            {
                if (e.Key == Key.Escape)
                {
                    btnClear_Click(this, null);
                }
                else if (e.Key == Key.F5)
                {
                    if (m_grid != null && _isConnected)
                    {
                        m_grid.RefreshProperties();
                    }
                }
            }

            private void expand_collapse_nodes(object sender, RoutedEventArgs e)
            {
                if (_nodesExpanded)
                {
                    CollapseAllNodes();
                    _nodesExpanded = false;
                }
                else
                {
                    ExpandAllNodes();
                    _nodesExpanded = true;
                }
            }

            private void btn_expand_Unchecked(object sender, RoutedEventArgs e)
            {
                CollapseAllNodes();
            }

            private void ToolBar_Loaded(object sender, RoutedEventArgs e)
            {
                System.Windows.Controls.ToolBar toolBar = sender as System.Windows.Controls.ToolBar;
                var overflowGrid = toolBar.Template.FindName("OverflowGrid", toolBar) as FrameworkElement;
                if (overflowGrid != null)
                {
                    overflowGrid.Visibility = System.Windows.Visibility.Collapsed;
                }

                var mainPanelBorder = toolBar.Template.FindName("MainPanelBorder", toolBar) as FrameworkElement;
                if (mainPanelBorder != null)
                {
                    mainPanelBorder.Margin = new Thickness(0);
                }
            }
        }


        public enum SortMethods { Alphabetical, SelectorBased, XML }
    }
}