Skip to content

File EditBoxControl.xaml.cs

File List > PGRControls > EditBoxControl.xaml.cs

Go to the documentation of this file

//=============================================================================
// Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR)
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Diagnostics;
using System.Windows.Threading;
using System.ComponentModel;
using System.Windows.Shapes;
using SpinnakerNET.GenApi;
using System.Runtime.ExceptionServices;
using System.Security;
using System.Threading;

namespace SpinnakerNET.GUI
{
    namespace WPFControls
    {


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

#region Properties
            // Basic Properties
            private INode _node;
            private IInteger _integerNode;
            private IFloat _floatNode;
            private IString _stringNode;
            private double _min, _max, _increment;
            private bool _integerDisplay = false;
            private string _currentValue;
            private bool _skipCallback = false;
            private bool _disposed = false;
            private double _oldValue = 0;
            private bool _textChanged = false;
            private bool _isEditboxEnabled;
            private bool _isEditboxReadOnly;
            private bool _isSpinnerControlEnabled;

            // GenICam callback update thread
            BackgroundWorker _updateWorker;

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

            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 long SpinnerValue
            {
                get
                {
                    return _spinnerValue;
                }
                set
                {
                    _spinnerValue = value;
                    NotifyPropertyChanged("SpinnerValue");
                }
            }


            public string CurrentValue
            {
                get
                {
                    return _currentValue;
                }
                set
                {
                    _currentValue = value;
                    NotifyPropertyChanged("CurrentValue");
                }
            }

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

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

            public double Increment
            {
                get
                {
                    return _increment;
                }
                set
                {
                    _increment = value;
                    NotifyPropertyChanged("Increment");
                }
            }

            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 override int RefreshTime
            {
                get
                {
                    return _refreshTime;
                }
                set
                {
                    this._refreshTime = value;
                }
            }

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

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

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

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

            ~EditBoxControl()
            {
                Disconnect();
            }

            internal EditBoxControl(EditBoxControl 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());

                // Editbox specific properties
                this.UnitLabelVisibility = originalControl.UnitLabelVisibility;
                this.SetIntegerDisplay(originalControl.GetIntegerDisplay());
                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 ICameraControlInterface

            public override void SetMin(double min)
            {
                this.Min = min;
            }

            public override void SetMax(double max)
            {
                this.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(System.Windows.Visibility visibility)
            {
                this.editbox.Visibility = visibility;
            }

            public override double GetMin()
            {
                return _min;
            }

            public override double GetMax()
            {
                return _max;
            }

            public void SetIntegerDisplay(bool status)
            {
                _integerDisplay = status;
            }

            public bool GetIntegerDisplay()
            {
                return _integerDisplay;
            }

            public override void Connect(INodeMap nodemap, string nodename, string label = "")
            {
                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();
                        SetToolTip(_node.ToolTip.ToString());

                        _featureAvailable = _node.IsImplemented;
                    }
                    catch (System.Exception ex)
                    {
                        _featureAvailable = false;
                        UpdateControlStatus();
                        log.Debug(
                            string.Format("{1}Problem fetching {0} feature.", PropertyToControl, FormattedSerialNumber),
                            ex);
                        throw new Exception(string.Format("Problem connecting to {0}!", PropertyToControl));
                    }
                }

                _initializing = true;

                try
                {
                    // Determine whether Spinbutton is visible
                    if (this._nodeType == typeof (Float))
                    {
                        if (_floatNode == null)
                        {
                            _floatNode = nodemap.GetNode<IFloat>(nodename);
                        }

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

                    UpdateControlValues(this._nodeType, this._nodeMap, this._propertyToControl, label);
                    UpdateControlStatus();
                    RegisterGenICamCallbacks();
                    // RegisterInterfaceEvents();
                    _featureAvailable = _node.IsImplemented;
                }
                catch (System.Exception ex)
                {
                    log.Error(
                        string.Format("{1}Problem accessing {0} node.", this._propertyToControl, FormattedSerialNumber),
                        ex);
                    throw new Exception(
                        string.Format("Problem accessing {0} node. {1}", this._propertyToControl, ex.Message));
                }
                finally
                {
                    _initializing = false;
                }
            }

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

