Skip to content

File LogarithmicSliderControl.xaml.cs

File List > PGRControls > LogarithmicSliderControl.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.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.ExceptionServices;
using System.Security;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace SpinnakerNET.GUI
{
    namespace WPFControls
    {



        public sealed partial class LogarithmicSliderControl : BaseClass
        {

#region Properties
            // Basic Properties
            private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(LogarithmicSliderControl));
            private static readonly log4net.ILog analytics = log4net.LogManager.GetLogger("Analytics");
            private const int k_numOfRetried = 5;
            private INode _node;
            private IInteger _integerNode;
            private IFloat _floatNode;
            private bool _nameLabelOnTop = false;
            private bool _nameLabelOnBottom = false;
            private bool _isNodeReadable = false;
            private double _minimum = 0;
            private double _maximum = 0;
            private double _increment = 0;
            private bool _disposed = false;
            private double _oldValue = 0;
            private string _editBoxTooltip;
            private bool _isEditing = false;
            private bool _isEditboxEnabled;
            private bool _isEditboxReadOnly;
            private bool _isSpinnerControlEnabled;
            private bool _isSliderBarEnabled;

            // Slider Dragging
            private bool _dragStarted = false;
            private bool _editStarted = false;
            private bool _skipCallback = false;
            private int _counter = 0;

            // GenICam callback update thread
            BackgroundWorker _updateWorker;

            // SpinButton
            private System.Windows.Visibility _SpinButtonVisibility = System.Windows.Visibility.Hidden;
            Integer _pAliasNode;
            long _spinnerValue;
#endregion

#region PROPERTIES
            public bool IsSliderBarEnabled
            {
                get
                {
                    return _isSliderBarEnabled;
                }
                set
                {
                    _isSliderBarEnabled = value;
                    NotifyPropertyChanged("IsSliderBarEnabled");
                }
            }

            public bool IsEditboxEnabled
            {
                get
                {
                    return _isEditboxEnabled;
                }
                set
                {
                    _isEditboxEnabled = value;
                    NotifyPropertyChanged("IsEditboxEnabled");
                }
            }

            public bool IsEditboxReadOnly
            {
                get
                {
                    return _isEditboxReadOnly;
                }
                set
                {
                    _isEditboxReadOnly = value;
                    NotifyPropertyChanged("IsEditboxReadOnly");
                }
            }

            public bool IsSpinnerControlEnabled
            {
                get
                {
                    return _isSpinnerControlEnabled;
                }
                set
                {
                    _isSpinnerControlEnabled = value;
                    NotifyPropertyChanged("IsSpinnerControlEnabled");
                }
            }

            public string EditBoxTooltip
            {
                get
                {
                    return _editBoxTooltip;
                }
                set
                {
                    _editBoxTooltip = value;
                    NotifyPropertyChanged("EditBoxTooltip");
                }
            }

            public System.Windows.Visibility SpinButtonVisibility
            {
                get
                {
                    if (_pAliasNode == null)
                    {
                        return System.Windows.Visibility.Hidden;
                    }
                    else
                    {
                        return _SpinButtonVisibility;
                    }
                }
                set
                {
                    _SpinButtonVisibility = value;
                    NotifyPropertyChanged("SpinButtonVisibility");
                }
            }

            public long SpinnerValue
            {
                get
                {
                    return _spinnerValue;
                }
                set
                {
                    _spinnerValue = value;
                    NotifyPropertyChanged("SpinnerValue");
                }
            }

            public Boolean IsNodeReadable
            {
                get
                {
                    return _isNodeReadable;
                }
                set
                {
                    _isNodeReadable = value;
                    NotifyPropertyChanged("IsNodeReadable");
                }
            }

            public double CurrentValue
            {
                get
                {
                    try
                    {
                        return (sliderbar != null) ? log2Double(sliderbar.Value) : float.NaN;
                    }
                    catch (System.Exception /*ex*/)
                    {
                        return float.NaN;
                    }
                }
                set
                {
                    if (IsNodeReadable)
                    {
                        double logVal = double2Log(value);

                        if (!double.IsNaN(logVal) && !double.IsNegativeInfinity(logVal) &&
                            !double.IsPositiveInfinity(logVal))
                        {
                            sliderbar.Value = logVal;
                            NotifyPropertyChanged("CurrentValue");
                            NotifyPropertyChanged("CurrentValueFormatted");
                        }
                    }
                }
            }

            public string CurrentValueFormatted
            {
                get
                {
                    return NumericFormatter.FormatNumericToString(CurrentValue, DecimalPlaces);
                }
                set
                {
                    double parsed;
                    if (double.TryParse(value, out parsed))
                    {
                        CurrentValue = parsed;
                    }
                }
            }

            public double Min
            {
                get
                {
                    return _minimum;
                }
                set
                {
                    _minimum = value;
                }
            }

            public double Max
            {
                get
                {
                    return _maximum;
                }
                set
                {
                    _maximum = value;
                }
            }

            public double Increment
            {
                get
                {
                    return _increment;
                }
                set
                {
                    _increment = value;
                }
            }

            public string Unit
            {
                get
                {
                    return unitLabel.Content.ToString();
                }
                set
                {
                    unitLabel.Content = value;
                }
            }

            public System.Windows.Visibility UnitLabelVisibility
            {
                get
                {
                    return this.unitLabel.Visibility;
                }
                set
                {
                    this.unitLabel.Visibility = value;
                }
            }

            public System.Windows.Visibility EditBoxVisibility
            {
                get
                {
                    return this.editbox.Visibility;
                }
                set
                {
                    this.editbox.Visibility = value;
                }
            }

            public System.Windows.Visibility SliderVisibility
            {
                get
                {
                    return sliderbar.Visibility;
                }
                set
                {
                    this.sliderbar.Visibility = value;
                }
            }

            public double MinLabelWidth
            {
                get
                {
                    return this.nameLabel.MinWidth;
                }
                set
                {
                    this.nameLabel.MinWidth = value;
                }
            }

            public double MaxLabelWidth
            {
                get
                {
                    return this.nameLabel.MaxWidth;
                }
                set
                {
                    this.nameLabel.MaxWidth = value;
                }
            }

            public double EditBoxWidth
            {
                get
                {
                    return editbox.ActualWidth;
                }
                set
                {
                    editbox.Width = value;
                }
            }

            public double MinEditBoxWidth
            {
                get
                {
                    return editbox.MinWidth;
                }
                set
                {
                    editbox.MinWidth = value;
                }
            }

            public double MaxEditBoxWidth
            {
                get
                {
                    return editbox.MaxWidth;
                }
                set
                {
                    editbox.MaxWidth = value;
                }
            }

            public bool NameLabelOnTop
            {
                get
                {
                    return _nameLabelOnTop;
                }
                set
                {
                    this._nameLabelOnTop = value;
                    if (_nameLabelOnTop)
                    {
                        LabelAppearOnTop();
                    }
                }
            }

            public bool NameLabelOnBottom
            {
                get
                {
                    return _nameLabelOnBottom;
                }
                set
                {
                    this._nameLabelOnBottom = value;
                    if (_nameLabelOnBottom)
                    {
                        LabelAppearOnBottom();
                    }
                }
            }
#endregion

#region Constructor
            public LogarithmicSliderControl()
            {
                InitializeComponent();
                this.DataContext = this;
                _timer = new System.Windows.Forms.Timer();

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

            ~LogarithmicSliderControl()
            {
                if (_counter != 0)
                {
                    Disconnect();
                }
            }

            internal LogarithmicSliderControl(LogarithmicSliderControl 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.NameLabelVisibility);
                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());

                this.NameLabelOnTop = originalControl.NameLabelOnTop;
                this.NameLabelOnBottom = originalControl.NameLabelOnBottom;

                // Slider specific properties
                this.UnitLabelVisibility = originalControl.UnitLabelVisibility;
                this.MinLabelWidth = originalControl.MinLabelWidth;
                this.MaxLabelWidth = originalControl.MaxLabelWidth;
                this.MinEditBoxWidth = originalControl.MinEditBoxWidth;
                this.MaxEditBoxWidth = originalControl.MinEditBoxWidth;
            }

            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_INTERFACE
            public override void SetMin(double min)
            {
                Min = min;
            }

            public override void SetMax(double max)
            {
                Max = max;
            }

            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()
            {
                // Sanity check
                if (_nodeMap == null)
                {
                    return;
                }

                try
                {
                    _initializing = true;
                    UpdateControlValues(this._nodeType, this._nodeMap, this.PropertyToControl, this.ControlNameLabel);
                    UpdateControlStatus();
                }
                catch (System.Exception /*ex*/)
                {
                    Debug.WriteLine("Problem updating control values.");
                }
                finally
                {
                    _initializing = false;
                }
            }

            public void SetUnitLabel(string unitLabel)
            {
                this.Unit = unitLabel;
            }

            public void SetUnitLabelVisibility(System.Windows.Visibility visibility)
            {
                this.UnitLabelVisibility = visibility;
            }

            public void SetEditBoxVisibility(bool overrideDefault, System.Windows.Visibility visibility)
            {
                if (overrideDefault)
                {
                    this.editbox.Visibility = visibility;
                }
            }

            public void SetSliderVisibility(System.Windows.Visibility visibility)
            {

                this.sliderbar.Visibility = visibility;
            }

            public override double GetMin()
            {
                return Min;
            }

            public override double GetMax()
            {
                return Max;
            }

            public override void Connect(INodeMap nodemap, string nodename, string namelabel = "")
            {
                this._propertyToControl = nodename;
                this._nodeMap = nodemap;

                if (nodemap != null && nodename.Length > 0)
                {
                    // Acquire device serial number
                    if (string.IsNullOrWhiteSpace(_serialNumber))
                    {
                        _serialNumber = RetrieveSerialNumber(nodemap);
                    }

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

                    try
                    {
                        _node = nodemap.GetNode<INode>(nodename);

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

                        this._nodeType = _node.GetType();
                        _featureAvailable = _node.IsImplemented;
                    }
                    catch (System.Exception ex)
                    {
                        _featureAvailable = false;
                        UpdateControlStatus();
                        log.Debug(
                            string.Format(
                                "{1}Problem accessing {0} node. {2}",
                                this._propertyToControl,
                                FormattedSerialNumber,
                                ex.Message),
                            ex);
                        throw new Exception(
                            string.Format("Problem accessing {0} node. {1}", this._propertyToControl, ex.Message));
                    }

                    _initializing = true;

                    try
                    {
                        UpdateControlValues(this._nodeType, this._nodeMap, this._propertyToControl, namelabel);

                        // Determine whether Spinbutton is visible
                        if (this._nodeType == typeof (Float))
                        {
                            if (_floatNode.Alias != null &&
                                _floatNode.Alias.GetType() == typeof (Integer) && _floatNode.Alias.IsReadable)
                            {
                                _pAliasNode = _floatNode.Alias as Integer;
                                SpinButtonVisibility = System.Windows.Visibility.Visible;
                                spinnerControl.Value = _pAliasNode.Value;
                                spinnerControl.Change = _pAliasNode.Increment;
                                spinnerControl.Maximum = _pAliasNode.Max;
                                spinnerControl.Minimum = _pAliasNode.Min;

                                spinnerControl.ValueChanged += spinnerControl_ValueChanged;
                            }
                            else
                            {
                                SpinButtonVisibility = System.Windows.Visibility.Hidden;
                            }
                        }
                        else
                        {
                            SpinButtonVisibility = System.Windows.Visibility.Hidden;
                        }

                        UpdateControlStatus();
                        RegisterGenICamCallbacks();
                        RegisterInterfaceEvents();
                    }
                    catch (System.Exception ex)
                    {
                        log.Error(
                            string.Format(
                                "{1}Problem accessing {0} node.", this._propertyToControl, FormattedSerialNumber),
                            ex);
                    }
                    finally
                    {
                        _initializing = false;
                    }
                }
            }

            public override void Disconnect()
            {
                try
                {
                    if (_floatNode != null)
                    {
                        _floatNode.Updated -= node_Updated;
                        _floatNode = null;
                    }
                    else if (_integerNode != null)
                    {
                        _integerNode.Updated -= node_Updated;
                        _integerNode = null;
                    }

                    _node = null;
                    _mapper = null;
                    _counter--;

                    base.Disconnect();
                }
                catch (System.Exception /*ex*/)
                {
                }
            }

#endregion

#region GENICAM_CALLBACK
            private void RegisterGenICamCallbacks()
            {
                if (_floatNode != null)
                {
                    _floatNode.Updated += node_Updated;
                }
                else if (_integerNode != null)
                {
                    _integerNode.Updated += node_Updated;
                }

                _counter++;
            }

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

                if (e.Cancelled)
                {
                    return;
                }

                try
                {
                    Dispatcher.Invoke(() => {
                        _isUpdating = true;
                        _skipCallback = 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 (_controlNameLabel != currentNodeStatus.NodeDisplayName)
                        {
                            ControlNameLabel = currentNodeStatus.NodeDisplayName;
                        }

                        if (_tooltip != currentNodeStatus.Tooltip)
                        {
                            ControlToolTip = currentNodeStatus.Tooltip;
                            refreshRequired = true;
                        }

                        if (Min != currentNodeStatus.Min)
                        {
                            Min = currentNodeStatus.Min;
                            refreshRequired = true;
                        }

                        if (Max != currentNodeStatus.Max)
                        {
                            Max = currentNodeStatus.Max;
                            refreshRequired = true;

                            EditBoxTooltip =
                                string.Format("Min: {0}, Max: {1}", Min.ToString("G5"), Max.ToString("G5"));
                        }

                        if (currentNodeStatus.CurrentValue != double.NaN)
                        {
                            if (CurrentValue != currentNodeStatus.CurrentValue)
                            {
                                if (!Dispatcher.CheckAccess())
                                {
                                    Dispatcher.BeginInvoke(
                                        (Action)(() => {
                                            sliderbar.ValueChanged -= sliderbar_ValueChanged;
                                            CurrentValue = currentNodeStatus.CurrentValue;
                                            NotifyPropertyChanged("CurrentValueFormatted");
                                            sliderbar.ValueChanged += sliderbar_ValueChanged;
                                        }),
                                        DispatcherPriority.Background,
                                        null);
                                }
                                else
                                {
                                    sliderbar.ValueChanged -= sliderbar_ValueChanged;
                                    CurrentValue = currentNodeStatus.CurrentValue;
                                    NotifyPropertyChanged("CurrentValueFormatted");
                                    sliderbar.ValueChanged += sliderbar_ValueChanged;
                                }

                                refreshRequired = true;
                            }
                        }

                        if (!currentNodeStatus.IsWritable)
                        {
                            // Node becomes non-writable
                            base.IsEditable = false;
                            IsSliderBarEnabled = false;
                            IsEditboxReadOnly = true;
                            IsSpinnerControlEnabled = false;
                            SpinButtonVisibility = System.Windows.Visibility.Hidden;
                        }

                        if (currentNodeStatus.IsWritable)
                        {
                            // Node becomes writable
                            base.IsEditable = true;
                            IsSliderBarEnabled = true;
                            IsEditboxEnabled = true;
                            IsSpinnerControlEnabled = true;
                            SpinButtonVisibility = System.Windows.Visibility.Visible;
                            IsEditboxReadOnly = false;
                        }
                    });
                }
                catch (System.Exception ex)
                {
                    log.Debug(
                        string.Format(
                            "{1}Problem updating control for {0} node", _propertyToControl, FormattedSerialNumber),
                        ex);
                }
                finally
                {
                    _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;
            }

            void node_Updated(INode node)
            {
                // Cancel update if slider was being dragged
                if (_dragStarted || _initializing || _skipCallback || _isEditing)
                {
                    return;
                }

                if (_nodeMap == null)
                {
                    return;
                }

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

                if (!IsVisible)
                {
                    return;
                }

                _updateWorker.RunWorkerAsync(node);
            }
#endregion

#region IEditableObject
            public void BeginEdit()
            {
                _isEditing = true;
                double tempValue = 0;
                if (double.TryParse(editbox.Text, out tempValue))
                {
                    _oldValue = tempValue;
                }
            }

            public void CancelEdit()
            {
                CurrentValue = _oldValue;
                _isEditing = false;
            }

            public void EndEdit()
            {
                double tempValue = 0;
                if (double.TryParse(editbox.Text, out tempValue))
                {
                    _oldValue = tempValue;
                }

                _isEditing = false;
            }
#endregion

#region UI_CONTROL_UPDATE

            private void editbox_TextChanged(object sender, TextChangedEventArgs e)
            {
                if (_initializing)
                {
                    return;
                }

                BeginEdit();

                if (!CheckValueBounds(editbox.Text))
                {
                    CancelEdit();
                }
                else
                {
                    try
                    {
                        double temp = 0;
                        if (double.TryParse(editbox.Text, out temp))
                        {
                            CurrentValue = temp;
                            SyncSpinnerValue();
                        }
                    }
                    catch
                    {
                    }
                }
            }

            private void editbox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                if (e.ClickCount == 2)
                {
                    e.Handled = true;
                    editbox.SelectAll();
                }

                BeginEdit();
            }

            private void Sliderbar_OnPreviewMouseUp(object sender, MouseButtonEventArgs e)
            {
                if (_nodeType == typeof (Integer))
                {
                    AnalyticsNodeUpdateAction(analytics, _node, _integerNode.ToString());
                }
                else if (_nodeType == typeof (Float))
                {
                    AnalyticsNodeUpdateAction(analytics, _node, string.Format("{0:0.00}", _floatNode.Value));
                }
            }

            private void Sliderbar_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                if (e.ClickCount == 2)
                {
                    e.Handled = true;
                }
            }

            private bool CheckValueBounds(string input)
            {
                if (_initializing)
                {
                    return false;
                }

                bool result = true;

                if (_nodeType == typeof (Integer))
                {
                    try
                    {
                        if (_integerNode != null && _integerNode.IsWritable)
                        {
                            string formattedInput;

                            if (_mapper != null)
                            {
                                formattedInput = _mapper.ConvertStringToNodeFormat(_propertyToControl, input);
                            }
                            else
                            {
                                formattedInput = input;
                            }

                            long convertedInput = 0;

                            if (long.TryParse(formattedInput, out convertedInput))
                            {
                                if (convertedInput < Min || convertedInput > Max)
                                {
                                    result = false;
                                }
                            }
                            else
                            {
                                result = false;
                            }
                        }
                    }
                    catch (System.Exception /*ex*/)
                    {
                    }
                }
                else if (_nodeType == typeof (Float))
                {
                    try
                    {
                        if (_floatNode != null && _floatNode.IsWritable)
                        {
                            string formattedInput;

                            if (_mapper != null)
                            {
                                formattedInput = _mapper.ConvertStringToNodeFormat(_propertyToControl, input);
                            }
                            else
                            {
                                formattedInput = input;
                            }

                            float convertedInput = 0;

                            if (float.TryParse(formattedInput, out convertedInput))
                            {
                                if (convertedInput < Min || convertedInput > Max)
                                {
                                    result = false;
                                }
                            }
                            else
                            {
                                result = false;
                            }
                        }
                    }
                    catch (System.Exception /*ex*/)
                    {
                    }
                }

                return result;
            }

            private void UpdateControlStatus()
            {
                try
                {
                    if (_node == null || !_node.IsAvailable)
                    {
                        base.IsEditable = false;
                        IsSliderBarEnabled = false;
                        IsEditboxEnabled = false;
                        IsSpinnerControlEnabled = false;
                        SpinButtonVisibility = System.Windows.Visibility.Hidden;
                        return;
                    }

                    if (!_node.IsWritable)
                    {
                        base.IsEditable = false;
                        IsSliderBarEnabled = false;
                        IsEditboxReadOnly = true;
                        IsSpinnerControlEnabled = false;
                        SpinButtonVisibility = System.Windows.Visibility.Hidden;
                        return;
                    }
                    else
                    {
                        base.IsEditable = true;
                        IsSliderBarEnabled = true;
                        IsEditboxEnabled = true;
                        IsSpinnerControlEnabled = true;
                        SpinButtonVisibility = System.Windows.Visibility.Visible;
                        IsEditboxReadOnly = false;
                    }
                }
                catch (System.Exception ex)
                {
                    log.Error(
                        string.Format("{0}There was a problem updating control status.", FormattedSerialNumber), ex);
                    throw new Exception(ex.Message);
                }
            }

            private void UpdateControlValues(Type type, INodeMap nodemap, string nodename, string namelabel = "")
            {
                if (type == typeof (Float))
                {
                    try
                    {
                        _floatNode = nodemap.GetNode<IFloat>(nodename);
                    }
                    catch (System.Exception ex)
                    {
                        log.Error(
                            string.Format("{1}Problem obtaining {0} from NodeMap.", nodename, FormattedSerialNumber),
                            ex);
                        return;
                    }

                    if (Min != _floatNode.Min)
                    {
                        Min = _floatNode.Min;
                    }
                    if (Max != _floatNode.Max)
                    {
                        Max = _floatNode.Max;
                    }
                    ControlNameLabel = namelabel.Length == 0 ? _floatNode.DisplayName : namelabel;
                    Unit = _floatNode.Unit;

                    // Set display precision from camera XML
                    if (_floatNode.IsReadable)
                    {
                        try
                        {
                            DecimalPlaces = ClampDisplayPrecision(_floatNode.DisplayPrecision);
                        }
                        catch (System.Exception /*ex*/)
                        {
                            // If DisplayPrecision is not available, keep existing DecimalPlaces value
                        }
                    }

                    // Set tooltip
                    ControlToolTip = _floatNode.ToolTip;

                    // Update _isReadable
                    IsNodeReadable = _floatNode.IsReadable;

                    if (_isNodeReadable)
                    {
                        try
                        {
                            _skipCallback = true;

                            if (_pAliasNode != null && _pAliasNode.IsReadable)
                            {
                                SpinnerValue = _pAliasNode.Value;
                            }

                            CurrentValue = _floatNode.Value;
                            NotifyPropertyChanged("CurrentValueFormatted");
                        }
                        catch
                        {
                        }
                        finally
                        {
                            _skipCallback = false;
                        }
                    }
                }
                else if (type == typeof (Integer))
                {
                    try
                    {
                        _integerNode = nodemap.GetNode<IInteger>(nodename);
                    }
                    catch (System.Exception ex)
                    {
                        log.Error(
                            string.Format("{1}Problem obtaining {0} from NodeMap.", nodename, FormattedSerialNumber),
                            ex);
                        return;
                    }

                    if (Min != _integerNode.Min)
                    {
                        Min = _integerNode.Min;
                    }
                    if (Max != _integerNode.Max)
                    {
                        Max = _integerNode.Max;
                    }

                    Increment = _integerNode.Increment;
                    this.sliderbar.IsSnapToTickEnabled = true;

                    // Update _isReadable
                    IsNodeReadable = _integerNode.IsReadable;

                    if (_isNodeReadable)
                    {
                        try
                        {
                            _skipCallback = true;
                            CurrentValue = _integerNode.Value;
                            NotifyPropertyChanged("CurrentValueFormatted");
                        }
                        catch (Exception /*ex*/)
                        {
                        }
                        finally
                        {
                            _skipCallback = false;
                        }
                    }

                    ControlNameLabel = namelabel.Length == 0 ? _integerNode.DisplayName : namelabel;
                    // No unit available for IInteger node
                    Unit = string.Empty;
                    // Set tooltip
                    ControlToolTip = _integerNode.ToolTip;
                }
                else
                {
                    // Unhandled node type detected
                    log.Warn(string.Format("{0}Unexpected control type.", FormattedSerialNumber));
                }

                try
                {
                    editbox.ToolTip = string.Format(
                        "Min: {0}, Max: {1}",
                        Min.ToString("G5", CultureInfo.InvariantCulture),
                        Max.ToString("G5", CultureInfo.InvariantCulture));
                }
                catch
                {
                }
            }
