// HardwareDialog.cs created with MonoDevelop
// User: klose at 15:03 03.02.2009
// CVS release: $Id: HardwareDialog.cs,v 1.48 2011-06-15 15:52:58 klose Exp $
//
//    QuickStep: Acquire, view and identify spectra 
//    Copyright (C) 2009  Thomas Klose, Hiperscan GmbH Dresden, Germany
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Collections.Generic;
using Gtk;
using Glade;

using Hiperscan.SGS;
using Hiperscan.Spectroscopy;
using Hiperscan.GUI.Figure;
using Hiperscan.FileIO;
using Hiperscan.Unix;


namespace Hiperscan.GUI
{
	
	public class ServiceDialog
	{
		[Widget] Gtk.Label vendor_label                = null;
		[Widget] Gtk.Label product_label               = null;
		[Widget] Gtk.Label serial_label                = null;
		[Widget] Gtk.Label driver_type_label           = null;
		[Widget] Gtk.Label protocol_version_label      = null;
		[Widget] Gtk.Label firmware_version_label      = null;
		[Widget] Gtk.Label firmware_revision_label     = null;
		[Widget] Gtk.Label scan_engine_version_label   = null;
		[Widget] Gtk.Label hardware_version_label      = null;
		[Widget] Gtk.Label is_finder_label             = null;
		[Widget] Gtk.Label finder_version_label        = null;
		[Widget] Gtk.Label device_name_label           = null;
		[Widget] Gtk.Label status_label                = null;
		[Widget] Gtk.Label frequency_label             = null;
		[Widget] Gtk.Label samples_label               = null;
		[Widget] Gtk.Label samplerate_label            = null;
		[Widget] Gtk.Label temperature_label           = null;
		[Widget] Gtk.Label di_label                    = null;
		[Widget] Gtk.Label di_sigma_label              = null;
		[Widget] Gtk.Label max_absorbance_label        = null;
		[Widget] Gtk.Label bg_label                    = null;
		[Widget] Gtk.Label wavelength_correction_label = null;
		[Widget] Gtk.Label adc_correction_label        = null;
		[Widget] Gtk.Label resolution_limit_label      = null;
		[Widget] Gtk.Label spectrum_count_label        = null;
		[Widget] Gtk.Label time_interval_label         = null;
		[Widget] Gtk.Label lut_timestamp_label         = null;
		[Widget] Gtk.Label has_key_pads_label          = null;

		[Widget] Gtk.Button hardware_properties_button = null;
		
		[Widget] Gtk.Expander  advanced_expander = null;
		
		[Widget] Gtk.CheckButton timeout_checkbutton = null;
		[Widget] Gtk.CheckButton eeprom_checkbutton  = null;
		
		[Widget] Gtk.SpinButton trigger_delay_spin      = null;
		[Widget] Gtk.SpinButton lambda_center_spin      = null;
		[Widget] Gtk.SpinButton amplitude_spin          = null;
		[Widget] Gtk.SpinButton grid_spin               = null;
		[Widget] Gtk.SpinButton deviation_spin          = null;
		[Widget] Gtk.SpinButton sample_count_spin       = null;
		[Widget] Gtk.SpinButton timeout_spin            = null;
		[Widget] Gtk.SpinButton quick_average_spin      = null;
		[Widget] Gtk.SpinButton quick_sample_count_spin = null;

		[Widget] Gtk.Button apply_button     = null;
		
		[Widget] Gtk.Dialog hardware_dialog = null;
				
		private string title;
		private static Dictionary<Device,ServiceDialog> Instances = new Dictionary<Device,ServiceDialog>();

		private UserInterface ui;
		
		private Device        device;
		private Device.Config new_device_config;
		
		private ScrolledPlot freq_plot;
		
		private bool run_frequency_dialog;
		
