File ButtonControl.xaml.cs¶
File List > PGRControls > ButtonControl.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.Windows.Threading;
using SpinnakerNET.GenApi;
using System.ComponentModel;
using System.Runtime.ExceptionServices;
using System.Security;
using System.Threading;
namespace SpinnakerNET.GUI
{
namespace WPFControls
{
public sealed partial class ButtonControl : BaseClass
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(ButtonControl));
private static readonly log4net.ILog analytics = log4net.LogManager.GetLogger("Analytics");
#region Properties
// Basic Properties
private SpinnakerNET.GenApi.ICommand _commandNode;
private bool _disposed = false;
private string _buttonLabel = "Execute";
private bool _isButtonEnabled;
// GenICam callback update thread
BackgroundWorker _updateWorker;
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);
}
public bool IsButtonEnabled
{
get
{
return _isButtonEnabled;
}
set
{
_isButtonEnabled = value;
NotifyPropertyChanged("IsButtonEnabled");
}
}
public System.Windows.Visibility ButtonVisibility
{
get
{
return this.button.Visibility;
}
set
{
this.button.Visibility = value;
NotifyPropertyChanged("ButtonVisibility");
}
}
public string ButtonLabel
{
get
{
return _buttonLabel;
}
set
{
_buttonLabel = value;
NotifyPropertyChanged("ButtonLabel");
}
}
#endregion
#region CONSTRUCTOR
public ButtonControl()
{
InitializeComponent();
_updateWorker = new BackgroundWorker();
_updateWorker.DoWork += _updateWorker_DoWork;
_updateWorker.RunWorkerCompleted += _updateWorker_RunWorkerCompleted;
}
// Copy Constructor
internal ButtonControl(ButtonControl originalControl)
{
InitializeComponent();
_updateWorker = new BackgroundWorker();
_updateWorker.DoWork += _updateWorker_DoWork;
_updateWorker.RunWorkerCompleted += _updateWorker_RunWorkerCompleted;
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());
}
#endregion
#region IPGRControlInterface
public void SetButtonLabel(string label)
{
ButtonLabel = label;
}
public override void Refresh()
{
UpdateControlStatus();
}
public string GetButtonLabel()
{
return ButtonLabel;
}
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
{
IValue node = nodemap.GetNode<IValue>(nodename);
if (node == null)
{
throw new Exception("Feature not found");
}
this._nodeType = node.GetType();
if (_nodeType != typeof (Command))
{
log.Error(string.Format("{1}{0} is not a command node!", nodename, FormattedSerialNumber));
throw new Exception(
string.Format("{1}{0} is not a command node!", nodename, FormattedSerialNumber));
}
_featureAvailable = node.IsImplemented;
}
catch (System.Exception ex)
{
log.Debug(string.Format(
"{2}Problem connecting to node {0} {1}!", nodename, ex.Message, FormattedSerialNumber));
_featureAvailable = false;
UpdateControlStatus();
throw new Exception(
string.Format("Problem accessing {0} node. {1}", this._propertyToControl, ex.Message));
}
_initializing = true;
try
{
UpdateControlValues(this._nodeType, this._nodeMap, this._propertyToControl, label);
UpdateControlStatus();
RegisterGenICamCallbacks();
// RegisterInterfaceEvents();
}
catch (System.Exception ex)
{
log.Error(string.Format(
"{2}Problem accessing {0} node. {1}",
this._propertyToControl,
ex.Message,
FormattedSerialNumber));
throw new Exception(
string.Format("Problem accessing {0} node. {1}", this._propertyToControl, ex.Message));
}
finally
{
_initializing = false;
}
}
else
{
_featureAvailable = false;
}
}
public override void Disconnect()
{
try
{
if (_commandNode != null)
{
_commandNode.Updated -= node_Updated;
}
_commandNode = null;
base.Disconnect();
}
catch (System.Exception /*ex*/)
{
}
}
#endregion
#region UI_CONTROL_UPDATE
private void UpdateControlStatus()
{
if (_nodeMap == null)
{
IsEditable = false;
IsButtonEnabled = false;
return;
}
try
{
IValue node = _nodeMap.GetNode<IValue>(_propertyToControl);
if (node == null || !node.IsAvailable)
{
IsEditable = false;
IsButtonEnabled = false;
return;
}
if (!node.IsWritable)
{
IsButtonEnabled = false;
IsEditable = false;
return;
}
else
{
IsEditable = true;
if (!IsButtonEnabled)
{
IsButtonEnabled = true;
}
}
}
catch (System.Exception /*ex*/)
{
}
}
private void UpdateControlValues(Type type, INodeMap nodemap, string nodename, string namelabel = "")
{
if (type == typeof (Command))
{
try
{
_commandNode = nodemap.GetNode<SpinnakerNET.GenApi.ICommand>(nodename);
}
catch (System.Exception /*ex*/)
{
Console.Out.WriteLine(string.Format("Problem obtaining {0} from NodeMap.", nodename));
return;
}
ControlNameLabel = namelabel.Length == 0 ? _commandNode.DisplayName : namelabel;
// Set tooltip
button.ToolTip = _commandNode.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!"));
}
}
#endregion
#region GENICAM_CALLBACK
private void RegisterGenICamCallbacks()
{
if (_commandNode != null)
{
_commandNode.Updated += node_Updated;
}
}
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
private void
_updateWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
bool refreshRequired = false;
if (e.Cancelled)
{
return;
}
if (_nodeMap == null)
{
// Nodemap is no longer valid. Control must have been disconnected.
return;
}
try
{
Dispatcher.Invoke(() => {
_isUpdating = true;
_initializing = true;
INode node = e.Result as INode;
NodeStatus currentNodeStatus = new NodeStatus(node);
if (currentNodeStatus.ExceptionObject != null)
{
return;
}
string logMessage =
string.Format("Spinnaker Callback: Feature=\"{0}\"", currentNodeStatus.NodeName);
logMessage += string.Format(", Value=\"{0}\"", currentNodeStatus.CurrentStringValue);
LogNodeCallback(log, currentNodeStatus.NodeName, logMessage);
if (_controlNameLabel != currentNodeStatus.NodeDisplayName)
{
ControlNameLabel = currentNodeStatus.NodeDisplayName;
refreshRequired = true;
}
if (!currentNodeStatus.IsAvailable)
{
IsEditable = false;
IsButtonEnabled = false;
}
if (!currentNodeStatus.IsWritable)
{
IsButtonEnabled = false;
IsEditable = false;
}
else
{
IsEditable = true;
if (!IsButtonEnabled)
{
IsButtonEnabled = true;
}
refreshRequired = true;
}
});
}
catch (System.Exception ex)
{
log.Debug(
string.Format(
"{1}Problem updating control for {0} node", _propertyToControl, FormattedSerialNumber),
ex);
}
finally
{
_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;
}
private void node_Updated(INode node)
{
if (_nodeMap == null)
{
return;
}
if (_updateWorker.IsBusy || _isUpdating)
{
return;
}
if (!IsVisible)
{
return;
}
_updateWorker.RunWorkerAsync(node);
}
#endregion
#region UI_Event_Handlers
new public void PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
private void button_Click(object sender, RoutedEventArgs e)
{
if (_commandNode != null)
{
try
{
// Set busy indicator
Mouse.OverrideCursor = Cursors.Wait;
if (_commandNode.IsWritable)
{
// Log user initiated changes
LogNodeUpdateAction(log, _commandNode, "Executed");
AnalyticsNodeUpdateAction(analytics, _commandNode, "Executed");
_commandNode.Execute();
// Poll for command completion
while (!_commandNode.IsDone(true))
{
// Sleep short duration
Thread.Sleep(2);
}
}
else
{
MessageBox.Show("Command is currently not executable.");
}
}
catch (Exception ex)
{
log.Error(string.Format("There was a problem executing {0}", _commandNode.Name), ex);
}
finally
{
Mouse.OverrideCursor = null;
}
}
}
#endregion
#region ORIENTATION_CONTROL
public override Orientation ContentOrientation
{
get
{
return rootLayout.Orientation;
}
set
{
rootLayout.Orientation = value;
}
}
public void SetContentOrientation(Orientation newOrientation)
{
this.ContentOrientation = newOrientation;
}
public Orientation GetContentOrientation()
{
return this.ContentOrientation;
}
#endregion
}
}
}