#endregion

#region Event_Handlers

            void timer_Tick(object sender, EventArgs e)
            {
                try
                {
                    if (_dragStarted || _editStarted)
                    {
                        // Skip update if user was
                        // dragging the slider or
                        // editing textbox
                        return;
                    }

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

            private void editbox_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.Enter)
                {
                    try
                    {
                        if (!CheckValueBounds(editbox.Text))
                        {
                            CancelEdit();
                        }
                        else
                        {
                            EndEdit();
                            BindingExpression exp = this.editbox.GetBindingExpression(TextBox.TextProperty);
                            exp.UpdateSource();
                            SyncSpinnerValue();

                            if (_nodeType == typeof (Integer))
                            {
                                AnalyticsNodeUpdateAction(analytics, _node, CurrentValue.ToString());
                            }
                            else if (_nodeType == typeof (Float))
                            {
                                AnalyticsNodeUpdateAction(analytics, _node, string.Format("{0:0.00}", CurrentValue));
                            }
                        }
                    }
                    catch
                    {
                    }
                }
                else if (e.Key == Key.Escape)
                {
                    CancelEdit();
                }
            }

            private void editbox_LostFocus(object sender, RoutedEventArgs e)
            {
                if (!CheckValueBounds(editbox.Text))
                {
                    CancelEdit();
                }
                else
                {
                    EndEdit();
                    BindingExpression exp = this.editbox.GetBindingExpression(TextBox.TextProperty);
                    exp.UpdateSource();
                    SyncSpinnerValue();
                }
            }

            private void sliderbar_DragCompleted(object sender, DragCompletedEventArgs e)
            {
                CurrentValue = log2Double(sliderbar.Value);
                UpdateNodeValue();
                _dragStarted = false;
                SyncSpinnerValue();
            }

            private void sliderbar_DragStarted(object sender, DragStartedEventArgs e)
            {
                _dragStarted = true;
            }

            private void sliderbar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double>e)
            {
                if (_skipCallback || _initializing)
                {
                    return;
                }

                if (!_dragStarted)
                {
                    CurrentValue = log2Double(sliderbar.Value);
                    UpdateNodeValue();
                }
            }