		public ServiceDialog(UserInterface ui, Device dev)
		{
			Console.WriteLine("Open new ServiceDialog...");
			
			this.ui = ui;
			
			if (ServiceDialog.Instances.ContainsKey(dev))
			{
				ServiceDialog.Instances[dev].hardware_dialog.Present();
				return;
			}
			
			ServiceDialog.Instances.Add(dev, this);
			this.device = dev;
			
			Glade.XML gui;
			
			try
			{
				gui = new Glade.XML(null, "GUI.UserInterface.glade", "hardware_dialog", MainClass.ApplicationDomain);
			}
			catch
			{
				Console.WriteLine("UserInterface: No embedded resource for GUI found. Trying to read external Glade file."); 
				gui = new Glade.XML("UserInterface.glade", "hardware_dialog", null);
			}
			gui.Autoconnect(this);

			this.title = this.hardware_dialog.Title;
			Gdk.Pixbuf[] icons = new Gdk.Pixbuf[5];
			icons[0] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.Menu,         string.Empty);
			icons[1] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.SmallToolbar, string.Empty);
			icons[2] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.LargeToolbar, string.Empty);
			icons[3] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.Button,       string.Empty);
			icons[4] = this.hardware_dialog.RenderIcon(Stock.Properties, IconSize.Dialog,       string.Empty);
			this.hardware_dialog.IconList = icons;

			this.Update(dev);

			this.device.StateChanged += this.Update;
			this.device.Removed      += this.OnDeviceRemoved;
			
			this.hardware_dialog.DeleteEvent += new DeleteEventHandler(this.OnDeleteEvent);			

			this.hardware_dialog.TransientFor = this.ui.MainWindow;
			this.hardware_dialog.Show();
		}
		
		public void Update()
		{
			this.Update(this.device);
		}
		
		private void Update(Device dev)
		{
			try
			{
				this.advanced_expander.Sensitive = dev.IsIdle;

				this.hardware_dialog.Title = this.title + " (" + dev.Info.SerialNumber + ")";
				
				if (dev.Info.VendorId == 0)
				{
					this.vendor_label.Text  = Catalog.GetString("n/a") + " / " + Catalog.GetString("n/a");
					this.product_label.Text = Catalog.GetString("n/a") + " / " + "'" + dev.Info.Description + "'";
				}
				else
				{
					this.vendor_label.Text = 
						"0x" + dev.Info.VendorId.ToString("X04") + " / " +
						"'" + dev.Info.Manufacturer + "'";
					
					this.product_label.Text =
						"0x" + dev.Info.ProductId.ToString("X04") + " / " +
						"'" + dev.Info.Description + "'";
				}

				try
				{
					this.serial_label.Text = dev.Info.SerialNumber;
					
					this.driver_type_label.Text = Enum.GetName(typeof(DriverType), dev.DriverType);
					if (this.device.Info.IsRemote)
					{
						this.driver_type_label.Text += "@" + 
							                           this.device.Info.RemoteUsbClient.Server + ":" + 
							                           this.device.Info.RemoteUsbClient.Port;
					}

					this.protocol_version_label.Text    = dev.ProtocolVersion.ToString();
					this.firmware_version_label.Text    = dev.FirmwareVersion.ToString();
					this.firmware_revision_label.Text   = dev.FirmwareRevision.ToString();

					string msa_factor = Catalog.GetString("n/a");
					if (dev.GetState() == Device.State.Idle)
					{
						try
						{
							dev.StateNotification = false;
							msa_factor = dev.ReadScanEngineMSAFactor().ToString("F4");
						}
						catch (NotImplementedException) {}
						catch (NotSupportedException)   {}
						finally
						{
							dev.StateNotification = true;
							UserInterface.DeviceStateChanged(dev);
						}
					}
					this.scan_engine_version_label.Text = dev.ScanEngineVersion.ToString() + " / " + msa_factor;

					this.hardware_version_label.Text = dev.HardwareVersion.ToString();
					
					if (dev.LutTimestamp == DateTime.MinValue)
						this.lut_timestamp_label.Text = Catalog.GetString("n/a");
					else
						this.lut_timestamp_label.Text = dev.LutTimestamp.ToString();
					
					string finder_version = string.Empty;
					if (dev.IsFinder && dev.FinderVersion != null)
					{
						finder_version = string.Format(" (Board {0}, Wheel {1}, Light {2}, Casing {3})",
						                               dev.FinderVersion.Board,
						                               dev.FinderVersion.ReferenceWheel,
						                               dev.FinderVersion.LightSource,
						                               dev.FinderVersion.Casing);
					}
					
					this.is_finder_label.Text = dev.IsFinder.ToString() + finder_version;

					if (dev.IsFinder && dev.FinderVersion != null && 
						dev.FinderVersion.FirmwareVersion.Id != 0 && 
						dev.FinderVersion.ProtocolVersion.Id != 0)
					{
						this.finder_version_label.Text = 
							dev.FinderVersion.FirmwareVersion + " / " + dev.FinderVersion.ProtocolVersion + " / " + dev.FinderVersion.Peripheral;
					}

					this.device_name_label.Text = dev.CurrentConfig.Name;
					this.status_label.Text      = Enum.GetName(typeof(Device.State), dev.GetState());
				}
				catch (NullReferenceException) { }

				if (dev.AcquisitionInfo == null)
				{
					this.frequency_label.Text  = Catalog.GetString("n/a");
					this.samples_label.Text    = Catalog.GetString("n/a");
					this.samplerate_label.Text = Catalog.GetString("n/a");
				}
				else
				{
					this.frequency_label.Text  = dev.AcquisitionInfo.MirrorFreq.ToString("f3") + " Hz";
					this.samples_label.Text    = dev.AcquisitionInfo.Samples.ToString();
					this.samplerate_label.Text = dev.AcquisitionInfo.SampleRate.ToString("f1") + " 1/s";
				}

				if (dev.GetState() == Device.State.Idle)
				{
					try
					{
						dev.StateNotification = false;
						this.temperature_label.Text = dev.ReadStatus().ToString("f1") + "°C";
						this.temperature_label.TooltipText = Catalog.GetString("Sensor");
						if (dev.IsFinder)
						{
							this.temperature_label.Text += " / " + dev.ReadFinderTemperature().ToString("f1") + "°C";
							this.temperature_label.TooltipText = Catalog.GetString("Sensor/Casing");
						}
						if (dev.TemperatureHistory != null)
						{
							double gradient = dev.TemperatureHistory.Gradient;
							if (!double.IsNaN(gradient))
							{
								this.temperature_label.Text += " / " + gradient.ToString("f1") + "K/h";
								this.temperature_label.TooltipText = Catalog.GetString("Sensor/Casing/Sensor gradient");
							}
						}
					}
					catch (Exception ex)
					{
						Console.WriteLine("Cannot update temperature info: " + ex.Message);
						this.temperature_label.Text = Catalog.GetString("n/a");
					}
					finally
					{
						dev.StateNotification = true;
						UserInterface.DeviceStateChanged(dev);
					}
					
					try
					{
						dev.StateNotification = false;
						this.has_key_pads_label.Text = dev.HasKeyPad.ToString();
					}
					catch (NotImplementedException ex)
					{
						this.has_key_pads_label.Text = Catalog.GetString("n/a");
					}
					finally
					{
						dev.StateNotification = true;
						UserInterface.DeviceStateChanged(dev);
					}


				}
				
				this.di_label.Text       = dev.CurrentConfig.DarkIntensity.Intensity.ToString("f5");
				this.di_sigma_label.Text = dev.CurrentConfig.DarkIntensity.Sigma.ToString("f5");
				
				if (dev.CurrentConfig.HasBackgroundSpectrum)
                    this.max_absorbance_label.Text =  DataSet.AbsorbanceLimit(dev.CurrentConfig.BackgroundSpectrum.Intensity, 
                                                                              dev.CurrentConfig.DarkIntensity).ToString("f5");
				else
					this.max_absorbance_label.Text = Catalog.GetString("n/a");
				
				this.bg_label.Text                    = dev.CurrentConfig.HasBackgroundSpectrum.ToString();
				this.wavelength_correction_label.Text = dev.CurrentConfig.HasWavelengthCorrection.ToString();
				this.adc_correction_label.Text        = dev.CurrentConfig.HasAdcCorrection.ToString();
				this.resolution_limit_label.Text      = dev.LimitBandwith.ToString();
				
				this.time_interval_label.Text  = dev.CurrentConfig.TimedSpan.ToString() + " s";
				this.spectrum_count_label.Text = dev.SpectrumCount.ToString();
				
				if ((dev.CurrentConfig.StreamType == Device.StreamType.Timed) &&
				    (dev.CurrentConfig.TimedCount > 0))
				{
					this.spectrum_count_label.Text += " / " +	dev.CurrentConfig.TimedCount.ToString();
				}
				
				this.trigger_delay_spin.Value = (double)dev.CurrentConfig.TriggerDelay;
				this.lambda_center_spin.Value = (double)dev.CurrentConfig.LambdaCenter;
				this.amplitude_spin.Value     = (double)dev.CurrentConfig.Amplitude;
				this.grid_spin.Value          = (double)dev.CurrentConfig.Grid;
				this.deviation_spin.Value     = (double)dev.CurrentConfig.Deviation;
				this.sample_count_spin.Value  = (double)dev.CurrentConfig.Samples;
				
				this.timeout_checkbutton.Active = !dev.CurrentConfig.AutoTimeout;
				this.timeout_spin.Sensitive     = !dev.CurrentConfig.AutoTimeout;
				this.timeout_spin.Value         = (double)dev.CurrentConfig.Timeout;

				this.quick_average_spin.Value      = (double)dev.CurrentConfig.QuickAverage;
				this.quick_sample_count_spin.Value = (double)dev.CurrentConfig.QuickSamples;
				
				this.eeprom_checkbutton.Active = UserInterface.Settings.Current.WriteToEEPROM;
				
				this.new_device_config = new Device.Config(dev.CurrentConfig);				
				
				this.apply_button.Sensitive = false;
			}
			catch (NullReferenceException) { }
		}
			
		private void OnDeviceRemoved(Device dev)
		{
			ServiceDialog.Instances.Remove(dev);
			this.hardware_dialog.Destroy();
		}
		
		internal void OnAdvancedExpanderActivate(object o, System.EventArgs e)
		{
			Expander expander = o as Expander;
			
			if (expander.Expanded && MainClass.IsRelease)
			{
				expander.Expanded = false;
				PasswordDialog dialog = new PasswordDialog(this.hardware_dialog, Catalog.GetString("Enter password"));
				if (dialog.Query("83-21-B1-FD-3E-15-70-7E-EA-17-86-2B-0E-CD-D0-41"))
					expander.Expanded = true;
			}
			
//			this.advanced_frame.Sensitive = c.Active;
		}
		
		internal void OnTimeoutCheckbuttonToggled(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			CheckButton c = o as CheckButton;

			this.new_device_config.AutoTimeout = !c.Active;
			
			this.timeout_spin.Sensitive = c.Active;
			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}

		internal void OnTriggerDelaySpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.TriggerDelay = (ushort)s.Value;
			
			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
		internal void OnLambdaCenterSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.LambdaCenter = (double)s.Value;

			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
		internal void OnAmplitudeSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.Amplitude = (double)s.Value;

			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
		internal void OnGridSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.Grid = (ushort)s.Value;
			
			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
		internal void OnDeviationSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.Deviation = (double)s.Value;

			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
		internal void OnSampleCountSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.Samples = (ushort)s.Value;

			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
		internal void OnQuickAverageSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.QuickAverage = (ushort)s.Value;

			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
		internal void OnQuickSampleCountSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.QuickSamples = (ushort)s.Value;

			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
		internal void OnTimeoutSpinValueChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config == null)
				return;
			
			SpinButton s = o as SpinButton;
			this.new_device_config.Timeout = (int)s.Value;

			this.apply_button.Sensitive = this.device.IsIdle || 
				this.device.GetState() == Device.State.Unprogrammed;
		}
		
