Skip to content

File SliderControl.xaml.cs

File List > PGRControls > SliderControl.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 SliderControl : BaseClass, IEditableObject
        {

#region Properties
            private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(SliderControl));
            private static readonly log4net.ILog analytics = log4net.LogManager.GetLogger("Analytics");

            // Basic Properties
            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 bool _disposed = false;
            private double _oldValue = 0;
            private double _smallIncrement = 1;
            private double _largeIncrement = 1;
            private double _min = 0;
            private double _max = 1;
            private bool _textChanged = false;
            private string _unit;
            private string _editBoxTooltip;
            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;

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

            // GenICam callback update thread
            BackgroundWorker _updateWorker;

#endregion

#region PROPERTIES
            public static DependencyProperty ValueProperty = DependencyProperty.Register(
                "CurrentValue",
                typeof(double),
                typeof(SliderControl),
                new FrameworkPropertyMetadata((double) 0, OnCurrentValuePropertyChanged));

            private static void OnCurrentValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                SliderControl control = d as SliderControl;
                if (control != null)
                {
                    control.NotifyPropertyChanged("CurrentValueFormatted");
                }
            }

            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 System.Windows.Visibility SpinButtonVisibility
            {
                get
                {
                    if (_pAliasNode == null)
                    {
                        return System.Windows.Visibility.Hidden;
                    }
                    else
                    {
                        return _SpinButtonVisibility;
                    }
                }
                set
                {
                    _SpinButtonVisibility = value;
                    NotifyPropertyChanged("SpinButtonVisibility");
                }
            }

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

            public double CurrentValue
            {
                get
                {
                    return (double) GetValue(ValueProperty);
                }
                set
                {
                    SetValue(ValueProperty, value);
                }
            }

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

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

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

            public double Min
            {
                get
                {
                    return _min;
                }
                set
                {
                    _min = value;
                    NotifyPropertyChanged("Min");
                }
            }

            public double Max
            {
                get
                {
                    return _max;
                }
                set
                {
                    _max = value;
                    NotifyPropertyChanged("Max");
                }
            }

            public double IncrementSmall
            {
                get
                {
                    return _smallIncrement;
                }
                set
                {
                    _smallIncrement = value;
                    NotifyPropertyChanged("IncrementSmall");
                }
            }

            public double IncrementLarge
            {
                get
                {
                    return _largeIncrement;
                }
                set
                {
                    _largeIncrement = value;
                    NotifyPropertyChanged("IncrementLarge");
                }
            }

            public string Unit
            {
                get
                {
                    return _unit;
                }
                set
                {
                    _unit = value;
                    NotifyPropertyChanged("Unit");
                }
            }

            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 SliderControl()
            {
                InitializeComponent();
                this.DataContext = this;
                _timer = new System.Windows.Forms.Timer();
                _updateWorker = new BackgroundWorker();
                _updateWorker.DoWork += _updateWorker_DoWork;
                _updateWorker.RunWorkerCompleted += _updateWorker_RunWorkerCompleted;
            }

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

            internal SliderControl(SliderControl 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
            override public void SetDecimalPlaces(int decimalPlaces)
            {
                this.DecimalPlaces = decimalPlaces;
                NotifyPropertyChanged("CurrentValueFormatted");
            }

            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()
            {
                Dispatcher.BeginInvoke(
                    (Action)(() => {
                        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;
                        }
                    }),
                    DispatcherPriority.Background,
                    null);
            }

            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 sliderbar.Minimum;
            }

            public override double GetMax()
            {
                return sliderbar.Maximum;
            }

            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;
                        SetToolTip(_node.ToolTip);
                    }
                    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.IsAvailable &&
                                _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();
                        _featureAvailable = true;
                    }
                    catch (System.Exception ex)
                    {
                        log.Warn(
                            string.Format(
                                "{1}Problem accessing {0} node.", this._propertyToControl, FormattedSerialNumber),
                            ex);
                        throw;
                    }
                    finally
                    {
                        _initializing = false;
                    }
                }
                else
                {
                    _featureAvailable = 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(() => {
                        if (_nodeMap == null)
                        {
                            // Nodemap is no longer valid. Control must have been disconnected.
                            return;
                        }

                        if (e.Error != null)
                        {
                            log.Debug(
                                string.Format(
                                    "{1}There was a problem updating control status for \"{0}\"",
                                    _propertyToControl,
                                    FormattedSerialNumber),
                                e.Error);
                            return;
                        }

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

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

                        LogNodeCallback(log, currentNodeStatus.NodeName, logMessage);

                        if (currentNodeStatus.IsReadable)
                        {
                            _skipCallback = true;
                            _initializing = true;
                            _isUpdating = true;

                            if (_controlNameLabel != currentNodeStatus.NodeDisplayName)
                            {
                                ControlNameLabel = currentNodeStatus.NodeDisplayName;
                            }

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

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

                            if (IsNodeReadable != (currentNodeStatus.IsReadable && currentNodeStatus.IsAvailable))
                            {
                                IsNodeReadable = currentNodeStatus.IsReadable && currentNodeStatus.IsAvailable;
                                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.IsReadable)
                            {
                                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;
                            }
                        }
                        else
                        {
                            base.IsEditable = false;
                            IsSliderBarEnabled = false;
                            IsEditboxReadOnly = true;
                            IsSpinnerControlEnabled = false;
                            SpinButtonVisibility = System.Windows.Visibility.Hidden;
                        }
                    });
                }
                catch (System.Exception ex)
                {
                    log.Debug(
                        string.Format(
                            "{1}Problem updating control for {0} node", _propertyToControl, FormattedSerialNumber),
                        ex);
                }
                finally
                {
                    _skipCallback = false;
                    _initializing = 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)
                {
                    return;
                }

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

                if (!IsVisible)
                {
                    return;
                }

                _updateWorker.RunWorkerAsync(node);
            }