#endregion

#region HELPERS
            private bool UpdateNodeValue()
            {
                if (_initializing)
                {
                    return false;
                }

                bool result = true;

                if (_nodeType == typeof (Integer))
                {
                    try
                    {
                        if (_integerNode != null && _integerNode.IsWritable)
                        {
                            double currentSliderValue = CurrentValue;
                            double currentNodeValue = _integerNode.Value;
                            // Special case for DeviceLinkThroughputLimit
                            if (base.PropertyToControl == "DeviceLinkThroughputLimit")
                            {
                                long previousValue = 0;
                                long currentValue = 0;
                                int iterations = 0;

                                // Find closest valid points between current cursor position
                                while (currentValue < currentSliderValue)
                                {
                                    previousValue = currentValue;
                                    currentValue = (_integerNode.Increment * iterations++) + _integerNode.Min;
                                }

                                // Pick value based on direction of dragging
                                if (currentSliderValue < currentNodeValue)
                                {
                                    currentSliderValue = previousValue;
                                }
                                else
                                {
                                    currentSliderValue = currentValue;
                                }
                            }
                            else
                            {
                                while (currentSliderValue % _integerNode.Increment != 0)
                                {
                                    if (currentSliderValue < currentNodeValue)
                                    {
                                        currentSliderValue--;
                                    }
                                    else
                                    {
                                        currentSliderValue++;
                                    }
                                }
                            }

                            bool success = false;
                            int count = 0;
                            while (!success && count < k_numOfRetried)
                            {
                                try
                                {
                                    _skipCallback = true;
                                    _integerNode.Value = (long) currentSliderValue;
                                    LogNodeUpdateAction(log, _node, currentSliderValue.ToString());
                                    success = true;
                                }
                                catch (System.Exception /*ex*/)
                                {
                                    count++;
                                }
                                finally
                                {
                                    _skipCallback = false;
                                }
                            }
                        }
                        else
                        {
                            Debug.WriteLine(string.Format("{0} node is currently not writable.", _propertyToControl));
                            result = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        result = false;
                        throw new Exception(
                            string.Format("Error updating node value for {0}. {1}", _propertyToControl, ex.Message));
                    }
                    finally
                    {
                        // read value back from node
                        if (_integerNode != null && _integerNode.IsReadable)
                        {
                            _skipCallback = true;
                            CurrentValue = _integerNode.Value;
                            _skipCallback = false;
                        }
                    }
                }
                else if (_nodeType == typeof (Float))
                {
                    try
                    {
                        if (_floatNode != null && _floatNode.IsWritable)
                        {
                            double valueToWrite = CurrentValue;
                            double increment;
                            if (TryGetFloatIncrement(_floatNode, out increment))
                            {
                                valueToWrite = NormalizeValueToIncrement(valueToWrite, _floatNode.Min, _floatNode.Max, increment);
                            }

                            bool success = false;
                            int count = 0;
                            while (!success && count < k_numOfRetried)
                            {
                                try
                                {
                                    _skipCallback = true;
                                    _floatNode.Value = valueToWrite;
                                    LogNodeUpdateAction(log, _node, valueToWrite.ToString());
                                    success = true;
                                }
                                catch (System.Exception /*ex*/)
                                {
                                    count++;
                                }
                                finally
                                {
                                    _skipCallback = false;
                                }
                            }
                        }
                        else
                        {
                            Debug.WriteLine(string.Format("{0} node is currently not writable.", _propertyToControl));
                            result = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        result = false;
                        throw new Exception(
                            string.Format("Error updating node value for {0}. {1}", _propertyToControl, ex.Message));
                    }
                    finally
                    {
                        // read new value back from node
                        if (_floatNode != null && _floatNode.IsReadable)
                        {
                            _skipCallback = true;
                            CurrentValue = _floatNode.Value;
                            _skipCallback = false;
                        }
                    }
                }

                // Update Dependency
                if (_dependencyControlList != null && _dependencyControlList.Count > 0)
                {
                    _dependencyControlList.Refresh();
                }

                return result;
            }

            public void SliderAppearRight()
            {
                try
                {
                    _skipCallback = true;

                    rootLayout.Children.Clear();

                    DockPanel.SetDock(nameLabel, Dock.Left);
                    DockPanel.SetDock(editboxContainer, Dock.Left);
                    DockPanel.SetDock(unitLabel, Dock.Left);
                    DockPanel.SetDock(lockIcon, Dock.Left);
                    // DockPanel.SetDock(sliderbar, Dock.Left);

                    rootLayout.Children.Add(nameLabel);
                    rootLayout.Children.Add(editboxContainer);
                    rootLayout.Children.Add(unitLabel);
                    rootLayout.Children.Add(lockIcon);
                    rootLayout.Children.Add(sliderbar);

                    UpdateControlStatus();
                }
                catch
                {
                }
                finally
                {
                    _skipCallback = false;
                }
            }

            public void SliderAppearLeft()
            {
                try
                {
                    _skipCallback = true;

                    rootLayout.Children.Clear();

                    DockPanel.SetDock(nameLabel, Dock.Left);
                    DockPanel.SetDock(unitLabel, Dock.Right);
                    DockPanel.SetDock(editboxContainer, Dock.Right);
                    DockPanel.SetDock(lockIcon, Dock.Right);

                    rootLayout.Children.Add(nameLabel);
                    rootLayout.Children.Add(unitLabel);
                    rootLayout.Children.Add(editboxContainer);
                    rootLayout.Children.Add(lockIcon);
                    rootLayout.Children.Add(sliderbar);

                    UpdateControlStatus();
                }
                catch
                {
                }
                finally
                {
                    _skipCallback = false;
                }
            }

            public void LabelAppearOnTop()
            {
                try
                {
                    _skipCallback = true;
                    rootLayout.Children.Clear();

                    DockPanel.SetDock(nameLabel, Dock.Top);
                    DockPanel.SetDock(lockIcon, Dock.Right);
                    DockPanel.SetDock(unitLabel, Dock.Right);
                    DockPanel.SetDock(editboxContainer, Dock.Right);
                    DockPanel.SetDock(sliderbar, Dock.Left);

                    DockPanel childPanel = new DockPanel();
                    DockPanel.SetDock(childPanel, Dock.Bottom);

                    childPanel.Children.Add(lockIcon);
                    childPanel.Children.Add(unitLabel);
                    childPanel.Children.Add(editboxContainer);
                    childPanel.Children.Add(sliderbar);

                    rootLayout.LastChildFill = false;

                    rootLayout.Children.Add(nameLabel);
                    rootLayout.Children.Add(childPanel);

                    UpdateControlStatus();
                }
                catch
                {
                }
                finally
                {
                    _skipCallback = false;
                }
            }

            public void LabelAppearOnBottom()
            {
                try
                {
                    _skipCallback = true;
                    rootLayout.Children.Clear();

                    DockPanel childPanel = new DockPanel();
                    DockPanel.SetDock(nameLabel, Dock.Bottom);

                    DockPanel.SetDock(lockIcon, Dock.Right);
                    DockPanel.SetDock(unitLabel, Dock.Right);
                    DockPanel.SetDock(editboxContainer, Dock.Right);
                    DockPanel.SetDock(sliderbar, Dock.Left);

                    childPanel.Children.Add(lockIcon);
                    childPanel.Children.Add(unitLabel);
                    childPanel.Children.Add(editboxContainer);
                    childPanel.Children.Add(sliderbar);

                    rootLayout.Children.Add(nameLabel);
                    rootLayout.Children.Add(childPanel);

                    UpdateControlStatus();
                }
                catch
                {
                }
                finally
                {
                    _skipCallback = false;
                }
            }
#endregion

#region SpinnerButton

            private void SyncSpinnerValue()
            {
                if (_pAliasNode != null && _pAliasNode.IsReadable)
                {
                    spinnerControl.ValueChanged -= spinnerControl_ValueChanged;
                    SpinnerValue = _pAliasNode.Value;
                    spinnerControl.ValueChanged += spinnerControl_ValueChanged;
                }
            }

            private void spinnerControl_MouseDoubleClick(object sender, MouseButtonEventArgs e)
            {
                e.Handled = true;
                return;
            }

            private void spinnerControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                if (e.ClickCount == 1)
                {
                    e.Handled = true;

                    var source = e.OriginalSource;

                    if (source != null && source.GetType() == typeof (Rectangle))
                    {
                        // Find out whether upper or lower button was clicked
                        Rectangle tempRect = source as Rectangle;

                        if (tempRect == null)
                        {
                            return;
                        }

                        SyncSpinnerValue();

                        if (tempRect.Name == "UpRect")
                        {
                            SpinnerValue++;
                        }
                        else if (tempRect.Name == "DownRect")
                        {
                            SpinnerValue--;
                        }

                        if (_nodeType == typeof (Integer))
                        {
                            AnalyticsNodeUpdateAction(analytics, _node, CurrentValue.ToString());
                        }
                        else if (_nodeType == typeof (Float))
                        {
                            AnalyticsNodeUpdateAction(analytics, _node, string.Format("{0:0.00}", CurrentValue));
                        }
                    }
                }
            }

            void spinnerControl_ValueChanged(object sender, RoutedPropertyChangedEventArgs<decimal>e)
            {
                if (_skipCallback)
                {
                    return;
                }

                if (_pAliasNode != null)
                {
                    try
                    {
                        if (_pAliasNode.IsWritable)
                        {
                            LogNodeUpdateAction(log, _pAliasNode, SpinnerValue.ToString());

                            _pAliasNode.Value = SpinnerValue;
                        }
                    }
                    catch (Exception ex)
                    {
                        log.Debug(
                            string.Format(
                                "{1}Problem updating pAlias \"{2}\" for {0} node.",
                                this._propertyToControl,
                                FormattedSerialNumber,
                                _pAliasNode.Name),
                            ex);
                    }
                }
            }
#endregion
            double log2Double(double position)
            {
                // position will be between 0 and 100
                int minp = 0;
                int maxp = 100;

                // The result should be between 100 an 10000000
                var minv = Math.Log(Min);
                var maxv = Math.Log(Max);

                // calculate adjustment factor
                var scale = (maxv - minv) / (maxp - minp);

                return Math.Exp(minv + scale * (position - minp));
            }

            double double2Log(double value)
            {
                // position will be between 0 and 100
                int minp = 0;
                int maxp = 100;

                // The result should be between 100 an 10000000
                var minv = Math.Log(Min);
                var maxv = Math.Log(Max);

                // calculate adjustment factor
                var scale = (maxv - minv) / (maxp - minp);

                return (Math.Log(value) - minv) / scale + minp;
            }

            private void editbox_GotFocus(object sender, RoutedEventArgs e)
            {
                editbox.SelectAll();
                BeginEdit();
            }
        }

    }
}