//		internal void OnResetDspButtonClicked(object o, System.EventArgs e)
//		{
//			try
//			{
//				this.device.ResetDSP();
//				new InfoMessage(this.hardware_dialog, Catalog.GetString("Successfully reset DSP."));
//			}
//			catch (System.Exception ex)
//			{
//				new InfoMessage(this.hardware_dialog, 
//				                Catalog.GetString("Cannot reset DSP: {0}"),
//				                ex.Message);
//			}
//		}
		
		internal void OnEepromCheckbuttonToggled(object o, EventArgs e)
		{
			CheckButton b = o as CheckButton;
			UserInterface.Settings.Current.WriteToEEPROM = b.Active; 
		}

		internal void OnSettingChanged(object o, System.EventArgs e)
		{
			if (this.new_device_config != null)
				this.apply_button.Sensitive = this.device.IsIdle || 
					this.device.GetState() == Device.State.Unprogrammed;
		}

		internal void OnApplyButtonClicked(object o, System.EventArgs e)
		{
			Button b = o as Gtk.Button;
			
			b.HasFocus  = true;
			
			try
			{
				this.device.CurrentConfig = this.new_device_config;
			}
			catch (System.Exception ex)
			{
				new InfoMessage(this.hardware_dialog, 
				                Catalog.GetString("Cannot apply device settings: {0}"),
				                ex.Message);
				return;
			}
			
			if (this.eeprom_checkbutton.Active)
			{
				try
				{
					this.device.WriteEEPROM();
					new InfoMessage(this.hardware_dialog, 
					                Catalog.GetString("Successfully wrote hardware settings to EEPROM.")
					                );
				}
				catch (System.Exception ex)
				{
					new InfoMessage(this.hardware_dialog, 
					                Catalog.GetString("Cannot write EEPROM: {0}"),
					                ex.Message);
				}
			}
			this.ui.UpdatePropertiesSpectrometerControls();
			
			b.Sensitive = false;
		}

		internal void OnFrequencyButtonClicked(object o, System.EventArgs e)
		{
			if (this.device.Frequency.Count < 4)
			{
				new InfoMessage(this.hardware_dialog, 
				                Catalog.GetString("Not enough mirror frequency data available."));
				return;
			}

			DataSet freq  = this.device.Frequency.GetRange(2, this.device.Frequency.Count-2);
			Dialog dialog = new Dialog(Catalog.GetString("Frequency characteristic") + 
			                           " ("  + this.device.Info.SerialNumber + ")",
			                           this.hardware_dialog, DialogFlags.Modal);
			dialog.AddButton(Stock.Save,    0);
			dialog.AddButton(Stock.Print,   1);
			dialog.AddButton(Stock.Refresh, 2);
			dialog.AddButton(Stock.Close, ResponseType.Close);
			
			dialog.Response += new ResponseHandler(this.OnFrequencyDialogResponse);
			
			dialog.HasSeparator  = true;
			dialog.WidthRequest  = 780;
			dialog.HeightRequest = 400;
			
			this.freq_plot = new ScrolledPlot(null);
			this.freq_plot.Plot.BackgroundColor = this.ui.BackgroundColor;
			this.freq_plot.Plot.AddDataSet(freq / new DataSet.Operand(60f, 1f));
			this.freq_plot.Plot.XLabel = Catalog.GetString("Time / min");
			this.freq_plot.Plot.YLabel = Catalog.GetString("Mirror frequency / Hz");
			this.freq_plot.Plot.Title = Catalog.GetString("Device serial:") + 
				                        " " + this.device.Info.SerialNumber;
			this.freq_plot.Plot.LegendVisible = false;
			dialog.VBox.PackStart(this.freq_plot);
			this.freq_plot.ShowAll();
			
			do
			{
				dialog.Run();
			} while (this.run_frequency_dialog);
			
			dialog.Destroy();
		}
		
		private void OnFrequencyDialogResponse(object o, ResponseArgs e)
		{
			switch ((int)e.ResponseId)
			{
				
			case 0:
				FileChooserDialog chooser = new QSFileChooserDialog(Catalog.GetString("Specify file name to save frequency characteristic"), 
					                                                this.hardware_dialog, 
				                                                    FileChooserAction.Save,
				                                                    Stock.Save,
				                                                    ResponseType.Ok,
				                                                    Stock.Cancel,
				                                                    ResponseType.Cancel);
				FileFilter filter = new FileFilter();
				filter.Name = Catalog.GetString("CSV files");
				filter.AddPattern("*.csv");
				chooser.AddFilter(filter);
				
				chooser.CurrentName = "frequency" +
					    DateTime.Now.ToString("_yyyy-MM-dd_HH-mm_") +
						this.device.Info.SerialNumber +
						".csv";
				
				if (!string.IsNullOrEmpty(UserInterface.Settings.Current.SaveFrequencyFilePath))
					chooser.SetCurrentFolder(UserInterface.Settings.Current.SaveFrequencyFilePath);
				else
					chooser.SetCurrentFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
				
				try
				{
					ResponseType choice = (ResponseType)chooser.Run();
					
					if (choice == ResponseType.Ok)
					{
						chooser.Hide();
						
						CSV.Write(this.device.Frequency.GetRange(2, this.device.Frequency.Count-2),
						          chooser.Filename, this.ui.OutputCultureInfo());
						UserInterface.Settings.Current.SaveFrequencyFilePath = chooser.CurrentFolder;
					}
				}
				catch (Exception ex)
				{
					new InfoMessage(this.hardware_dialog, 
					                Catalog.GetString("Error while saving frequency characteristic: {0}"),
					                ex.Message);
				}
				finally
				{
					chooser.Destroy();
				}
				this.run_frequency_dialog = true;
				break;
				
			case 1:
				new Printer(this.hardware_dialog, this.freq_plot.Plot);
				this.run_frequency_dialog = true;
				break;
				
			case 2:
				DataSet freq = this.device.Frequency.GetRange(2, this.device.Frequency.Count-2);
				this.freq_plot.Plot.Clear();
				this.freq_plot.Plot.AddDataSet(freq / new DataSet.Operand(60f, 1f));
				
				this.run_frequency_dialog = true;
				break;
				
			default:
				this.run_frequency_dialog = false;
				break;
				
			}
		}
		
		internal void OnWavelengthCorrectionButtonClicked(object o, EventArgs e)
		{
			if (!this.device.HasReference && !this.device.IsFinder)
			{
				new InfoMessage(this.hardware_dialog, 
				                Catalog.GetString("Cannot perform wavelength correction: " +
				                                  "Please specify background spectrum and dark intensity first.")
				                );
				return;
			}
			try
			{
				new CorrectionDialog(this.device, this, this.ui);
			}
			catch (Exception ex)
			{
				new InfoMessage(this.hardware_dialog, ex.Message);
			}
		}

		internal void OnHardwarePropertiesButtonClicked(object o, EventArgs e)
		{
			string msg = Catalog.GetString("<b>Hardware Properties</b>\n\n") + 
				"<span font_family=\"monospace\">" + this.device.HardwareProperties.ToString() + "</span>";
			QSMessageDialog dialog = new QSMessageDialog(this.hardware_dialog, DialogFlags.Modal, MessageType.Info, ButtonsType.Ok, msg);
			Console.WriteLine(msg);
			dialog.Run();
			dialog.Destroy();
		}
		
		internal void OnResolutionLimitButtonClicked(object o, EventArgs e)
		{
			this.device.LimitBandwith = !this.device.LimitBandwith;
			this.Update();
		}
		
		internal void OnCloseButtonClicked(object o, System.EventArgs e)
		{
			this.device.StateChanged -= this.Update;
			this.OnDeviceRemoved(this.device);
		}

		private void OnDeleteEvent(System.Object o, DeleteEventArgs e)
		{
			this.device.StateChanged -= this.Update;
			this.OnDeviceRemoved(this.device);
			e.RetVal = true;
		}
	}
}