                    if (_integerNode != null && _callbackRegistered)
                    {
                        _integerNode.Updated -= Node_Updated;
                    }

                    if (_stringNode != null && _callbackRegistered)
                    {
                        _stringNode.Updated -= Node_Updated;
                    }
                }
                catch (System.Exception ex)
                {
                    Debug.WriteLine("Problem unregsitering callbacks for {0}. {1}", PropertyToControl, ex.Message);
                }

                _mapper = null;
                _node = null;
                _integerNode = null;
                _floatNode = null;
                _stringNode = null;
                _pAliasNode = null;
                _nodeMap = null;
                base.Disconnect();
            }
#endregion

#region GENICAM_CALLBACK
            private void RegisterGenICamCallbacks()
            {
                if (_nodeType == typeof (Float) && _floatNode != null)
                {
                    _floatNode.Updated += Node_Updated;
                }

                if ((_nodeType == typeof (Integer) || _nodeType == typeof (IntReg)) && _integerNode != null)
                {
                    _integerNode.Updated += Node_Updated;
                }

                if ((_nodeType == typeof (String) || _nodeType == typeof (StringReg)) && _stringNode != null)
                {
                    _stringNode.Updated += Node_Updated;
                }

                _callbackRegistered = true;
            }

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

                if (e.Cancelled)
                {
                    return;
                }

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

                try
                {
                    Dispatcher.Invoke(() => {
                        _isUpdating = true;
                        _initializing = true;
                        _skipCallback = true;

                        INode node = e.Result as INode;
                        NodeStatus currentNodeStatus;
                        try
                        {
                            currentNodeStatus = new NodeStatus(node);
                            if (currentNodeStatus.ExceptionObject != null)
                            {
                                return;
                            }
                        }
                        catch (Exception)
                        {
                            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 (_controlNameLabel != currentNodeStatus.NodeDisplayName)
                        {
                            SetControlNameLabel(currentNodeStatus.NodeDisplayName);
                        }

                        bool userEditing = this.editbox.IsFocused && IsEditable;
                        if (currentNodeStatus.IsReadable && !userEditing &&
                            CurrentValue != currentNodeStatus.CurrentStringValue)
                        {
                            IsEditboxReadOnly = false;
                            IsEditboxEnabled = true;
                            IsSpinnerControlEnabled = true;
                            CurrentValue = currentNodeStatus.CurrentStringValue;
                            refreshNeeded = true;
                        }

                        if (!userEditing && CurrentValue != currentNodeStatus.CurrentStringValue)
                        {
                            refreshNeeded = true;
                        }

                        if (!currentNodeStatus.IsAvailable)
                        {
                            IsEditable = false;
                            IsEditboxEnabled = false;
                            IsSpinnerControlEnabled = false;
                        }

                        if (!currentNodeStatus.IsWritable)
                        {
                            IsEditboxReadOnly = true;
                            IsSpinnerControlEnabled = false;
                            IsEditable = false;
                        }
                        else
                        {
                            IsEditable = true;

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

                if (!refreshNeeded)
                {
                    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)
            {
                if (_skipCallback)
                {
                    return;
                }

                if (_nodeMap == null)
                {
                    return;
                }

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

                if (!IsVisible)
                {
                    return;
                }

                _updateWorker.RunWorkerAsync(node);
            }
#endregion

#region UI_CONTROL_UPDATE

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

                BeginEdit();
            }

            private void UpdateControlStatus()
            {
                if (_nodeMap == null)
                {
                    IsEditable = false;
                    IsEditboxEnabled = false;
                    IsSpinnerControlEnabled = false;
                    return;
                }

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

                    if (node == null || !node.IsAvailable)
                    {
                        IsEditable = false;
                        IsEditboxEnabled = false;
                        IsSpinnerControlEnabled = false;
                        return;
                    }

                    if (!node.IsWritable)
                    {
                        IsEditboxReadOnly = true;
                        IsSpinnerControlEnabled = false;
                        IsEditable = false;
                        return;
                    }
                    else
                    {
                        IsEditable = true;

                        IsEditboxReadOnly = false;
                        IsSpinnerControlEnabled = true;
                        IsEditboxEnabled = true;
                    }
                }
                catch (System.Exception /*ex*/)
                {
                }
            }

            private void UpdateControlValues(Type type, INodeMap nodemap, string nodename, string namelabel = "")
            {
                bool userEditing = this.editbox.IsFocused && IsEditable;
                if (userEditing)
                {
                    return;
                }

                if (type == typeof (Float))
                {
                    try
                    {
                        _skipCallback = true;

                        if (_floatNode == null)
                        {
                            _floatNode = nodemap.GetNode<IFloat>(nodename);
                        }

                        if (_floatNode.IsReadable)
                        {
                            Min = _floatNode.Min;
                            Max = _floatNode.Max;

                            if (_mapper != null)
                            {
                                CurrentValue = _mapper.FormatNodeValueToString(_propertyToControl, "", DecimalPlaces);
                            }
                            else
                            {
                                CurrentValue = NumericFormatter.FormatNumericToString(_floatNode.Value, DecimalPlaces);
                            }
                        }
                        else
                        {
                            CurrentValue = "N/A";
                        }
                        ControlNameLabel = namelabel.Length == 0 ? _floatNode.DisplayName : namelabel;
                        Unit = _floatNode.Unit;

                        // Update spinner
                        SyncSpinnerValue();

                        // Set tooltip
                        nameLabel.ToolTip = _floatNode.ToolTip;

                        try
                        {
                            editbox.ToolTip =
                                string.Format("Min: {0}, Max: {1}", Min.ToString("G5"), Max.ToString("G5"));
                        }
                        catch (System.Exception ex)
                        {
                            log.Debug(string.Format(
                                "{2}{1} - Problem updating tooltip. {0}",
                                ex.Message,
                                _propertyToControl,
                                FormattedSerialNumber));
                        }
                    }
                    catch (System.Exception ex)
                    {
                        log.Warn(string.Format(
                            "{2}{1} - Problem retrieving node value. {0}",
                            ex.Message,
                            _propertyToControl,
                            FormattedSerialNumber));
                    }
                    finally
                    {
                        _skipCallback = false;
                    }
                }
                else if (type == typeof (StringNode) || type == typeof (StringReg))
                {
                    try
                    {
                        _skipCallback = true;

                        if (_stringNode == null)
                        {
                            _stringNode = nodemap.GetNode<IString>(nodename);
                        }

                        if (_stringNode.IsReadable)
                        {
                            if (_mapper != null)
                            {
                                CurrentValue = _mapper.FormatNodeValueToString(_propertyToControl);
                            }
                            else
                            {
                                CurrentValue = _stringNode.Value.ToString();
                            }
                        }
                        else
                        {
                            CurrentValue = "N/A";
                        }
                        ControlNameLabel = namelabel.Length == 0 ? _stringNode.DisplayName : namelabel;

                        // Set tooltip
                        nameLabel.ToolTip = _stringNode.ToolTip;

                        try
                        {
                            editbox.ToolTip = _stringNode.ToolTip;
                        }
                        catch (System.Exception ex)
                        {
                            log.Debug(string.Format(
                                "{2}{1} - Problem updating tooltip. {0}",
                                ex.Message,
                                _propertyToControl,
                                FormattedSerialNumber));
                        }
                    }
                    catch (System.Exception ex)
                    {
                        log.Warn(string.Format(
                            "{2}{1} - Problem retrieving node value. {0}",
                            ex.Message,
                            _propertyToControl,
                            FormattedSerialNumber));
                    }
                    finally
                    {
                        _skipCallback = false;
                    }
                }
                else if (type == typeof (Integer) || type == typeof (IntReg))
                {
                    DateTime now = DateTime.Now;
                    try
                    {
                        _skipCallback = true;

                        if (_integerNode == null)
                        {
                            _integerNode = nodemap.GetNode<IInteger>(nodename);
                        }

                        DateTime conversionStart = DateTime.Now;
                        if (_integerNode.IsReadable)
                        {
                            Min = _integerNode.Min;
                            Max = _integerNode.Max;
                            Increment = _integerNode.Increment;

                            if (_mapper != null)
                            {
                                CurrentValue = _mapper.FormatNodeValueToString(_propertyToControl, type, nodemap);
                            }
                            else
                            {
                                CurrentValue = _integerNode.Value.ToString();
                            }
                        }
                        else
                        {
                            CurrentValue = "N/A";
                        }

                        ControlNameLabel = namelabel.Length == 0 ? _integerNode.DisplayName : namelabel;
                        // No unit available for IInteger node
                        Unit = string.Empty;
                        // Set tooltip
                        nameLabel.ToolTip = _integerNode.ToolTip;
                        TimeSpan s = DateTime.Now - now;

                        try
                        {
                            editbox.ToolTip =
                                string.Format("Min: {0}, Max: {1}", Min.ToString("G5"), Max.ToString("G5"));
                        }
                        catch (System.Exception ex)
                        {
                            log.Debug(string.Format(
                                "{2}{1} - Problem updating tooltip. {0}",
                                ex.Message,
                                _propertyToControl,
                                FormattedSerialNumber));
                        }
                    }
                    catch (System.Exception ex)
                    {
                        log.Warn(string.Format(
                            "{2}{1} - Problem retrieving node value. {0}",
                            ex.Message,
                            _propertyToControl,
                            FormattedSerialNumber));
                        return;
                    }
                    finally
                    {
                        _skipCallback = false;
                    }
                }
                else
                {
                    // Unhandled node type detected
                    log.Debug(
                        string.Format("{1}{0} - Unexpected control type!", _propertyToControl, FormattedSerialNumber));
                }
            }
#endregion

#region Event Handlers
            void timer_Tick(object sender, EventArgs e)
            {
                try
                {
                    Refresh();
                }
                catch (System.Exception /*ex*/)
                {
                    Debug.WriteLine(string.Format("Problem retrieving new value from {0} node", _propertyToControl));
                }
            }

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

            private void editbox_TextChanged(object sender, TextChangedEventArgs e)
            {
                _textChanged = true;
            }

            private void editbox_LostFocus(object sender, RoutedEventArgs e)
            {
                if (!IsEditable)
                {
                    return;
                }

                if (CheckValueBounds(editbox.Text))
                {
                    EndEdit();

                    if (_textChanged)
                    {
                        UpdateNodeValue();
                        UpdateControlValues(this._nodeType, this._nodeMap, this._propertyToControl, ControlNameLabel);
                        SyncSpinnerValue();
                    }

                    UnfocusControl(editbox);
                }
                else
                {
                    CancelEdit();
                    UnfocusControl(editbox);
                }

                _textChanged = false;
            }

            private void editbox_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.Enter)
                {
                    if (CheckValueBounds(editbox.Text))
                    {
                        EndEdit();
                        UpdateNodeValue();
                        UpdateControlValues(this._nodeType, this._nodeMap, this._propertyToControl, ControlNameLabel);
                        UnfocusControl(editbox);
                        SyncSpinnerValue();
                    }
                    else
                    {
                        CancelEdit();
                        UnfocusControl(editbox);
                    }
                }
                else if (e.Key == Key.Escape)
                {
                    CancelEdit();
                    UnfocusControl(editbox);
                }
            }

            // private void editbox_PreviewTextInput(object sender, TextCompositionEventArgs e)
            //{
            //    e.Handled = !CheckValueBounds(e.Text);
            //}

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

            public void CancelEdit()
            {
                editbox.Text = _oldValue.ToString();
            }

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

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

                            // Check for hex
                            if (formattedInput.ToLower().Contains("0x"))
                            {
                                // Convert hex to decimal so we can compare it against Min and Max
                                long decValue = Convert.ToInt64(formattedInput, 16);

                                formattedInput = decValue.ToString();
                            }

                            long convertedInput = 0;

                            if (long.TryParse(formattedInput, out convertedInput))
                            {
                                if (convertedInput < _integerNode.Min)
                                {
                                    result = false;
                                    log.Warn(string.Format(
                                        "{3}{2} - {0} is below minimum range of {1}.",
                                        formattedInput,
                                        _integerNode.Min,
                                        _propertyToControl,
                                        FormattedSerialNumber));
                                }
                                else if (convertedInput > _integerNode.Max)
                                {
                                    result = false;
                                    log.Warn(string.Format(
                                        "{3}{2} - {0} is above maximum range of {1}.",
                                        formattedInput,
                                        _integerNode.Max,
                                        _propertyToControl,
                                        FormattedSerialNumber));
                                }
                            }
                            else
                            {
                                result = false;
                                log.Warn(string.Format(
                                    "{2}{1} - Invalid Input: {0}", input, _propertyToControl, FormattedSerialNumber));
                            }
                        }
                    }
                    catch
                    {
                    }
                }
                else if (_nodeType == typeof (Float))
                {
                    try
                    {
                        if (_floatNode != null && _floatNode.IsWritable)
                        {
                            string formattedInput;

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

                            // Check for hex
                            if (formattedInput.ToLower().Contains("0x"))
                            {
                                // Let's remove "0x" prefix
                                formattedInput = formattedInput.ToLower().Replace("0x", "");

                                long decValue = Convert.ToInt64(formattedInput, 16);

                                formattedInput = decValue.ToString();
                            }

                            double convertedInput = 0;

                            if (double.TryParse(formattedInput, out convertedInput))
                            {
                                if (convertedInput < _floatNode.Min)
                                {
                                    result = false;
                                    log.Warn(string.Format(
                                        "{3}{2} - {0} is below minimum range of {1}.",
                                        formattedInput,
                                        _floatNode.Min,
                                        _propertyToControl,
                                        FormattedSerialNumber));
                                }
                                else if (convertedInput > _floatNode.Max)
                                {
                                    result = false;
                                    log.Warn(string.Format(
                                        "{3}{2} - {0} is above maximum range of {1}.",
                                        formattedInput,
                                        _floatNode.Max,
                                        _propertyToControl,
                                        FormattedSerialNumber));
                                }
                            }
                            else
                            {
                                result = false;
                                log.Warn(string.Format(
                                    "{2}{1} - Invalid Input: {0}", input, _propertyToControl, FormattedSerialNumber));
                            }
                        }
                    }
                    catch (System.Exception /*ex*/)
                    {
                    }
                }

                return result;
            }

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

                bool result = true;

                if (_nodeType == typeof (Integer) || _nodeType == typeof (IntReg))
                {
                    try
                    {
                        _skipCallback = true;
                        if (_integerNode != null && _integerNode.IsWritable)
                        {
                            string input = editbox.Text;

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

                            if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                            {
                                // Convert hex to decimal
                                long decValue = Convert.ToInt64(input, 16);

                                input = decValue.ToString();
                            }

                            long convertedInput = 0;

                            // Log user initiated changes
                            LogNodeUpdateAction(log, _integerNode, editbox.Text);
                            AnalyticsNodeUpdateAction(analytics, _integerNode, editbox.Text);

                            if (long.TryParse(input, out convertedInput))
                            {
                                _integerNode.Value = convertedInput;
                            }
                            else
                            {
                                CurrentValue = _oldValue.ToString();
                                log.Error(string.Format(
                                    "Node {0}: can't convert string {1} to long", _propertyToControl, input));
                            }
                        }
                        else
                        {
                            Debug.WriteLine(string.Format("{0} node is currently not writable.", _propertyToControl));
                            result = false;
                        }

                        // read value back from node
                        if (_mapper != null)
                        {
                            CurrentValue = _mapper.FormatNodeValueToString(_propertyToControl);
                        }
                        else
                        {
                            CurrentValue = _integerNode.Value.ToString();
                        }
                    }
                    catch (Exception ex)
                    {
                        result = false;
                        UnfocusControl(this);
                        log.Error(string.Format(
                            "{2}{1} - Problem updating node value. {0}",
                            ex.Message,
                            _propertyToControl,
                            FormattedSerialNumber));
                    }
                    finally
                    {
                        _skipCallback = false;
                    }
                }
                else if (_nodeType == typeof (StringNode) || _nodeType == typeof (StringReg))
                {
                    try
                    {
                        _skipCallback = true;
                        if (_stringNode != null && _stringNode.IsWritable)
                        {
                            string input = editbox.Text;

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

                            // Log user initiated changes
                            LogNodeUpdateAction(log, _stringNode, editbox.Text);
                            AnalyticsNodeUpdateAction(analytics, _stringNode, editbox.Text);

                            // Write new value back to node
                            _stringNode.Value = input;

                            // read value back from node
                            if (_mapper != null)
                            {
                                CurrentValue = _mapper.FormatNodeValueToString(_propertyToControl);
                            }
                            else
                            {
                                CurrentValue = _stringNode.Value.ToString();
                            }
                        }
                        else
                        {
                            log.Warn(string.Format(
                                "{1}{0} node is currently not writable.", _propertyToControl, FormattedSerialNumber));
                            result = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        result = false;
                        UnfocusControl(this);
                        log.Error(
                            string.Format(
                                "{1}{0} - Problem updating node value.", _propertyToControl, FormattedSerialNumber),
                            ex);
                    }
                    finally
                    {
                        _skipCallback = false;
                    }
                }
                else if (_nodeType == typeof (Float))
                {
                    try
                    {
                        _skipCallback = true;

                        if (_floatNode != null && _floatNode.IsWritable)
                        {
                            string input;

                            if (editbox.Text.ToLower().Contains("0x"))
                            {
                                // Let's remove "0x" prefix
                                input = editbox.Text.ToLower().Replace("0x", "");
                            }
                            else
                            {
                                input = editbox.Text;
                            }

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

                            float convertedInput = 0;

                            if (float.TryParse(input, out convertedInput))
                            {
                                // Log user initiated changes
                                LogNodeUpdateAction(log, _floatNode, editbox.Text);
                                AnalyticsNodeUpdateAction(analytics, _floatNode, editbox.Text);

                                _floatNode.Value = convertedInput;
                            }
                            else
                            {
                                // Abort updating node's value
                                // show old value on screen
                                CurrentValue = _oldValue.ToString();
                                log.Error(string.Format(
                                    "Node {0}: can't convert string {1} to long", _propertyToControl, input));
                            }

                            // read new value back from node
                            if (_mapper != null)
                            {
                                CurrentValue = _mapper.FormatNodeValueToString(_propertyToControl);
                            }
                            else
                            {
                                CurrentValue = _floatNode.Value.ToString();
                            }
                        }
                        else
                        {
                            log.Warn(string.Format(
                                "{1}{0} node is currently not writable.", _propertyToControl, FormattedSerialNumber));
                            result = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        result = false;
                        UnfocusControl(this);
                        log.Error(
                            string.Format(
                                "{1}{0} - Problem updating node value. {0}", _propertyToControl, FormattedSerialNumber),
                            ex);
                    }
                    finally
                    {
                        _skipCallback = false;
                    }
                }

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

                return result;
            }
#endregion

#region ORIENTATION_CONTROL
            public override Orientation ContentOrientation
            {
                get
                {
                    return rootLayout.Orientation;
                }
                set
                {
                    rootLayout.Orientation = value;
                }
            }

            public void SetContentOrientation(Orientation newOrientation)
            {
                this.ContentOrientation = newOrientation;
            }

            public Orientation GetContetntOrientation()
            {
                return this.ContentOrientation;
            }
#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 == 2)
                {
                    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--;
                        }
                    }
                }
            }

            private void _aliasNodeUpdateWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if (_nodeMap == null)
                {
                    // Nodemap is no longer valid. Control must have been disconnected.
                    return;
                }

                try
                {
                    _skipCallback = true;
                    _initializing = true;
                    NodeStatus currentNodeStatus = (NodeStatus) e.Result;

                    if (!currentNodeStatus.IsReadable)
                    {
                        return;
                    }

                    Type type = currentNodeStatus.NodeType;
                    if (type == typeof (Integer) || type == typeof (IntReg))
                    {

                        if (_spinnerValue != (long) currentNodeStatus.CurrentValue)
                        {
                            SpinnerValue = (long) currentNodeStatus.CurrentValue;
                        }
                    }
                }
                catch (System.Exception /*ex*/)
                {
                }
                finally
                {
                    _skipCallback = false;
                    _initializing = false;
                }
            }

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

                if (_pAliasNode != null)
                {
                    try
                    {
                        if (_pAliasNode.IsWritable)
                        {
                            _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

#region HELPER
            private void UnfocusControl(UIElement element)
            {
                var scope = FocusManager.GetFocusScope(element); // elem is the UIElement to un-focus
                FocusManager.SetFocusedElement(scope, null);     // remove logical focus
                Keyboard.ClearFocus();                           // remove keyboard focus
            }
#endregion
        }

    }
}