#endregion

#region UI_CONTROL_UPDATE

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

                _textChanged = true;

                BeginEdit();

                if (!CheckValueBounds(editbox.Text))
                {
                    CancelEdit();
                }
            }

            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, CurrentValue.ToString());
                }
                else if (_nodeType == typeof (Float))
                {
                    AnalyticsNodeUpdateAction(analytics, _node, string.Format("{0:0.00}", CurrentValue));
                }
            }

            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;

                            // Special case for HexNumber Representation
                            if (_integerNode.Representation == SpinnakerNET.GenApi.Representation.HexNumber)
                            {
                                formattedInput.Replace("0x", "");
                            }

                            bool noError = true;
                            try
                            {
                                long.TryParse(formattedInput, out convertedInput);
                            }
                            catch
                            {
                                noError = false;
                            }

                            // Fallback for error case
                            if (!noError)
                            {
                                try
                                {
                                    long.TryParse(input, out convertedInput);
                                    noError = true;
                                }
                                catch
                                {
                                    noError = false;
                                }
                            }

                            if (noError)
                            {
                                if (convertedInput < Min)
                                {
                                    result = false;
                                    log.Warn(string.Format(
                                        "{3}{0} is below minimum allowable value of {1} for feature {2}.",
                                        formattedInput,
                                        Min,
                                        _propertyToControl,
                                        FormattedSerialNumber));
                                }
                                else if (convertedInput > Max)
                                {
                                    result = false;
                                    log.Warn(string.Format(
                                        "{3}{0} is above maximum allowable value of {1} for feature {2}.",
                                        formattedInput,
                                        Max,
                                        _propertyToControl,
                                        FormattedSerialNumber));
                                }
                            }
                            else
                            {
                                result = false;
                                log.Warn(string.Format(
                                    "{2}Invalid Input: {0} for feature {1}",
                                    formattedInput,
                                    _propertyToControl,
                                    FormattedSerialNumber));
                            }
                        }
                    }
                    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;

                            // Special case for HexNumber Representation
                            if (_floatNode.Representation == SpinnakerNET.GenApi.Representation.HexNumber)
                            {
                                formattedInput.Replace("0x", "");
                            }

                            bool noError = true;
                            try
                            {
                                float.TryParse(formattedInput, out convertedInput);
                            }
                            catch
                            {
                                noError = false;
                            }

                            // Fallback for error case
                            if (!noError)
                            {
                                try
                                {
                                    float.TryParse(input, out convertedInput);
                                    noError = true;
                                }
                                catch
                                {
                                    noError = false;
                                }
                            }
                            if (noError)
                            {
                                if (convertedInput < Min)
                                {
                                    result = false;
                                    log.Warn(string.Format(
                                        "{3}{0} is below minimum allowable value of {1} for feature {2}.",
                                        formattedInput,
                                        Min,
                                        _propertyToControl,
                                        FormattedSerialNumber));
                                }
                                else if (convertedInput > Max)
                                {
                                    result = false;
                                    log.Warn(string.Format(
                                        "{3}{0} is above maximum allowable value of {1} for feature {2}.",
                                        formattedInput,
                                        Max,
                                        _propertyToControl,
                                        FormattedSerialNumber));
                                }
                            }
                            else
                            {
                                result = false;
                                log.Warn(string.Format(
                                    "{2}Invalid Input: {0} for feature {1}",
                                    formattedInput,
                                    _propertyToControl,
                                    FormattedSerialNumber));
                            }
                        }
                    }
                    catch (System.Exception /*ex*/)
                    {
                    }
                }

                return result;
            }

            private void UpdateControlStatus()
            {
                try
                {
                    if (_node == null || !_node.IsAvailable || !_node.IsImplemented)
                    {
                        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(
                            "{1}There was a problem updating control status for \"{0}\"",
                            _propertyToControl,
                            FormattedSerialNumber),
                        ex);
                    throw new Exception(ex.Message);
                }
            }

            private void UpdateControlValues(Type type, INodeMap nodemap, string nodename, string namelabel = "")
            {
                // Sanity check
                if (nodemap == null)
                {
                    return;
                }

                if (type == typeof (Float))
                {
                    try
                    {
                        _floatNode = nodemap.GetNode<IFloat>(nodename);
                    }
                    catch (System.Exception ex)
                    {
                        log.Error(
                            string.Format("{0}Problem accessing {1} from Nodemap.", FormattedSerialNumber, nodename),
                            ex);
                        return;
                    }

                    ControlNameLabel = namelabel.Length == 0 ? _floatNode.DisplayName : namelabel;
                    Unit = _floatNode.Unit;

                    // Set display precision from camera XML
                    if (_floatNode.IsReadable)
                    {
                        try
                        {
                            SetDecimalPlaces(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 && _floatNode.IsAvailable;

                    if (IsNodeReadable)
                    {
                        try
                        {
                            _skipCallback = true;

                            if (Min != _floatNode.Min)
                            {
                                Min = _floatNode.Min;
                            }

                            if (Max != _floatNode.Max)
                            {
                                Max = _floatNode.Max;
                            }

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

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

                    this.sliderbar.IsSnapToTickEnabled = true;

                    // Update _isReadable
                    IsNodeReadable = _integerNode.IsReadable && _integerNode.IsAvailable;

                    if (IsNodeReadable)
                    {
                        try
                        {
                            _skipCallback = true;

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

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

                            CurrentValue = _integerNode.Value;
                            NotifyPropertyChanged("CurrentValueFormatted");
                        }
                        catch (Exception ex)
                        {
                            log.Error(
                                string.Format(
                                    "{1}There was a problem fetching node value for \"{0}\"",
                                    _propertyToControl,
                                    FormattedSerialNumber),
                                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.Error(string.Format(
                        "{0}Unexpected control type for {1} node from Nodemap.", FormattedSerialNumber, nodename));
                    throw new Exception(string.Format("Unexpected control type!"));
                }

                try
                {
                    EditBoxTooltip = string.Format("Min: {0}, Max: {1}", Min.ToString("G5"), Max.ToString("G5"));
                }
                catch (System.Exception /*ex*/)
                {
                }
            }
#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*/)
                {
                    log.Warn(string.Format(
                        "{1}Problem retrieving new value from {0} node", _propertyToControl, FormattedSerialNumber));
                }
            }

            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 (Exception /*ex*/)
                    {
                    }
                }
                else if (e.Key == Key.Escape)
                {
                    CancelEdit();
                }
            }

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

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

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

            private void sliderbar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double>e)
            {
                if (_skipCallback || _initializing)
                {
                    return;
                }
                if (!_dragStarted)
                {
                    UpdateNodeValue(e.NewValue, e.OldValue);
                }
            }

#endregion

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

            public void CancelEdit()
            {
                CurrentValue = _oldValue;
            }

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

#region HELPERS
            private bool UpdateNodeValue(double newValue, double oldValue = 0)
            {
                if (_initializing)
                {
                    return false;
                }

                bool result = true;

                if (_nodeType == typeof (Integer))
                {
                    try
                    {
                        if (_integerNode != null && _integerNode.IsWritable)
                        {
                            double currentNodeValue = _integerNode.Value;
                            double nodeMinimumValue = _integerNode.Min;
                            double nodeMaximumValue = _integerNode.Max;
                            double tempValue = newValue;
                            IncrementSmall = _integerNode.Increment;
                            IncrementLarge = IncrementSmall * 2;

                            if ((nodeMaximumValue - nodeMinimumValue) % IncrementSmall != 0)
                            {
                                // Special case where (Max - Min) is not dividable by Increment
                                while ((tempValue - nodeMinimumValue) % IncrementSmall != 0)
                                {
                                    if (tempValue < currentNodeValue)
                                    {
                                        tempValue--;
                                    }
                                    else
                                    {
                                        tempValue++;
                                    }

                                    if (tempValue >= nodeMaximumValue)
                                    {
                                        // find closest allowable value near Max
                                        tempValue--;

                                        while ((tempValue - nodeMinimumValue) % IncrementSmall != 0)
                                        {
                                            tempValue--;
                                        }

                                        break;
                                    }
                                    else if (tempValue < nodeMinimumValue)
                                    {
                                        tempValue = nodeMinimumValue;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                while ((tempValue - nodeMinimumValue) % IncrementSmall != 0)
                                {
                                    if (tempValue < currentNodeValue)
                                    {
                                        tempValue--;
                                    }
                                    else
                                    {
                                        tempValue++;
                                    }

                                    if (tempValue >= nodeMaximumValue)
                                    {
                                        tempValue = nodeMaximumValue;
                                        break;
                                    }
                                    else if (tempValue < nodeMinimumValue)
                                    {
                                        tempValue = nodeMinimumValue;
                                        break;
                                    }
                                }
                            }
                            newValue = tempValue;

                            _skipCallback = true;
                            _integerNode.Value = (long) newValue;
                            LogNodeUpdateAction(log, _node, newValue.ToString());
                            _skipCallback = false;
                        }
                        else
                        {
                            log.Debug(string.Format(
                                "{1}{0} node is currently not writable.", _propertyToControl, FormattedSerialNumber));
                            result = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        result = false;
                        log.Error(
                            string.Format("{1}Problem updating {0} node.", _propertyToControl, FormattedSerialNumber),
                            ex);
                    }
                    finally
                    {
                        // read value back from node
                        if (_integerNode != null && _integerNode.IsReadable)
                        {
                            _skipCallback = true;
                            sliderbar.Value = _integerNode.Value;
                            _skipCallback = false;
                        }
                    }
                }
                else if (_nodeType == typeof (Float))
                {
                    bool success = false;
                    try
                    {
                        if (_floatNode != null && _floatNode.IsWritable)
                        {
                            double increment;
                            if (TryGetFloatIncrement(_floatNode, out increment))
                            {
                                newValue = NormalizeValueToIncrement(newValue, _floatNode.Min, _floatNode.Max, increment);
                            }

                            int count = 0;
                            while (!success && count < k_numOfRetried)
                            {
                                try
                                {
                                    _skipCallback = true;
                                    _floatNode.Value = newValue;
                                    LogNodeUpdateAction(log, _node, newValue.ToString());
                                    success = true;
                                }
                                catch (System.Exception /*ex*/)
                                {
                                    count++;
                                }
                                finally
                                {
                                    _skipCallback = false;
                                }
                            }
                        }
                        else
                        {
                            log.Debug(string.Format(
                                "{1}{0} node is currently not writable.", _propertyToControl, FormattedSerialNumber));
                            result = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        result = false;
                        log.Error(
                            string.Format(
                                "{1}Problem updating node value for feature {0}.",
                                _propertyToControl,
                                FormattedSerialNumber),
                            ex);
                    }
                    finally
                    {
                        // read new value back from node
                        if (_floatNode != null && _floatNode.IsReadable)
                        {
                            _skipCallback = true;
                            sliderbar.Value = _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(lockIconBtn, Dock.Left);
                    DockPanel.SetDock(sliderbar, Dock.Left);

                    rootLayout.Children.Add(nameLabel);
                    rootLayout.Children.Add(editboxContainer);
                    rootLayout.Children.Add(unitLabel);
                    rootLayout.Children.Add(lockIconBtn);
                    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(lockIconBtn, Dock.Right);

                    rootLayout.Children.Add(nameLabel);
                    rootLayout.Children.Add(unitLabel);
                    rootLayout.Children.Add(editboxContainer);
                    rootLayout.Children.Add(lockIconBtn);
                    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(lockIconBtn, 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(lockIconBtn);
                    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(lockIconBtn, Dock.Right);
                    DockPanel.SetDock(unitLabel, Dock.Right);
                    DockPanel.SetDock(editboxContainer, Dock.Right);
                    DockPanel.SetDock(sliderbar, Dock.Left);

                    childPanel.Children.Add(lockIconBtn);
                    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
            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);
                    }
                }
            }

            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));
                        }
                    }
                }
            }
#endregion

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

    }
}