#include <algorithm>
#include <apps/Common/Info.h>
#include <apps/Common/mvIcon.xpm>
#include "CaptureThread.h"
#include "DataConversion.h"
#include "HistogramCanvas.h"
#include "icons.h"
#include "ImageCanvas.h"
#include "InfoPlotCanvas.h"
#include <limits>
#include "LineProfileCanvas.h"
#include <memory>
#include "PropData.h"
#include "PropViewFrame.h"
#include "VectorScopeCanvas.h"
#include <wx/choicdlg.h>
#include <wx/config.h>
#include <wx/dnd.h>
#include <wx/file.h>
#include <wx/numdlg.h>
#if wxCHECK_VERSION(2, 7, 1)
#	include <wx/platinfo.h>
#endif // #if wxCHECK_VERSION(2, 7, 1)
#include <wx/slider.h>
#include <wx/spinctrl.h>
#include <wx/splitter.h>
#include <wx/tooltip.h>

#ifdef WIN32
#	define BUILD_WITH_TEXT_EVENTS_FOR_SPINCTRL
#endif // #ifdef WIN32

using namespace mvIMPACT::acquire;
using namespace std;

DEFINE_EVENT_TYPE(imageReadyEvent)
DEFINE_EVENT_TYPE(imageSkippedEvent)
DEFINE_EVENT_TYPE(toggleDisplayArea)
DEFINE_EVENT_TYPE(liveModeAborted)
DEFINE_EVENT_TYPE(eventNotified)
DEFINE_EVENT_TYPE(sequenceReadyEvent)
DEFINE_EVENT_TYPE(imageInfoEvent)
DEFINE_EVENT_TYPE(refreshAOIControls)
DEFINE_EVENT_TYPE(refreshCurrentPixelData)
DEFINE_EVENT_TYPE(imageCanvasSelected)
DEFINE_EVENT_TYPE(imageCanvasFullScreen)

//-----------------------------------------------------------------------------
template<class _Ty1, class _Ty2>
class SecondMatches : public std::unary_function<std::pair<_Ty1, _Ty2>, bool>
//-----------------------------------------------------------------------------
{
	std::pair<_Ty1, _Ty2> value_;
public:
	explicit SecondMatches( const std::pair<_Ty1, _Ty2>& val ) : value_(val) {}
	bool operator()( const std::pair<_Ty1, _Ty2>& x ) { return x.second == value_.second; }
};

//-----------------------------------------------------------------------------
struct SettingData
//-----------------------------------------------------------------------------
{
	TScope scope_;
	string name_;
	explicit SettingData( TScope scope, const string& name ) : scope_(scope), name_(name) {}
};

//=============================================================================
//================= Implementation RequestData ================================
//=============================================================================

const wxString RequestData::UNKNOWN_PIXEL_FORMAT_STRING_(wxT("unknown"));

//-----------------------------------------------------------------------------
RequestData::RequestData() : image_(1), pixelFormat_(UNKNOWN_PIXEL_FORMAT_STRING_), requestNr_(INVALID_ID)
//-----------------------------------------------------------------------------
{
	image_.getBuffer()->pixelFormat = ibpfMono8;
	memset( &requestInfo_, 0, sizeof(requestInfo_) );
}

//=============================================================================
//================= Implementation FramePositionStorage =======================
//=============================================================================
//-----------------------------------------------------------------------------
class FramePositionStorage
//-----------------------------------------------------------------------------
{
	wxConfigBase* m_pConfig;
	wxWindow* m_pWin;
	wxString m_windowName;
public:
	FramePositionStorage( wxWindow* pWin, const wxString& windowName ) : m_pConfig(wxConfigBase::Get()), m_pWin(pWin), m_windowName(windowName) {}
	void store( void ) const
	{
		int Height, Width, XPos, YPos;
		m_pWin->GetSize( &Width, &Height );
		m_pWin->GetPosition( &XPos, &YPos );
		m_pConfig->Write( wxString::Format( wxT("/%s/h"), m_windowName.c_str() ), Height );
		m_pConfig->Write( wxString::Format( wxT("/%s/w"), m_windowName.c_str() ), Width );
		m_pConfig->Write( wxString::Format( wxT("/%s/x"), m_windowName.c_str() ), XPos );
		m_pConfig->Write( wxString::Format( wxT("/%s/y"), m_windowName.c_str() ), YPos );
	}
	wxRect restore( const wxRect& defaultDimensions ) const
	{
		wxRect rect;
		rect.height = m_pConfig->Read( wxString::Format( wxT("/%s/h"), m_windowName.c_str() ), defaultDimensions.height );
		rect.width = m_pConfig->Read( wxString::Format( wxT("/%s/w"), m_windowName.c_str() ), defaultDimensions.width );
		rect.x = m_pConfig->Read( wxString::Format( wxT("/%s/x"), m_windowName.c_str() ), defaultDimensions.x );
		rect.y = m_pConfig->Read( wxString::Format( wxT("/%s/y"), m_windowName.c_str() ), defaultDimensions.y );
		int displayWidth = 0;
		int displayHeight = 0;
		wxDisplaySize( &displayWidth, &displayHeight );
		if( ( rect.x >= displayWidth ) || ( rect.x < 0 ) )
		{
			rect.x = 0;
		}
		if( ( rect.y >= displayHeight ) || ( rect.y < 0 ) )
		{
			rect.y = 0;
		}
		return rect;
	}
};

//-----------------------------------------------------------------------------
class DnDFile : public wxFileDropTarget
//-----------------------------------------------------------------------------
{
public:
	DnDFile( PropViewFrame *pOwner, ImageCanvas* pImageCanvas ) : pOwner_(pOwner), pImageCanvas_(pImageCanvas) {}
	virtual bool OnDropFiles( wxCoord, wxCoord, const wxArrayString& fileNames )
	{
		return ( fileNames.IsEmpty() ) ? false : pOwner_->SetCurrentImage( wxFileName(fileNames.Item( 0 )), pImageCanvas_ );
	}
private:
	PropViewFrame* pOwner_;
	ImageCanvas* pImageCanvas_;
};

//-----------------------------------------------------------------------------
class MonitorDisplay : public wxFrame
//-----------------------------------------------------------------------------
{
	ImageCanvas* m_pDisplayArea;
public:
	explicit MonitorDisplay( wxWindow* pParent ) : wxFrame(pParent, wxID_ANY, wxT("Monitor display"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxRESIZE_BORDER | wxFRAME_FLOAT_ON_PARENT)
	{
		wxBoxSizer* pTopDownSizer = new wxBoxSizer(wxHORIZONTAL);
		wxPanel* pPanel = new wxPanel(this);
		m_pDisplayArea = new ImageCanvas(this, pPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN, wxEmptyString);
		m_pDisplayArea->SetScaling( true );
		m_pDisplayArea->HandleMouseAndKeyboardEvents( false );
		pTopDownSizer->Add( m_pDisplayArea, wxSizerFlags(1).Expand() );
		pPanel->SetSizer( pTopDownSizer );
		pTopDownSizer->SetSizeHints( this );
		SetSizeHints( 100, 66 );
		wxRect defaultRect(0, 0, 150, 100);
		FramePositionStorage frameStorage(this, wxString(wxT("MonitorDisplay")));
		SetSize( frameStorage.restore( defaultRect ) );
	}
	~MonitorDisplay()
	{
		FramePositionStorage frameStorage(this, wxString(wxT("MonitorDisplay")));
		frameStorage.store();
	}
	ImageCanvas* GetDisplayArea( void ) { return m_pDisplayArea; }
};

//=============================================================================
//================= Implementation MyApp ======================================
//=============================================================================
//-----------------------------------------------------------------------------
class MyApp : public wxApp
//-----------------------------------------------------------------------------
{
	PropViewFrame* pFrame_;
public:
	virtual int FilterEvent( wxEvent& e )
	{
		if ( ( e.GetEventType() == wxEVT_KEY_DOWN ) && ((wxKeyEvent&)e).GetKeyCode() == WXK_ESCAPE )
		{
			pFrame_->EndFullScreenMode();
			return true;
		}
		return -1;
	}
	virtual bool OnInit( void )
	{
		wxImage::AddHandler( new wxGIFHandler );
		wxImage::AddHandler( new wxJPEGHandler );
		wxImage::AddHandler( new wxPNGHandler );
		wxImage::AddHandler( new wxTIFFHandler );
		// Create the main application window
		pFrame_ = new PropViewFrame( wxString::Format( wxT("wxPropView(%s)"), VERSION_STRING ), wxDefaultPosition, wxDefaultSize, argc, argv );
		pFrame_->Show( true );
		SetTopWindow( pFrame_ );
		// success: wxApp::OnRun() will be called which will enter the main message
		// loop and the application will run. If we returned false here, the
		// application would exit immediately.
		return true;
	}
};

// Create a new application object: this macro will allow wxWidgets to create
// the application object during program execution (it's better than using a
// static object for many reasons) and also declares the accessor function
// wxGetApp() which will return the reference of the right type (i.e. MyApp and
// not wxApp)
IMPLEMENT_APP(MyApp)

//=============================================================================
//================= Implementation ImageAnalysisPlotControls ==================
//=============================================================================
//-----------------------------------------------------------------------------
void ImageAnalysisPlotControls::Load( wxConfigBase* pConfig )
//-----------------------------------------------------------------------------
{
	bool boEnable = pConfig->Read( wxString::Format(wxT("/Controls/%s/AOIFullMode"), m_pPlotCanvas->GetConfigName().c_str()), 0l ) != 0;
	m_pCBAOIFullMode->SetValue( boEnable );
	m_pPlotCanvas->SetAOIFullMode( boEnable );
	if( m_pCBProcessBayerParity )
	{
		bool boEnable = pConfig->Read( wxString::Format(wxT("/Controls/%s/ProcessBayerParity"), m_pPlotCanvas->GetConfigName().c_str()), 1l ) != 0;
		m_pCBProcessBayerParity->SetValue( boEnable );
		m_pPlotCanvas->SetProcessBayerParity( boEnable );
	}
	m_pSCAOIh->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/AOIh"), m_pPlotCanvas->GetConfigName().c_str()), 480l ) );
	m_pSCAOIw->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/AOIw"), m_pPlotCanvas->GetConfigName().c_str()), 640l ) );
	m_pSCAOIx->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/AOIx"), m_pPlotCanvas->GetConfigName().c_str()), 0l ) );
	m_pSCAOIy->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/AOIy"), m_pPlotCanvas->GetConfigName().c_str()), 0l ) );
	if( m_pCoBPlotSelection )
	{
		wxString plotSelection(pConfig->Read( wxString::Format(wxT("/Controls/%s/PlotSelection"), m_pPlotCanvas->GetConfigName().c_str()), wxT("") ));
		const std::vector<wxString>& v(m_pPlotCanvas->GetAvailablePlotSelections());
		const std::vector<wxString>::size_type cnt = v.size();
		for( std::vector<wxString>::size_type i=0; i<cnt; i++ )
		{
			if( v[i] == plotSelection )
			{
				m_pCoBPlotSelection->Select( i );
				m_pPlotCanvas->SetPlotSelection( plotSelection );
			}
		}
	}
	if( m_pSCHistoryDepth )
	{
		m_pSCHistoryDepth->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/HistoryDepth"), m_pPlotCanvas->GetConfigName().c_str()), 0l ) );
	}
	if( m_pSCDrawStart_percent )
	{
		m_pSCDrawStart_percent->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/DrawStartPercent"), m_pPlotCanvas->GetConfigName().c_str()), 0l ) );
	}
	if( m_pSCDrawWindow_percent )
	{
		m_pSCDrawWindow_percent->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/DrawWindowPercent"), m_pPlotCanvas->GetConfigName().c_str()), 100l ) );
	}
	if( m_pSCDrawStepWidth )
	{
		m_pSCDrawStepWidth->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/DrawStepWidth"), m_pPlotCanvas->GetConfigName().c_str()), 0l ) );
	}
	if( m_pSCGridStepsX )
	{
		m_pSCGridStepsX->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/GridStepsX"), m_pPlotCanvas->GetConfigName().c_str()), 1l ) );
	}
	if( m_pSCGridStepsY )
	{
		m_pSCGridStepsY->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/GridStepsY"), m_pPlotCanvas->GetConfigName().c_str()), 1l ) );
	}
	m_pSCUpdateSpeed->SetValue( pConfig->Read( wxString::Format(wxT("/Controls/%s/UpdateSpeed"), m_pPlotCanvas->GetConfigName().c_str()), 3l ) );
	ImageAnalysisPlotCanvas::TDisplayMethod displayMethod = static_cast<ImageAnalysisPlotCanvas::TDisplayMethod>(pConfig->Read( wxString::Format(wxT("/Controls/%s/DisplayMethod"), m_pPlotCanvas->GetConfigName().c_str()), 0l ));
	m_pNBDisplayMethod->SetSelection( displayMethod );
	m_pPlotCanvas->SetDisplayMethod( displayMethod );
	UpdateControls();
}

//-----------------------------------------------------------------------------
void ImageAnalysisPlotControls::Save( wxConfigBase* pConfig )
//-----------------------------------------------------------------------------
{
	pConfig->Write( wxString::Format(wxT("/Controls/%s/AOIFullMode"), m_pPlotCanvas->GetConfigName().c_str()), m_pCBAOIFullMode->GetValue() );
	if( m_pCBProcessBayerParity )
	{
		pConfig->Write( wxString::Format(wxT("/Controls/%s/ProcessBayerParity"), m_pPlotCanvas->GetConfigName().c_str()), m_pCBProcessBayerParity->GetValue() );
	}
	pConfig->Write( wxString::Format(wxT("/Controls/%s/AOIh"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCAOIh->GetValue() );
	pConfig->Write( wxString::Format(wxT("/Controls/%s/AOIw"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCAOIw->GetValue() );
	pConfig->Write( wxString::Format(wxT("/Controls/%s/AOIx"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCAOIx->GetValue() );
	pConfig->Write( wxString::Format(wxT("/Controls/%s/AOIy"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCAOIy->GetValue() );
	if( m_pCoBPlotSelection )
	{
		pConfig->Write( wxString::Format(wxT("/Controls/%s/PlotSelection"), m_pPlotCanvas->GetConfigName().c_str()), m_pCoBPlotSelection->GetValue() );
	}
	if( m_pSCHistoryDepth )
	{
		pConfig->Write( wxString::Format(wxT("/Controls/%s/HistoryDepth"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCHistoryDepth->GetValue() );
	}
	if( m_pSCDrawStart_percent )
	{
		pConfig->Write( wxString::Format(wxT("/Controls/%s/DrawStartPercent"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCDrawStart_percent->GetValue() );
	}
	if( m_pSCDrawWindow_percent )
	{
		pConfig->Write( wxString::Format(wxT("/Controls/%s/DrawWindowPercent"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCDrawWindow_percent->GetValue() );
	}
	if( m_pSCDrawStepWidth )
	{
		pConfig->Write( wxString::Format(wxT("/Controls/%s/DrawStepWidth"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCDrawStepWidth->GetValue() );
	}
	if( m_pSCGridStepsX )
	{
		pConfig->Write( wxString::Format(wxT("/Controls/%s/GridStepsX"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCGridStepsX->GetValue() );
	}
	if( m_pSCGridStepsY )
	{
		pConfig->Write( wxString::Format(wxT("/Controls/%s/GridStepsY"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCGridStepsY->GetValue() );
	}
	pConfig->Write( wxString::Format(wxT("/Controls/%s/UpdateSpeed"), m_pPlotCanvas->GetConfigName().c_str()), m_pSCUpdateSpeed->GetValue() );
	pConfig->Write( wxString::Format(wxT("/Controls/%s/DisplayMethod"), m_pPlotCanvas->GetConfigName().c_str()), m_pNBDisplayMethod->GetSelection() );
}

//-----------------------------------------------------------------------------
void ImageAnalysisPlotControls::UpdateControls( void )
//-----------------------------------------------------------------------------
{
	bool boFullAOIMode = m_pCBAOIFullMode->IsChecked();
	m_pSCAOIx->Enable( !boFullAOIMode );
	m_pSCAOIy->Enable( !boFullAOIMode );
	m_pSCAOIw->Enable( !boFullAOIMode );
	m_pSCAOIh->Enable( !boFullAOIMode );
}

//=============================================================================
//================= Implementation PropViewFrame ==============================
//=============================================================================
// ----------------------------------------------------------------------------
// event tables and other macros for wxWidgets
// ----------------------------------------------------------------------------

// the event tables connect the wxWidgets events with the functions (event
// handlers) which process them. It can be also done at run-time, but for the
// simple menu events like this the static method is much simpler.
BEGIN_EVENT_TABLE(PropViewFrame, PropGridFrameBase)
	EVT_MENU(miHelp_About, PropViewFrame::OnHelp_About)
	EVT_MENU(miHelp_DriverInformation, PropViewFrame::OnHelp_DriverInformation)
	EVT_MENU(miQuit, PropViewFrame::OnQuit)
	EVT_MENU(miAction_UseDevice, PropViewFrame::OnUseDevice)
	EVT_MENU(miAction_Settings_Save_ToDefault, PropViewFrame::OnSaveToDefault)
	EVT_MENU(miAction_Settings_Save_SystemToDefault, PropViewFrame::OnSaveSystemToDefault)
	EVT_MENU(miAction_Settings_Save_CurrentProduct, PropViewFrame::OnSaveCurrentProduct)
	EVT_MENU(miAction_Settings_Save_ActiveDevice, PropViewFrame::OnSaveActiveDevice)
	EVT_MENU(miAction_Settings_Save_ExportActiveDevice, PropViewFrame::OnExportActiveDevice)
	EVT_MENU(miAction_Settings_Load_FromDefault, PropViewFrame::OnLoadFromDefault)
	EVT_MENU(miAction_Settings_Load_CurrentProduct, PropViewFrame::OnLoadCurrentProduct)
	EVT_MENU(miAction_Settings_Load_ActiveDevice, PropViewFrame::OnLoadActiveDevice)
	EVT_MENU(miAction_Settings_Load_ImportActiveDevice, PropViewFrame::OnImportActiveDevice)
	EVT_MENU(miAction_Settings_Manage, PropViewFrame::OnManageSettings)
	EVT_MENU(miAction_LoadImage, PropViewFrame::OnLoadImage)
	EVT_MENU(miAction_SaveImage, PropViewFrame::OnSaveImage)
	EVT_MENU(miAction_SaveImageSequenceToFiles, PropViewFrame::OnSaveImageSequenceToFiles)
	EVT_MENU(miAction_SaveImageSequenceToStream, PropViewFrame::OnSaveImageSequenceToStream)
	EVT_MENU(miAction_UpdateDeviceList, PropViewFrame::OnUpdateDeviceList)
	EVT_MENU(miCapture_Live, PropViewFrame::OnBtnLive)
	EVT_MENU(miCapture_Snap, PropViewFrame::OnBtnSnap)
	EVT_MENU(miCapture_Abort, PropViewFrame::OnBtnAbort)
	EVT_MENU(miCapture_Record, PropViewFrame::OnBtnRecord)
	EVT_MENU(miCapture_Backward, PropViewFrame::OnIncDecRecordDisplay)
	EVT_MENU(miCapture_Forward, PropViewFrame::OnIncDecRecordDisplay)
	EVT_MENU(miCapture_Recording_Continuous, PropViewFrame::OnContinuousRecording)
	EVT_MENU(miCapture_Recording_SetupSequenceSize, PropViewFrame::OnSetupRecordSequenceSize)
	EVT_MENU(miCapture_Recording_SetupHarddiscRecording, PropViewFrame::OnSetupHarddiscRecording)
	EVT_MENU(miCapture_CaptureSettings_CreateCaptureSetting, PropViewFrame::OnCapture_CaptureSettings_CreateCaptureSetting)
	EVT_MENU(miCapture_CaptureSettings_CaptureSettingHierarchy, PropViewFrame::OnCapture_CaptureSettings_CaptureSettingHierarchy)
	EVT_MENU(miCapture_CaptureSettings_AssignToDisplays, PropViewFrame::OnCapture_CaptureSettings_AssignToDisplays)
	EVT_MENU(miCapture_CaptureSettings_UsageMode_Manual, PropViewFrame::OnCapture_CaptureSettings_UsageMode_Changed)
	EVT_MENU(miCapture_CaptureSettings_UsageMode_Automatic, PropViewFrame::OnCapture_CaptureSettings_UsageMode_Changed)
	EVT_MENU(miCapture_SetupCaptureQueueDepth, PropViewFrame::OnSetupCaptureQueueDepth)
	EVT_MENU(miSettings_Display_Active, PropViewFrame::OnActivateDisplay)
	EVT_MENU(miSettings_Display_ShowMonitorImage, PropViewFrame::OnShowMonitorDisplay)
	EVT_MENU(miSettings_Display_ShowIncompleteFrames, PropViewFrame::OnShowIncompleteFrames)
	EVT_MENU(miSettings_ShowStatusBar, PropViewFrame::OnShowStatusBar)
	EVT_MENU(miSettings_ToggleFullScreenMode, PropViewFrame::OnToggleFullScreenMode)
	EVT_MENU(miSettings_ShowToolBar, PropViewFrame::OnShowToolBar)
	EVT_MENU(miSettings_ShowConnectedDevicesOnly, PropViewFrame::OnConnectedOnly)
	EVT_MENU(miSettings_DefaultDeviceInterface_DeviceSpecific, PropViewFrame::OnSettings_DefaultDeviceInterface_Changed)
	EVT_MENU(miSettings_DefaultDeviceInterface_Generic, PropViewFrame::OnSettings_DefaultDeviceInterface_Changed)
	EVT_MENU(miSettings_DefaultDeviceInterface_GenICam, PropViewFrame::OnSettings_DefaultDeviceInterface_Changed)
	EVT_MENU(miSettings_Analysis_ShowControls, PropViewFrame::OnSettings_Analysis_ShowControls)
	EVT_MENU(miSettings_PropGrid_Show, PropViewFrame::OnSettingsPropGrid_Show)
	EVT_MENU(miSettings_PropGrid_DisplayPropIndicesAsHex, PropViewFrame::OnSettingsPropGrid_UpdateViewMode)
	EVT_MENU(miSettings_PropGrid_UseDisplayNameIfAvailable, PropViewFrame::OnSettingsPropGrid_UpdateViewMode)
	EVT_MENU(miSettings_PropGrid_UseSelectorGrouping, PropViewFrame::OnSettingsPropGrid_UpdateViewMode)
	EVT_MENU(miSettings_PropGrid_StandardView, PropViewFrame::OnSettingsPropGrid_ViewModeChanged)
	EVT_MENU(miSettings_PropGrid_DevelopersView, PropViewFrame::OnSettingsPropGrid_ViewModeChanged)
	EVT_COMMAND_SCROLL_THUMBTRACK(widSLRecordDisplay, PropViewFrame::OnSLRecordDisplay)
	EVT_SIZE(PropViewFrame::OnSize)
	EVT_BUTTON(miAction_UseDevice, PropViewFrame::OnUseDevice)
	EVT_BUTTON(miAction_UpdateDeviceList, PropViewFrame::OnUpdateDeviceList)
	EVT_BUTTON(miCapture_Live, PropViewFrame::OnBtnLive)
	EVT_BUTTON(miCapture_Snap, PropViewFrame::OnBtnSnap)
	EVT_BUTTON(miCapture_Abort, PropViewFrame::OnBtnAbort)
	EVT_COMMAND(widMainFrame, imageReadyEvent, PropViewFrame::OnImageReady)
	EVT_COMMAND(widMainFrame, sequenceReadyEvent, PropViewFrame::OnSequenceReady)
	EVT_COMMAND(widMainFrame, imageSkippedEvent, PropViewFrame::OnImageSkipped)
	EVT_COMMAND(widMainFrame, toggleDisplayArea, PropViewFrame::OnToggleDisplayWindowSize)
	EVT_COMMAND(widMainFrame, liveModeAborted, PropViewFrame::OnLiveModeAborted)
	EVT_COMMAND(widMainFrame, eventNotified, PropViewFrame::OnEventNotified)
	EVT_COMMAND(widMainFrame, imageInfoEvent, PropViewFrame::OnImageInfo)
	EVT_COMMAND(widMainFrame, refreshAOIControls, PropViewFrame::OnRefreshAOIControls)
	EVT_COMMAND(widMainFrame, refreshCurrentPixelData, PropViewFrame::OnRefreshCurrentPixelData)
	EVT_COMMAND(widMainFrame, imageCanvasSelected, PropViewFrame::OnImageCanvasSelected)
	EVT_COMMAND(widMainFrame, imageCanvasFullScreen, PropViewFrame::OnImageCanvasFullScreen)
	EVT_NOTEBOOK_PAGE_CHANGED(widNotebook, PropViewFrame::OnNotebookPageChanged)
	EVT_NOTEBOOK_PAGE_CHANGED(widNBConfigurationMethod, PropViewFrame::OnNBConfigurationMethodPageChanged)
	EVT_TEXT(widDevCombo, PropViewFrame::OnDevComboTextChanged)
	EVT_TEXT(widUserExperienceCombo, PropViewFrame::OnUserExperienceComboTextChanged)
	EVT_CLOSE(PropViewFrame::OnClose)
	EVT_SPLITTER_SASH_POS_CHANGED(widHorSplitter, PropViewFrame::OnSplitterSashPosChanged)
	EVT_SPLITTER_SASH_POS_CHANGED(widVerSplitter, PropViewFrame::OnSplitterSashPosChanged)

	EVT_CHECKBOX(widPixelHistogram | iapidCBAOIFullMode, PropViewFrame::OnAnalysisPlotCBAOIFullMode)
	EVT_CHECKBOX(widPixelHistogram | iapidCBProcessBayerParity, PropViewFrame::OnAnalysisPlotCBProcessBayerParity)
	EVT_SPINCTRL(widPixelHistogram | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxChanged)
	EVT_SPINCTRL(widPixelHistogram | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyChanged)
	EVT_SPINCTRL(widPixelHistogram | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwChanged)
	EVT_SPINCTRL(widPixelHistogram | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhChanged)
	EVT_SPINCTRL(widPixelHistogram | iapidSCDrawStart_percent, PropViewFrame::OnAnalysisPlotDrawStartChanged)
	EVT_SPINCTRL(widPixelHistogram | iapidSCDrawWindow_percent, PropViewFrame::OnAnalysisPlotDrawWindowChanged)
	EVT_SPINCTRL(widPixelHistogram | iapidSCDrawStepWidth, PropViewFrame::OnAnalysisPlotDrawStepWidthChanged)
	EVT_SPINCTRL(widPixelHistogram | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedChanged)
	EVT_NOTEBOOK_PAGE_CHANGED(widPixelHistogram | iapidNBDisplayMethod, PropViewFrame::OnNBDisplayMethodPageChanged)

	EVT_CHECKBOX(widNoiseHistogram | iapidCBAOIFullMode, PropViewFrame::OnAnalysisPlotCBAOIFullMode)
	EVT_CHECKBOX(widNoiseHistogram | iapidCBProcessBayerParity, PropViewFrame::OnAnalysisPlotCBProcessBayerParity)
	EVT_SPINCTRL(widNoiseHistogram | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxChanged)
	EVT_SPINCTRL(widNoiseHistogram | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyChanged)
	EVT_SPINCTRL(widNoiseHistogram | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwChanged)
	EVT_SPINCTRL(widNoiseHistogram | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhChanged)
	EVT_SPINCTRL(widNoiseHistogram | iapidSCDrawStart_percent, PropViewFrame::OnAnalysisPlotDrawStartChanged)
	EVT_SPINCTRL(widNoiseHistogram | iapidSCDrawWindow_percent, PropViewFrame::OnAnalysisPlotDrawWindowChanged)
	EVT_SPINCTRL(widNoiseHistogram | iapidSCDrawStepWidth, PropViewFrame::OnAnalysisPlotDrawStepWidthChanged)
	EVT_SPINCTRL(widNoiseHistogram | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedChanged)
	EVT_NOTEBOOK_PAGE_CHANGED(widNoiseHistogram | iapidNBDisplayMethod, PropViewFrame::OnNBDisplayMethodPageChanged)

	EVT_CHECKBOX(widLineProfile | iapidCBAOIFullMode, PropViewFrame::OnAnalysisPlotCBAOIFullMode)
	EVT_CHECKBOX(widLineProfile | iapidCBProcessBayerParity, PropViewFrame::OnAnalysisPlotCBProcessBayerParity)
	EVT_SPINCTRL(widLineProfile | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxChanged)
	EVT_SPINCTRL(widLineProfile | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyChanged)
	EVT_SPINCTRL(widLineProfile | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwChanged)
	EVT_SPINCTRL(widLineProfile | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhChanged)
	EVT_SPINCTRL(widLineProfile | iapidSCDrawStart_percent, PropViewFrame::OnAnalysisPlotDrawStartChanged)
	EVT_SPINCTRL(widLineProfile | iapidSCDrawWindow_percent, PropViewFrame::OnAnalysisPlotDrawWindowChanged)
	EVT_SPINCTRL(widLineProfile | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedChanged)
	EVT_NOTEBOOK_PAGE_CHANGED(widLineProfile | iapidNBDisplayMethod, PropViewFrame::OnNBDisplayMethodPageChanged)

	EVT_CHECKBOX(widIntensityPlot | iapidCBAOIFullMode, PropViewFrame::OnAnalysisPlotCBAOIFullMode)
	EVT_CHECKBOX(widIntensityPlot | iapidCBProcessBayerParity, PropViewFrame::OnAnalysisPlotCBProcessBayerParity)
	EVT_SPINCTRL(widIntensityPlot | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxChanged)
	EVT_SPINCTRL(widIntensityPlot | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyChanged)
	EVT_SPINCTRL(widIntensityPlot | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwChanged)
	EVT_SPINCTRL(widIntensityPlot | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhChanged)
	EVT_TEXT(widIntensityPlot | iapidCoBPlotSelection , PropViewFrame::OnAnalysisPlot_PlotSelectionChanged)
	EVT_SPINCTRL(widIntensityPlot | iapidSCHistoryDepth, PropViewFrame::OnAnalysisPlotHistoryDepthChanged)
	EVT_SPINCTRL(widIntensityPlot | iapidSCDrawStart_percent, PropViewFrame::OnAnalysisPlotDrawStartChanged)
	EVT_SPINCTRL(widIntensityPlot | iapidSCDrawWindow_percent, PropViewFrame::OnAnalysisPlotDrawWindowChanged)
	EVT_SPINCTRL(widIntensityPlot | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedChanged)
	EVT_NOTEBOOK_PAGE_CHANGED(widIntensityPlot | iapidNBDisplayMethod, PropViewFrame::OnNBDisplayMethodPageChanged)

	EVT_CHECKBOX(widVectorScope | iapidCBAOIFullMode, PropViewFrame::OnAnalysisPlotCBAOIFullMode)
	EVT_SPINCTRL(widVectorScope | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxChanged)
	EVT_SPINCTRL(widVectorScope | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyChanged)
	EVT_SPINCTRL(widVectorScope | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwChanged)
	EVT_SPINCTRL(widVectorScope | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhChanged)
	EVT_SPINCTRL(widVectorScope | iapidSCGridStepsX, PropViewFrame::OnAnalysisPlotGridXStepsChanged)
	EVT_SPINCTRL(widVectorScope | iapidSCGridStepsY, PropViewFrame::OnAnalysisPlotGridYStepsChanged)
	EVT_SPINCTRL(widVectorScope | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedChanged)
	EVT_NOTEBOOK_PAGE_CHANGED(widVectorScope | iapidNBDisplayMethod, PropViewFrame::OnNBDisplayMethodPageChanged)

	EVT_TEXT(widInfoPlot_PlotSelectionCombo, PropViewFrame::OnInfoPlot_PlotSelectionComboTextChanged)
	EVT_CHECKBOX(widCBEnableInfoPlot, PropViewFrame::OnCBEnableInfoPlot)
	EVT_SPINCTRL(widSCInfoPlotHistoryDepth, PropViewFrame::OnInfoPlotUpdateHistoryDepthChanged)
	EVT_SPINCTRL(widSCInfoPlotUpdateSpeed, PropViewFrame::OnInfoPlotUpdateSpeedChanged)

#ifdef BUILD_WITH_TEXT_EVENTS_FOR_SPINCTRL // BAT: Unfortunately on linux wxWidgets 2.6.x - ??? handling these messages will cause problems, while on Windows not doing so will not always update the GUI as desired :-(
	EVT_TEXT(widPixelHistogram | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxTextChanged)
	EVT_TEXT(widPixelHistogram | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyTextChanged)
	EVT_TEXT(widPixelHistogram | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwTextChanged)
	EVT_TEXT(widPixelHistogram | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhTextChanged)
	EVT_TEXT(widPixelHistogram | iapidSCDrawStart_percent, PropViewFrame::OnAnalysisPlotDrawStartTextChanged)
	EVT_TEXT(widPixelHistogram | iapidSCDrawWindow_percent, PropViewFrame::OnAnalysisPlotDrawWindowTextChanged)
	EVT_TEXT(widPixelHistogram | iapidSCDrawStepWidth, PropViewFrame::OnAnalysisPlotDrawStepWidthTextChanged)
	EVT_TEXT(widPixelHistogram | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedTextChanged)

	EVT_TEXT(widNoiseHistogram | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxTextChanged)
	EVT_TEXT(widNoiseHistogram | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyTextChanged)
	EVT_TEXT(widNoiseHistogram | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwTextChanged)
	EVT_TEXT(widNoiseHistogram | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhTextChanged)
	EVT_TEXT(widNoiseHistogram | iapidSCDrawStart_percent, PropViewFrame::OnAnalysisPlotDrawStartTextChanged)
	EVT_TEXT(widNoiseHistogram | iapidSCDrawWindow_percent, PropViewFrame::OnAnalysisPlotDrawWindowTextChanged)
	EVT_TEXT(widNoiseHistogram | iapidSCDrawStepWidth, PropViewFrame::OnAnalysisPlotDrawStepWidthTextChanged)
	EVT_TEXT(widNoiseHistogram | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedTextChanged)

	EVT_TEXT(widLineProfile | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxTextChanged)
	EVT_TEXT(widLineProfile | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyTextChanged)
	EVT_TEXT(widLineProfile | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwTextChanged)
	EVT_TEXT(widLineProfile | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhTextChanged)
	EVT_TEXT(widLineProfile | iapidSCDrawStart_percent, PropViewFrame::OnAnalysisPlotDrawStartTextChanged)
	EVT_TEXT(widLineProfile | iapidSCDrawWindow_percent, PropViewFrame::OnAnalysisPlotDrawWindowTextChanged)
	EVT_TEXT(widLineProfile | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedTextChanged)

	EVT_TEXT(widIntensityPlot | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxTextChanged)
	EVT_TEXT(widIntensityPlot | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyTextChanged)
	EVT_TEXT(widIntensityPlot | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwTextChanged)
	EVT_TEXT(widIntensityPlot | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhTextChanged)
	EVT_TEXT(widIntensityPlot | iapidSCHistoryDepth, PropViewFrame::OnAnalysisPlotHistoryDepthTextChanged)
	EVT_TEXT(widIntensityPlot | iapidSCDrawStart_percent, PropViewFrame::OnAnalysisPlotDrawStartTextChanged)
	EVT_TEXT(widIntensityPlot | iapidSCDrawWindow_percent, PropViewFrame::OnAnalysisPlotDrawWindowTextChanged)
	EVT_TEXT(widIntensityPlot | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedTextChanged)

	EVT_TEXT(widVectorScope | iapidSCAOIx, PropViewFrame::OnAnalysisPlotAOIxTextChanged)
	EVT_TEXT(widVectorScope | iapidSCAOIy, PropViewFrame::OnAnalysisPlotAOIyTextChanged)
	EVT_TEXT(widVectorScope | iapidSCAOIw, PropViewFrame::OnAnalysisPlotAOIwTextChanged)
	EVT_TEXT(widVectorScope | iapidSCAOIh, PropViewFrame::OnAnalysisPlotAOIhTextChanged)
	EVT_TEXT(widVectorScope | iapidSCGridStepsX, PropViewFrame::OnAnalysisPlotGridXStepsTextChanged)
	EVT_TEXT(widVectorScope | iapidSCGridStepsY, PropViewFrame::OnAnalysisPlotGridYStepsTextChanged)
	EVT_TEXT(widVectorScope | iapidSCUpdateSpeed, PropViewFrame::OnAnalysisPlotUpdateSpeedTextChanged)

	EVT_TEXT(widSCInfoPlotHistoryDepth, PropViewFrame::OnInfoPlotUpdateHistoryDepthTextChanged)
	EVT_TEXT(widSCInfoPlotUpdateSpeed, PropViewFrame::OnInfoPlotUpdateSpeedTextChanged)
#endif
END_EVENT_TABLE()

//-----------------------------------------------------------------------------
PropViewFrame::PropViewFrame( const wxString& title, const wxPoint& pos, const wxSize& size, int argc, wxChar** argv )
: PropGridFrameBase(widMainFrame, title, pos, size), m_boCloseDeviceInProgress(false), m_boDisplayWindowMaximized(false), m_boShutdownInProgress(false),
   m_boUpdateAOIInProgress(false), m_boCurrentImageIsFromFile(false), m_boImageCanvasInFullScreenMode(false), m_CurrentImageAnalysisControlIndex(-1),
   m_DeviceListChangedCounter(numeric_limits<unsigned int>::max()),
   m_DeviceCount(0), m_NoDevStr(wxT("no device")), m_pDevPropHandler(0), m_pLastMouseHooverDisplay(0), m_pCurrentAnalysisDisplay(0),
   m_CurrentRequestDataIndex(0), m_pUserExperienceCombo(0), m_pLogWindow(0),
   m_defaultDeviceInterfaceLayout(dilGenICam), m_harddiscRecordingParameters()
//-----------------------------------------------------------------------------
{
	// create the menu
	/* Keyboard shortcuts:
			CTRL+A : imageRequestReset(Abort)
		ALT+CTRL+A : Analysis tab on/off
			CTRL+B : Blit on/off
		ALT+CTRL+B : Backward in captured sequence
			CTRL+C : Create capture setting
			CTRL+D : Assign capture settings to display(s)
		ALT+CTRL+D : Show connected devices only on/off
		ALT+CTRL+F : Forward in captured sequence
			CTRL+G : Switch on/off selector grouping
			CTRL+H : Display capture setting hierarchy
		ALT+CTRL+H : Array property indices will be displayed as HEX on/off
			CTRL+I : Single snap(Capture image)
		ALT+CTRL+I : Display incomplete image on/off
			CTRL+L : Live
			CTRL+M : Show Monitor Image
			CTRL+O : Load device settings from default location
		ALT+CTRL+O : Load device settings from file
			CTRL+P : Use Display names for grid features if available
		ALT+CTRL+P : Property grid on/off
			CTRL+R : Record mode on/off
			CTRL+S : Save active device settings to default location
		ALT+CTRL+S : Save active device settings to file
			CTRL+T : Show tool bar on/off
		ALT+CTRL+T : Show status bar on/off
			CTRL+U : Open/Close Device
		ALT+CTRL+U : Update device list
			CTRL+Q : Set capture queue depth
		ALT+     X : Exit
			   F1  : Display 'About' dialog
			   F2  : Default Device Interface Layout 'Device Specific'
			   F3  : Default Device Interface Layout 'Generic'
			   F4  : Default Device Interface Layout 'GenICam'
			   F5  : Grid view mode 'Standard'
			   F6  : Grid view mode 'Developer'
			   F9  : Settings -> Capture Settings -> Usage Mode 'Manual'
			   F10 : Settings -> Capture Settings -> Usage Mode 'Automatic'
			   F11 : Settings -> Full Screen mode on/off
			   F12 : Display driver information dialog
	*/

	// sub menu 'Action -> Settings -> Save'
	wxMenu* pMenuActionSettingsSave = new wxMenu;
	m_pMIAction_Settings_Save_ToDefault = pMenuActionSettingsSave->Append( miAction_Settings_Save_ToDefault, wxT("Device Settings To Default(user specific, for this product family)") );
	m_pMIAction_Settings_Save_SystemToDefault = pMenuActionSettingsSave->Append( miAction_Settings_Save_SystemToDefault, wxT("System Settings To Default(user specific, for this product family)") );
	m_pMIAction_Settings_Save_CurrentProduct = pMenuActionSettingsSave->Append( miAction_Settings_Save_CurrentProduct, wxT("Current Product Settings") );
	m_pMIAction_Settings_Save_ActiveDevice = pMenuActionSettingsSave->Append( miAction_Settings_Save_ActiveDevice, wxT("Active Device Settings\tCTRL+S") );
	m_pMIAction_Settings_Save_ExportActiveDevice = pMenuActionSettingsSave->Append( miAction_Settings_Save_ExportActiveDevice, wxT("Active Device Settings To File\tALT+CTRL+S"), wxT("Stores the current settings for this device in a platform independent XML file") );

	// sub menu 'Action -> Settings -> Load'
	wxMenu* pMenuActionSettingsLoad = new wxMenu;
	m_pMIAction_Settings_Load_FromDefault = pMenuActionSettingsLoad->Append( miAction_Settings_Load_FromDefault, wxT("Default(user specific, for this product family)") );
	m_pMIAction_Settings_Load_CurrentProduct = pMenuActionSettingsLoad->Append( miAction_Settings_Load_CurrentProduct, wxT("Current Product Settings") );
	m_pMIAction_Settings_Load_ActiveDevice = pMenuActionSettingsLoad->Append( miAction_Settings_Load_ActiveDevice, wxT("Active Device Settings\tCTRL+O") );
	m_pMIAction_Settings_Load_ImportActiveDevice = pMenuActionSettingsLoad->Append( miAction_Settings_Load_ImportActiveDevice, wxT("Active Device Settings From File\tALT+CTRL+O"), wxT("Tries to loads settings for this device from a platform independent XML file") );

	// sub menu 'Action -> Settings'
	wxMenu* pMenuActionSettings = new wxMenu;
	pMenuActionSettings->Append( wxID_ANY, wxT("Save"), pMenuActionSettingsSave );
	pMenuActionSettings->Append( wxID_ANY, wxT("Load"), pMenuActionSettingsLoad );
	m_pMIAction_Settings_Manage = pMenuActionSettings->Append( miAction_Settings_Manage, wxT("Manage..." ) );

	// sub menu 'Action -> Save All Recorded Images'
	wxMenu* pMenuAction_SaveAllRecordedImages = new wxMenu;
	m_pMIAction_SaveImageSequenceToFiles = pMenuAction_SaveAllRecordedImages->Append( miAction_SaveImageSequenceToFiles, wxT("Save Images Into Separate Files...") );
	m_pMIAction_SaveImageSequenceToStream = pMenuAction_SaveAllRecordedImages->Append( miAction_SaveImageSequenceToStream, wxT("Save Images Into Stream...") );

	// menu 'Action'
	wxMenu* pMenuAction = new wxMenu;
	m_pMIAction_Use = pMenuAction->Append( miAction_UseDevice, wxT("&Use Device\tCTRL+U"), wxT("Opens or closes the selected device"), wxITEM_CHECK );
	m_pMIAction_UpdateDeviceList = pMenuAction->Append( miAction_UpdateDeviceList, wxT("&Update Device List\tALT+CTRL+U") );
	pMenuAction->Append( wxID_ANY, wxT("Settings"), pMenuActionSettings );
	pMenuAction->AppendSeparator();
	m_pMIAction_LoadImage = pMenuAction->Append( miAction_LoadImage, wxT("Load Image...") );
	m_pMIAction_SaveImage = pMenuAction->Append( miAction_SaveImage, wxT("Save Image...") );
	pMenuAction->Append( wxID_ANY, wxT("Save All Recorded Images..."), pMenuAction_SaveAllRecordedImages );
	pMenuAction->AppendSeparator();
	pMenuAction->Append( miQuit, wxT("E&xit\tALT+X") );

	// sub menu 'Capture -> Recording'
	wxMenu* pMenuSettingsRecording = new wxMenu;
	m_pMICapture_Recording_SlientMode = pMenuSettingsRecording->AppendCheckItem( miCapture_Recording_SilentMode, wxT("Silent Mode"), wxT("Check this to disable all recording related dialogs") );
	m_pMICapture_Recording_Continuous = pMenuSettingsRecording->AppendCheckItem( miCapture_Recording_Continuous, wxT("Continuous"), wxT("Check this to enable continuous recording") );
	m_pMICapture_Recording_SetupSequenceSize = pMenuSettingsRecording->Append( miCapture_Recording_SetupSequenceSize, wxT("Setup Sequence Size"), wxT("Sets the number of buffers that will be recorded during a recording session that stops automatically") );
	m_pMICapture_Recording_SetupHarddiscRecording = pMenuSettingsRecording->Append( miCapture_Recording_SetupHarddiscRecording, wxT("Setup Harddisc Recording"), wxT("Configures automatic harddisc recording") );

	// sub menu 'Capture -> Capture Settings -> Usage Mode'
	wxMenu* pMenuCaptureCaptureSettingsUsageMode = new wxMenu;
	m_pMICapture_CaptureSettings_UsageMode_Manual = pMenuCaptureCaptureSettingsUsageMode->Append( miCapture_CaptureSettings_UsageMode_Manual, wxT("Manual\tF9"), wxT(""), wxITEM_RADIO );
	m_pMICapture_CaptureSettings_UsageMode_Automatic = pMenuCaptureCaptureSettingsUsageMode->Append( miCapture_CaptureSettings_UsageMode_Automatic, wxT("Automatic\tF10"), wxT(""), wxITEM_RADIO );

	// sub menu 'Capture -> Capture Settings'
	wxMenu* pMenuCaptureCaptureSettings = new wxMenu;
	m_pMICapture_CaptureSettings_CreateCaptureSetting = pMenuCaptureCaptureSettings->Append( miCapture_CaptureSettings_CreateCaptureSetting, wxT("Create Capture Setting...\tCTRL+C"), wxT("Creates a new capture setting to configure for acquisition") );
	m_pMICapture_CaptureSettings_CaptureSettingHierarchy = pMenuCaptureCaptureSettings->Append( miCapture_CaptureSettings_CaptureSettingHierarchy, wxT("Capture Setting Hierarchy...\tCTRL+H"), wxT("Displays the current capture setting parent <-> child relationships") );
	m_pMICapture_CaptureSettings_AssignToDisplays = pMenuCaptureCaptureSettings->Append( miCapture_CaptureSettings_AssignToDisplays, wxT("Assign To Display(s)...\tCTRL+D"), wxT("Opens a dialog to configure the display <-> setting relationships if there is more then one display") );
	pMenuCaptureCaptureSettings->Append( wxID_ANY, wxT("Usage Mode"), pMenuCaptureCaptureSettingsUsageMode );

	// menu 'Capture'
	wxMenu* pMenuCapture = new wxMenu;
	m_pMICapture_Live = pMenuCapture->Append( miCapture_Live, wxT("&Live\tCTRL+L"), wxT("Starts or stops a continuous acquisition"), wxITEM_CHECK );
	m_pMICapture_Snap = pMenuCapture->Append( miCapture_Snap, wxT("S&ingle Snap\tCTRL+I"), wxT("Captures a single image from the selected device") );
	m_pMICapture_Abort = pMenuCapture->Append( miCapture_Abort, wxT("&Abort\tCTRL+A"), wxT("Clears the request queue, but does NOT stop a running continuous acquisition") );
	pMenuCapture->AppendSeparator();
	m_pMICapture_Record = pMenuCapture->Append( miCapture_Record, wxT("&Record\tCTRL+R"), wxT("Records the next 'RequestCount'(System Settings) images"), wxITEM_CHECK );
	m_pMICapture_Forward = pMenuCapture->Append( miCapture_Forward, wxT("&Forward\tALT+CTRL+F"), wxT("Displays the next recorded image") );
	m_pMICapture_Backward = pMenuCapture->Append( miCapture_Backward, wxT("&Backward\tALT+CTRL+B"), wxT("Displays the previous recorded image") );
	pMenuCapture->Append( wxID_ANY, wxT("&Recording"), pMenuSettingsRecording );
	pMenuCapture->AppendSeparator();
	pMenuCapture->Append( wxID_ANY, wxT("Capture Settings"), pMenuCaptureCaptureSettings );
	m_pMICapture_SetupCaptureQueueDepth = pMenuCapture->Append( miCapture_SetupCaptureQueueDepth, wxT("Setup Capture Queue Depth\tCTRL+Q"), wxT("Sets the number of buffers that will be used to prefill the capture queue") );

	// sub menu 'Settings -> Property grid'
	wxMenu* pMenuSettingsPropertyGrid = new wxMenu;
	m_pMISettings_PropGrid_Show = pMenuSettingsPropertyGrid->Append( miSettings_PropGrid_Show, wxT("Show &Property Grid\tALT+CTRL+P"), wxT(""), wxITEM_CHECK );
	m_pMISettings_PropGrid_DisplayPropIndicesAsHex = pMenuSettingsPropertyGrid->Append( miSettings_PropGrid_DisplayPropIndicesAsHex, wxT("Display Property Indices As &Hex\tALT+CTRL+H"), wxT(""), wxITEM_CHECK );
	m_pMISettings_PropGrid_UseDisplayNameIfAvailable = pMenuSettingsPropertyGrid->Append( miSettings_PropGrid_UseDisplayNameIfAvailable, wxT("Use Dis&play Names If Available\tCTRL+P"), wxT(""), wxITEM_CHECK );
	m_pMISettings_PropGrid_UseSelectorGrouping = pMenuSettingsPropertyGrid->Append( miSettings_PropGrid_UseSelectorGrouping, wxT("Use Selector Grouping\tCTRL+G"), wxT(""), wxITEM_CHECK );
	pMenuSettingsPropertyGrid->AppendSeparator();
	m_pMISettings_PropGrid_StandardView = pMenuSettingsPropertyGrid->Append( miSettings_PropGrid_StandardView, wxT("Standard View\tF5"), wxT(""), wxITEM_RADIO );
	m_pMISettings_PropGrid_DevelopersView = pMenuSettingsPropertyGrid->Append( miSettings_PropGrid_DevelopersView, wxT("Developers View\tF6"), wxT(""), wxITEM_RADIO );

	// sub menu 'Settings -> Display'
	wxMenu* pMenuSettingsDisplay = new wxMenu;
	m_pMISettings_Display_Active = pMenuSettingsDisplay->Append( miSettings_Display_Active, wxT("&Blit Active\tCTRL+B"), wxT("If not active images will be captured, but will NOT displayed"), wxITEM_CHECK );
	m_pMISettings_Display_ShowIncompleteFrames = pMenuSettingsDisplay->Append( miSettings_Display_ShowIncompleteFrames, wxT("Show &Incomplete Frames\tALT+CTRL+I"), wxT("If active incomplete frames are displayed as well"), wxITEM_CHECK );
	pMenuSettingsDisplay->AppendSeparator();
	m_pMISettings_Display_ShowMonitorImage = pMenuSettingsDisplay->Append( miSettings_Display_ShowMonitorImage, wxT("Show &Monitor Image\tCTRL+M"), wxT("") , wxITEM_CHECK );

	// sub menu 'Settings -> Analysis'
	wxMenu* pMenuSettingsAnalysis = new wxMenu;
	m_pMISettings_Analysis_ShowControls = pMenuSettingsAnalysis->Append( miSettings_Analysis_ShowControls, wxT("Show &Analysis Tabs\tALT+CTRL+A"), wxT(""), wxITEM_CHECK );
	m_pMISettings_Analysis_SynchroniseAOIs = pMenuSettingsAnalysis->Append( wxID_ANY, wxT("Synchronise AOIs"), wxT(""), wxITEM_CHECK );

	// sub menu 'Settings -> Default Device Interface'
	wxMenu* pMenuSettingsDefaultDeviceInterface = new wxMenu;
	m_pMISettings_DefaultDeviceInterface_DeviceSpecific = pMenuSettingsDefaultDeviceInterface->Append( miSettings_DefaultDeviceInterface_DeviceSpecific, wxT("Device Specific\tF2"), wxT(""), wxITEM_RADIO );
	m_pMISettings_DefaultDeviceInterface_Generic = pMenuSettingsDefaultDeviceInterface->Append( miSettings_DefaultDeviceInterface_Generic, wxT("Generic\tF3"), wxT(""), wxITEM_RADIO );
	m_pMISettings_DefaultDeviceInterface_GenICam = pMenuSettingsDefaultDeviceInterface->Append( miSettings_DefaultDeviceInterface_GenICam, wxT("GenICam\tF4"), wxT(""), wxITEM_RADIO );

	// menu 'Settings'
	wxMenu* pMenuSettings = new wxMenu;
	pMenuSettings->Append( wxID_ANY, wxT("Property Grid"), pMenuSettingsPropertyGrid );
	pMenuSettings->Append( wxID_ANY, wxT("Image Display"), pMenuSettingsDisplay );
	pMenuSettings->Append( wxID_ANY, wxT("Analysis"), pMenuSettingsAnalysis );
	m_pMISettings_ShowToolBar = pMenuSettings->Append( miSettings_ShowToolBar, wxT("Show &Tool Bar\tCTRL+T"), wxT(""), wxITEM_CHECK );
	m_pMISettings_ShowStatusBar = pMenuSettings->Append( miSettings_ShowStatusBar, wxT("Show S&tatus Bar\tALT+CTRL+T"), wxT(""), wxITEM_CHECK );
	m_pMISettings_ToggleFullScreenMode = pMenuSettings->Append( miSettings_ToggleFullScreenMode, wxT("Full Screen Mode\tF11"), wxT(""), wxITEM_CHECK );
	pMenuSettings->AppendSeparator();
	m_pMISettings_ShowConnectedOnly = pMenuSettings->Append( miSettings_ShowConnectedDevicesOnly, wxT("Display &Connected Devices Only\tALT+CTRL+D"), wxT(""), wxITEM_CHECK );
	pMenuSettings->Append( wxID_ANY, wxT("Default Device Interface Layout"), pMenuSettingsDefaultDeviceInterface );

	// menu 'About'
	wxMenu* pMenuAbout = new wxMenu;
	pMenuAbout->Append( miHelp_About, wxT("About\tF1"));
	pMenuAbout->Append( miHelp_DriverInformation, wxT("Driver Information\tF12"));

	// add all menus to the menu bar
	wxMenuBar* pMenuBar = new wxMenuBar;
	pMenuBar->Append( pMenuAction, wxT("&Action") );
	pMenuBar->Append( pMenuCapture, wxT("&Capture") );
	pMenuBar->Append( pMenuSettings, wxT("&Settings") );
	pMenuBar->Append( pMenuAbout, wxT("&Help") );
	// ... and attach this menu bar to the frame
	SetMenuBar(pMenuBar);

	// define the applications icon
	wxIcon icon(mvIcon_xpm);
	SetIcon( icon );

	// scan command line
	bool boDisplayDebugInfo = false;
	bool boDisplayFullTree = false;
	bool boDisplayInvisibleComponents = false;
	bool boOpenDeviceInLiveMode = false;
	bool boShowEvents = false;
	wxString processedParameters;
	wxString serialToOpen;
	wxString fileToOpen;
	unsigned int displayCountX = 1;
	unsigned int displayCountY = 1;
	wxRect cmdLineRect(-1, -1, -1, -1);
	double splitterratio = 0.;
	wxString parserErrors;
	for( int i=1; i<argc; i++ )
	{
		wxString key, value;
		wxString param(argv[i]);
		key = param.BeforeFirst( wxT('=') );
		value = param.AfterFirst( wxT('=') );
		if( key.IsEmpty() )
		{
			parserErrors.Append( wxString::Format( wxT("Invalid command line parameter: '%s'. Ignored.\n"), param.c_str() ) );
		}
		else
		{
			if( value.IsEmpty() )
			{
				fileToOpen = param;
			}
			else
			{
				if( ( key == wxT("width") ) || ( key == wxT("w") ) )
				{
					cmdLineRect.width = atoi( value.mb_str() );
				}
				else if( ( key == wxT("height") ) || ( key == wxT("h") ) )
				{
					cmdLineRect.height = atoi( value.mb_str() );
				}
				else if( ( key == wxT("xpos") ) || ( key == wxT("x") ) )
				{
					cmdLineRect.x = atoi( value.mb_str() );
				}
				else if( ( key == wxT("ypos") ) || ( key == wxT("y") ) )
				{
					cmdLineRect.y = atoi( value.mb_str() );
				}
				else if( key == wxT("splitterratio") )
				{
					splitterratio = atof( value.mb_str() );
				}
				else if( ( key == wxT("propgridwidth") ) || ( key == wxT("pgw") ) )
				{
					m_VerticalSplitterPos = atoi( value.mb_str() );
				}
				else if( ( key == wxT("debuginfo") ) || ( key == wxT("di") ) )
				{
					boDisplayDebugInfo = ( atoi( value.mb_str() ) != 0 );
				}
				else if( ( key == wxT("dic") ) )
				{
					boDisplayInvisibleComponents = ( atoi( value.mb_str() ) != 0 );
				}
				else if( ( key == wxT("fulltree") ) || ( key == wxT("ft") ) )
				{
					boDisplayFullTree = ( atoi( value.mb_str() ) != 0 );
				}
				else if( ( key == wxT("device") ) || ( key == wxT("d") ) )
				{
					serialToOpen = value;
				}
				else if( key == wxT("live") )
				{
					boOpenDeviceInLiveMode = ( atoi( value.mb_str() ) != 0 );
				}
				else if( ( key == wxT("showEvents") ) || ( key == wxT("se") ) )
				{
					boShowEvents = ( atoi( value.mb_str() ) != 0 );
				}
				else if( ( key == wxT("displayCountX") ) || ( key == wxT("dcx") ) )
				{
					displayCountX = atoi( value.mb_str() );
					if( displayCountX > DISPLAY_COUNT_MAX )
					{
						displayCountX = DISPLAY_COUNT_MAX;
						parserErrors.Append( wxString::Format( wxT("Too many displays in X-direction: '%s'. %d is the current maximum.\n"), param.c_str(), displayCountX ) );
					}
				}
				else if( ( key == wxT("displayCountY") ) || ( key == wxT("dcy") ) )
				{
					displayCountY = atoi( value.mb_str() );
					if( displayCountY > DISPLAY_COUNT_MAX )
					{
						displayCountY = DISPLAY_COUNT_MAX;
						parserErrors.Append( wxString::Format( wxT("Too many displays in Y-direction: '%s'. %d is the current maximum.\n"), param.c_str(), displayCountY ) );
					}
				}
				else
				{
					parserErrors.Append( wxString::Format( wxT("Invalid command line parameter: '%s'. Ignored.\n"), param.c_str() ) );
				}
			}
			processedParameters += param;
			processedParameters.Append( wxT(' ') );
		}
	}

	// create all GUI elements
	/*
		|-------------------|
		|buttons            |
		|-------------------|
		|prop-  | display   |
		|grid   |           |
		|       |           |
		|       |-----------|
		|       | output    |
		|       |           |
		|-------------------|
	*/
	wxBoxSizer* pTopDownSizer = new wxBoxSizer(wxVERTICAL);
	m_pPanel = new wxPanel(this);

	// the toolbar
	m_pToolBar = CreateToolBar( wxNO_BORDER | wxHORIZONTAL | wxTB_FLAT | wxTB_TEXT );
	m_pToolBar->SetMargins( 5, 5 );
	m_pToolBar->SetToolBitmapSize( wxSize(32, 16) );
	m_pToolBar->SetToolSeparation( 10 );

	wxStaticText *pStaticText = new wxStaticText(m_pToolBar, wxID_ANY, wxT(" Device "));
	m_pToolBar->AddControl( pStaticText );
	m_pDevCombo = new wxComboBox(m_pToolBar, widDevCombo, wxT(" Device "), wxDefaultPosition, wxSize(200,wxDefaultCoord), 0, NULL, wxCB_DROPDOWN | wxCB_READONLY);
	m_pDevCombo->Select(0);
	m_pDevCombo->SetToolTip( wxT("Contains a list of all device detected. If devices seem to miss make sure these are connected AND a driver for the corresponding device family has been installed") );
	m_pToolBar->AddControl( m_pDevCombo );

	pStaticText = new wxStaticText(m_pToolBar, wxID_ANY, wxT("  "));
	m_pToolBar->AddControl( pStaticText );
	m_pToolBar->AddTool( miAction_UseDevice, wxT("Use"), Use_xpm, wxNullBitmap, wxITEM_CHECK,
		wxT("Opens or closes the selected device"),
		wxT("Opens or closes the selected device") );
	m_pToolBar->AddTool( miAction_UpdateDeviceList, wxT("Update"), Update_xpm, wxNullBitmap, wxITEM_NORMAL,
		wxT("Updates the device list"),
		wxT("Updates the device list") );
	m_pToolBar->AddSeparator();
	m_pToolBar->AddTool( miCapture_Live, wxT("Live"), live_xpm, wxNullBitmap, wxITEM_CHECK,
		wxT("Starts or stops continuous acquisition from the selected device"),
		wxT("Starts or stops continuous acquisition from the selected device") );
	m_pToolBar->AddTool( miCapture_Snap, wxT("Snap"), photo_xpm, wxNullBitmap, wxITEM_NORMAL,
		wxT("Captures a single image from the selected device"),
		wxT("Captures a single image from the selected device") );
	m_pToolBar->AddTool( miCapture_Abort, wxT("Abort"), abort_xpm, wxNullBitmap, wxITEM_NORMAL,
		wxT("Empties the image request queue for the selected device but does NOT stop a running continuous acquisition"),
		wxT("Empties the image request queue for the selected device but does NOT stop a running continuous acquisition") );
	m_pToolBar->AddSeparator();
	m_pToolBar->AddTool( miCapture_Record, wxT("Rec."), record_xpm, wxNullBitmap, wxITEM_CHECK,
		wxT("Records the next 'RequestCount'(System Settings) images"),
		wxT("Records the next 'RequestCount'(System Settings) images") );
	m_pToolBar->AddTool( miCapture_Backward, wxT("Prev."), back_xpm, wxNullBitmap, wxITEM_NORMAL,
		wxT("Displays the previous recorded image"),
		wxT("Displays the previous recorded image") );
	m_pToolBar->AddTool( miCapture_Forward, wxT("Next"), forward_xpm, wxNullBitmap, wxITEM_NORMAL,
		wxT("Displays the next recorded image"),
		wxT("Displays the next recorded image") );
	m_pRecordDisplaySlider = new wxSlider(m_pToolBar, widSLRecordDisplay, 0, 0, 1000, wxDefaultPosition, wxSize(150, -1), wxSL_HORIZONTAL | wxSL_LABELS);
	m_pRecordDisplaySlider->SetToolTip( wxT("Can be used to quickly move within a recorded sequence of images") );
	m_pToolBar->AddControl( m_pRecordDisplaySlider );
	m_pToolBar->AddSeparator();
	m_pToolBar->AddTool( miSettings_Display_Active, wxT("Blit"), DisplayActive_xpm, wxNullBitmap, wxITEM_CHECK,
		wxT("Turns the main display on or off"),
		wxT("Turns the main display on or off") );
	m_pToolBar->AddTool( miSettings_Display_ShowMonitorImage, wxT("Monitor"), DisplayActive_xpm, wxNullBitmap, wxITEM_CHECK,
		wxT("Displays or hides the scaled image to monitor the visible part of the main display(NOTE: This feature can only be used when the main display is active!)"),
		wxT("Displays or hides the scaled image to monitor the visible part of the main display(NOTE: This feature can only be used when the main display is active!)") );
	m_pToolBar->AddTool( miSettings_Analysis_ShowControls, wxT("Analysis"), LogWindow_xpm, wxNullBitmap, wxITEM_CHECK,
		wxT("Displays or hides the analysis tabs"),
		wxT("Displays or hides the analysis tabs") );
	m_pToolBar->AddTool( miSettings_PropGrid_Show, wxT("Grid"), PropertyGrid_xpm, wxNullBitmap, wxITEM_CHECK,
		wxT("Displays or hides the device property grid"),
		wxT("Displays or hides the device property grid") );
	m_pToolBar->AddSeparator();
	m_pToolBar->AddTool( miHelp_About, wxT("About"), help_xpm, wxNullBitmap, wxITEM_NORMAL,
		wxT("Displays the about dialog"),
		wxT("Displays the about dialog") );
	m_pToolBar->Realize();

	// splitter for property grid and the windows on the right
	m_pVerticalSplitter = new wxSplitterWindow(m_pPanel, widVerSplitter, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER);

	m_pSettingsPanel = new wxPanel(m_pVerticalSplitter);
	m_pSettingsPanel->SetWindowStyle( wxTAB_TRAVERSAL | wxSUNKEN_BORDER );

	// property grid on the left
	m_pNBConfigurationMethod = new wxNotebook(m_pSettingsPanel, widNBConfigurationMethod, wxDefaultPosition, wxDefaultSize);
	CreatePropertyGrid( m_pNBConfigurationMethod );
	m_pNBConfigurationMethod->AddPage( GetPropertyGrid(), wxT("Device Properties"), true );

	// a texr control below the property grid to display the selected properties doc string
	m_pToolTipWindow = new wxTextCtrl(m_pSettingsPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_RICH | wxTE_READONLY);

	wxBoxSizer* pSettingsSizer = new wxBoxSizer(wxVERTICAL);

	try
	{
		wxArrayString userExperiences;
		userExperiences.Add( wxString(ConvertedString(Component::visibilityAsString( cvBeginner ))) );
		userExperiences.Add( wxString(ConvertedString(Component::visibilityAsString( cvExpert ))) );
		userExperiences.Add( wxString(ConvertedString(Component::visibilityAsString( cvGuru ))) );
		//userExperiences.Add( wxString(ConvertedString(Component::visibilityAsString( cvInvisible ))) );
		// controls to adjust the level of user experience
		wxBoxSizer* pSettingsControlsSizer = new wxBoxSizer(wxHORIZONTAL);
		wxStaticText* pSTUserExperience = new wxStaticText(m_pSettingsPanel, wxID_ANY, wxT(" User Experience: "));
		pSTUserExperience->SetToolTip( wxT("Allows to select the appropriate level of visibility for the user. More experienced users may select a higher level of visibility to get access to more advanced features.") );
		pSettingsControlsSizer->Add( pSTUserExperience, wxSizerFlags().Center() );
		m_pUserExperienceCombo = new wxComboBox(m_pSettingsPanel, widUserExperienceCombo, userExperiences[0], wxDefaultPosition, wxSize(120,wxDefaultCoord), userExperiences, wxCB_DROPDOWN | wxCB_READONLY);
		m_pUserExperienceCombo->SetToolTip( wxT("Allows to select the appropriate level of visibility for the user. More experienced users may select a higher level of visibility to get access to more advanced features.") );
		pSettingsControlsSizer->Add( m_pUserExperienceCombo );
		pSettingsSizer->AddSpacer( 5 );
		pSettingsSizer->Add( pSettingsControlsSizer );
		GlobalDataStorage::Instance()->ConfigureComponentVisibilitySupport( true );
	}
	catch( const ImpactAcquireException& )
	{

	}
	pSettingsSizer->AddSpacer( 5 );
	pSettingsSizer->Add( m_pNBConfigurationMethod, wxSizerFlags(12).Expand() );
	pSettingsSizer->Add( m_pToolTipWindow, wxSizerFlags(1).Expand() );
	pSettingsSizer->AddSpacer( 5 );
	m_pSettingsPanel->SetSizer( pSettingsSizer );

	// splitter between the image display window and the notebook window in the lower right corner of the window
	m_pHorizontalSplitter = new wxSplitterWindow(m_pVerticalSplitter, widHorSplitter, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER);

	// the window(s) for displaying the images
	const unsigned int displayCount = displayCountX * displayCountY;
	m_pDisplayPanel = new wxPanel(m_pHorizontalSplitter);
	wxGridSizer* pDisplayGridSizer = new wxGridSizer(displayCountX, displayCountY);
	for( unsigned int i=0; i<displayCount; i++ )
	{
		ImageCanvas* pDisplayArea = new ImageCanvas(this, m_pDisplayPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN | wxHSCROLL | wxVSCROLL, wxEmptyString);
		pDisplayArea->SetUserData( i );
		pDisplayArea->EnableScrolling( true, true );
		pDisplayArea->SetDropTarget( new DnDFile(this, pDisplayArea) ); // this will allow to drop image files into the display area
		pDisplayGridSizer->Add( pDisplayArea, wxSizerFlags().Expand() );
		m_pDisplayAreas.push_back( pDisplayArea );
		m_CurrentRequestDataContainer.push_back( RequestData() );
		m_pDisplayAreas[i]->SetImage( m_CurrentRequestDataContainer[i].image_.getBuffer() );
	}
	m_pLastMouseHooverDisplay = m_pDisplayAreas[0];
	m_pCurrentAnalysisDisplay = m_pDisplayAreas[0];
	m_pDisplayPanel->SetSizer( pDisplayGridSizer );

	// A separate window that displays the full, scaled image with an AOI on top showing the part of the image currently visible in the main display window
	m_pMonitorImage = new MonitorDisplay(this);

	// the window for the controls in the lower right corner of the application
	m_pLowerRightWindow = new wxNotebook(m_pHorizontalSplitter, widNotebook, wxDefaultPosition, wxDefaultSize);

	// log window (page of lower right notebook)
	m_pLogWindow = new wxTextCtrl(m_pLowerRightWindow, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_RICH | wxTE_READONLY);
	m_pLowerRightWindow->AddPage( m_pLogWindow, wxT("Output"), true );

	wxScrolledWindow* pAnalysisPanel = 0;
	for( int i=0; i<iapLAST; i++ )
	{
		pAnalysisPanel = CreateImageAnalysisPlotControls( m_pLowerRightWindow, BuildPlotWindowStartID( i ) );
		m_pLowerRightWindow->AddPage( pAnalysisPanel, m_ImageAnalysisPlots[GetAnalysisControlIndex( BuildPlotWindowStartID( i ) )].m_pPlotCanvas->GetName(), false );
	}

	// info plot window (page of lower right notebook)
	wxPanel* pPanelInfoPlot = new wxPanel(m_pLowerRightWindow);
	wxBoxSizer* pInfoPlotPanelSizer = new wxBoxSizer(wxHORIZONTAL);
	wxBoxSizer* pInfoPlotControlsSizer = new wxBoxSizer(wxVERTICAL);
	m_pCBEnableInfoPlot = new wxCheckBox(pPanelInfoPlot, widCBEnableInfoPlot, wxT("Enable"));
	pInfoPlotControlsSizer->Add( m_pCBEnableInfoPlot, wxSizerFlags().Left() );
	pInfoPlotControlsSizer->AddSpacer( 5 );

	wxFlexGridSizer* pInfoPlotControlsGridSizer = new wxFlexGridSizer(2, 0);
	pInfoPlotControlsGridSizer->Add( new wxStaticText(pPanelInfoPlot, wxID_ANY, wxT("Update interval:")) );
	m_pSCInfoPlotUpdateSpeed = new wxSpinCtrl( pPanelInfoPlot, widSCInfoPlotUpdateSpeed, wxT("3"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, PlotCanvas::ulMin, PlotCanvas::ulMax, 3 );
	pInfoPlotControlsGridSizer->Add( m_pSCInfoPlotUpdateSpeed, wxSizerFlags().Left() );
	pInfoPlotControlsGridSizer->Add( new wxStaticText(pPanelInfoPlot, wxID_ANY, wxT("History depth:")) );
	m_pSCInfoPlotHistoryDepth = new wxSpinCtrl( pPanelInfoPlot, widSCInfoPlotHistoryDepth, wxT("0"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 5, 10000, 20 );
	pInfoPlotControlsGridSizer->Add( m_pSCInfoPlotHistoryDepth, wxSizerFlags().Left() );
	pInfoPlotControlsGridSizer->Add( new wxStaticText(pPanelInfoPlot, wxID_ANY, wxT("Plot selection:")) );
	m_pInfoPlotSelectionCombo = new wxComboBox(pPanelInfoPlot, widInfoPlot_PlotSelectionCombo, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
	pInfoPlotControlsGridSizer->Add( m_pInfoPlotSelectionCombo, wxSizerFlags().Left() );
	m_pInfoPlotSelectionCombo->Select(0);
	m_pInfoPlotSelectionCombo->SetToolTip( wxT("Contains a list of possible plots that can be displayed on this page") );
	wxStaticText* pSTTimestampAsTime = new wxStaticText(pPanelInfoPlot, wxID_ANY, wxT("Timestamp as time:"));
	pSTTimestampAsTime->SetToolTip( wxT("This is the device timestamp converted into local time. This value only makes sense for devices that can create a timestamp in us since 01.01.1970 GMT(thus a timestamp of 0 in Berlin will result an absolute time of 1 in the night on the first of January in 1970).") );
	pInfoPlotControlsGridSizer->Add( pSTTimestampAsTime );
	m_pTCTimestampAsTime = new wxTextCtrl(pPanelInfoPlot, wxID_ANY, wxT("00:00:00:000") );
	m_pTCTimestampAsTime->SetToolTip( wxT("This is the device timestamp converted into local time. This value only makes sense for devices that can create a timestamp in us since 01.01.1970 GMT(thus a timestamp of 0 in Berlin will result an absolute time of 1 in the night on the first of January in 1970).") );
	m_pTCTimestampAsTime->Enable( false );
	pInfoPlotControlsGridSizer->Add( m_pTCTimestampAsTime );

	pInfoPlotControlsSizer->Add( pInfoPlotControlsGridSizer );
	pInfoPlotPanelSizer->Add( pInfoPlotControlsSizer, wxSizerFlags().Left() );
	m_pInfoPlotArea = new InfoPlotCanvas( pPanelInfoPlot, wxID_ANY, wxDefaultPosition, wxDefaultSize );
	for( unsigned int i=0; i<InfoPlotCanvas::psLAST; i++ )
	{
		int item = m_pInfoPlotSelectionCombo->Append( m_pInfoPlotArea->GetPlotSelectionName( static_cast<InfoPlotCanvas::TPlotSelection>(i) ) );
		m_pInfoPlotSelectionCombo->SetClientData( item, reinterpret_cast<void*>(i) );
	}
	pInfoPlotPanelSizer->Add( m_pInfoPlotArea, wxSizerFlags(1).Expand() );
	pPanelInfoPlot->SetSizer( pInfoPlotPanelSizer );
	m_pLowerRightWindow->AddPage( pPanelInfoPlot, wxT("Info plot"), false );

	// configure splitters
	m_pHorizontalSplitter->SetMinimumPaneSize( 175 );
	m_pHorizontalSplitter->SetSashGravity( 0.9 );
	m_pVerticalSplitter->SetMinimumPaneSize( 50 );
	pTopDownSizer->Add( m_pVerticalSplitter, wxSizerFlags(6).Expand() );

	m_pStatusBar = new wxStatusBar(m_pPanel, widStatusBar);
	pTopDownSizer->Add( m_pStatusBar, wxSizerFlags().Expand() );
	m_pPanel->SetSizer( pTopDownSizer );
	pTopDownSizer->SetSizeHints( this );

	// restore previous state
	FramePositionStorage frameStorage(this, wxString(wxT("MainFrame")));
	wxRect defaultRect(0, 0, 1024, 700);
	wxRect rect = frameStorage.restore( defaultRect );
	wxConfigBase *pConfig = wxConfigBase::Get();
	m_VerticalSplitterPos = pConfig->Read( wxT("/MainFrame/verticalSplitter"), -1l );
	m_HorizontalSplitterPos = pConfig->Read( wxT("/MainFrame/horizontalSplitter"), -1l );

	for( unsigned int i=0; i<displayCount; i++ )
	{
		wxString displayToken(wxString::Format( wxT("/MainFrame/Settings/Display/%d/"), i ));
		m_pDisplayAreas[i]->SetScaling( pConfig->Read( displayToken + wxString(wxT("FitToScreen")), 0l ) != 0 );
		m_pDisplayAreas[i]->SetPerformanceWarningOutput( pConfig->Read( displayToken + wxString(wxT("ShowPerformanceWarnings")), 0l ) != 0 );
		m_pDisplayAreas[i]->SetInfoOverlayMode( pConfig->Read( displayToken + wxString(wxT("ShowRequestInfos")), 0l ) != 0 );
	}
	bool boMonitorDisplayActive = pConfig->Read( wxT("/MainFrame/Settings/monitorDisplay"), 0l ) != 0;
	m_pMISettings_Display_ShowMonitorImage->Check( boMonitorDisplayActive );
	m_pToolBar->ToggleTool( miSettings_Display_ShowMonitorImage, boMonitorDisplayActive );
	bool boLowerRightControlsActive = pConfig->Read( wxT("/MainFrame/Settings/displayLogWindow"), 0l ) != 0;
	bool boDisplayActive = pConfig->Read( wxT("/MainFrame/Settings/displayActive"), 1l ) != 0;
	// either the display or the controls MUST be active!
	m_pMISettings_Analysis_ShowControls->Check( boLowerRightControlsActive );
	m_pToolBar->ToggleTool( miSettings_Analysis_ShowControls, boLowerRightControlsActive );
	m_pMISettings_Display_Active->Check( boDisplayActive );
	m_pToolBar->ToggleTool( miSettings_Display_Active, boDisplayActive );
	const DisplayWindowContainer::size_type displayCnt = m_pDisplayAreas.size();
	for( DisplayWindowContainer::size_type i=0; i<displayCnt; i++ )
	{
		m_pDisplayAreas[i]->SetActive( boDisplayActive );
	}
	SetupDisplayLogSplitter( true ); // needed as otherwise the initial view might not be correct when display and propgrid are switched off!!!
	SetupDisplayLogSplitter();
	bool boActive = pConfig->Read( wxT("/MainFrame/Settings/displayIncompleteFrames"), 0l ) != 0;
	m_pMISettings_Display_ShowIncompleteFrames->Check( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/silentRecording"), 0l ) != 0;
	m_pMICapture_Recording_SlientMode->Check( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/continuousRecording"), 0l ) != 0;
	m_pMICapture_Recording_Continuous->Check( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/activeDevicesOnly"), 0l ) != 0;
	m_pMISettings_ShowConnectedOnly->Check( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/synchroniseAOIs"), 0l ) != 0;
	m_pMISettings_Analysis_SynchroniseAOIs->Check( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/displayPropGrid"), 1l ) != 0;
	m_pMISettings_PropGrid_Show->Check( boActive );
	m_pToolBar->ToggleTool( miSettings_PropGrid_Show, boActive );
	SetupVerSplitter( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/showToolBar"), 1l ) != 0;
	m_pMISettings_ShowToolBar->Check( boActive );
	ConfigureToolBar( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/showStatusBar"), 1l ) != 0;
	m_pMISettings_ShowStatusBar->Check( boActive );
	ConfigureStatusBar( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/displayPropsWithHexIndices"), 0l ) != 0;
	m_pMISettings_PropGrid_DisplayPropIndicesAsHex->Check( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/useDisplayNameIfAvailable"), 1l ) != 0;
	m_pMISettings_PropGrid_UseDisplayNameIfAvailable->Check( boActive );
	boActive = pConfig->Read( wxT("/MainFrame/Settings/useSelectorGrouping"), 1l ) != 0;
	m_pMISettings_PropGrid_UseSelectorGrouping->Check( boActive );
	int selectedPage = pConfig->Read( wxT("/MainFrame/selectedPage"), -1l );
	if( selectedPage != -1 )
	{
		m_pLowerRightWindow->SetSelection( selectedPage );
		m_CurrentImageAnalysisControlIndex = GetAnalysisControlIndex();
		if( m_CurrentImageAnalysisControlIndex >= 0 )
		{
			m_pCurrentAnalysisDisplay->SetActiveAnalysisPlot( m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas );
			m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->SetActive( true );
		}
	}

	// previous view mode
	m_ViewMode = static_cast<DevicePropertyHandler::TViewMode>(pConfig->Read( wxT("/MainFrame/Settings/propGridViewMode"), DevicePropertyHandler::vmStandard ));
	if( m_ViewMode >= DevicePropertyHandler::vmLAST )
	{
		m_ViewMode = DevicePropertyHandler::vmStandard; // for backwards compatibility
	}
	m_defaultDeviceInterfaceLayout = static_cast<TDeviceInterfaceLayout>(pConfig->Read( wxT("/MainFrame/Settings/defaultDeviceInterfaceLayout"), dilGenICam ));

	int selectedConfigurationMethod = pConfig->Read( wxT("/MainFrame/selectedConfigurationMethod"), 0l );
	m_pNBConfigurationMethod->SetSelection( selectedConfigurationMethod );

	if( GlobalDataStorage::Instance()->IsComponentVisibilitySupported() )
	{
		wxString userExperience( pConfig->Read( wxT("/MainFrame/Settings/UserExperience"), wxString(ConvertedString(Component::visibilityAsString( cvBeginner ))) ) );
		m_pUserExperienceCombo->SetValue( userExperience );
		UpdateUserExperience( userExperience );
	}

	// property grid
	pConfig->Read( wxT("/PropGrid/splitterRatio"), &splitterratio, 0.5 );

	for( unsigned int i=0; i<iapLAST; i++ )
	{
		m_ImageAnalysisPlots[i].Load( pConfig );
	}

	// info plot
	bool boInfoPlotActive = pConfig->Read( wxT("/Controls/InfoPlot/Enable"), 0l ) != 0;
	m_pCBEnableInfoPlot->SetValue( boInfoPlotActive );
	m_pInfoPlotArea->SetActive( boInfoPlotActive );
	m_pSCInfoPlotHistoryDepth->SetValue( pConfig->Read( wxT("/Controls/InfoPlot/HistoryDepth"), 20l ) );
	m_pSCInfoPlotUpdateSpeed->SetValue( pConfig->Read( wxT("/Controls/InfoPlot/UpdateSpeed"), 3l ) );
	m_pInfoPlotSelectionCombo->Select( pConfig->Read( wxT("/Controls/InfoPlot/PlotSelection"), 0l ) );
	InfoPlotCanvas::TPlotSelection plotSelection = static_cast<InfoPlotCanvas::TPlotSelection>(wxPtrToUInt( m_pInfoPlotSelectionCombo->GetClientData( m_pInfoPlotSelectionCombo->GetSelection() ) ));
	m_pInfoPlotArea->SetPlotSelection( plotSelection );

	m_pLogWindow->GetStyle( m_pLogWindow->GetLastPosition(), m_boldTextStyle );
	wxFont boldFont(m_boldTextStyle.GetFont());
	boldFont.SetWeight( wxFONTWEIGHT_BOLD );
	boldFont.SetPointSize( 10 );
	boldFont.SetUnderlined( true );
	m_boldTextStyle.SetFont( boldFont );
	wxTextAttr style(*wxBLUE);
	WriteLogMessage( wxT("Available command line options:\n" ), m_boldTextStyle );
	WriteLogMessage( wxT("'width'         or 'w'   defines the startup width of the application\n") );
	WriteLogMessage( wxT("'height'        or 'h'   defines the startup height of the application\n") );
	WriteLogMessage( wxT("'xpos'          or 'x'   defines the startup x position of the application\n") );
	WriteLogMessage( wxT("'ypos'          or 'y'   defines the startup y position of the application\n") );
	WriteLogMessage( wxT("'splitterratio'          defines the startup ratio of the position of the property grids splitter\n") );
	WriteLogMessage( wxT("'propgridwidth' or 'pgw' defines the startup width of the property grid\n") );
	WriteLogMessage( wxT("'debuginfo'     or 'di'  to display debug information in the property grid\n") );
	WriteLogMessage( wxT("'dic'                    to display invisible(currently shadowed) components in the property grid\n") );
	WriteLogMessage( wxT("'displayCountX' or 'dcx' defines the number of image displays in horizontal direction\n") );
	WriteLogMessage( wxT("'displayCountY' or 'dcy' defines the number of image displays in vertical direction\n") );
	WriteLogMessage( wxT("'fulltree'      or 'ft'  to display the complete property tree(including the data not meant to be accessed by the user\n") );
	WriteLogMessage( wxT("'device'        or 'd'   to directly open a device with a particular serial number\n") );
	WriteLogMessage( wxT("'live'                   to start live acquisition from the device openen via 'device' or 'd' directly\n") );
	WriteLogMessage( wxT("'showEvents'    or 'se'  to display occuring events in the log output window (this will cause additional CPU load)\n") );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("Usage example: '<app name> di=1 h=340'\n") );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxString::Format( wxT("processed command line parameters: %s\n"), ( processedParameters.length() > 0 ) ? processedParameters.c_str() : wxT("none") ), m_boldTextStyle );
	WriteLogMessage( wxT("\n") );
	if( !parserErrors.IsEmpty() )
	{
		WriteErrorMessage( parserErrors );
		WriteLogMessage( wxT("\n") );
	}
	WriteLogMessage( wxT("Using the property grid:\n"), m_boldTextStyle );
	WriteLogMessage( wxT("Right-click on a method object to execute it.\n"), style );
	WriteLogMessage( wxT("Parameters must be separated by whitespaces, empty strings can be passed as a single underscore.\n"), style );
	WriteLogMessage( wxT("To find out what kind of parameters a function expects please have a look in the manuals interface reference.\n"), style );
	WriteLogMessage( wxT("Right-click on a list or property to restore its default.\n"), style );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("Using the display:\n"), m_boldTextStyle );
	WriteLogMessage( wxT("Left-click onto a display area to select it for configuration and to assign this display to the analysis plots and the monitor display.\n"), style );
	WriteLogMessage( wxT("Press '+' or '-' or use the mouse wheel for zooming in and out of the image for the selected display(this will only be active when the 'fit to screen mode is switched off).\n"), style );
	WriteLogMessage( wxT("Left-click into the AOI for the selected analysis page to drag it to a new location.\n"), style );
	WriteLogMessage( wxT("Double-left-click on any of the image displays to toggle full screen display mode.\n"), style );
	WriteLogMessage( wxT("Right-click onto a display to get a pop up menu with additional options.\n"), style );
	WriteLogMessage( wxT("Right-click onto a display and drag the mouse to select a new AOI for the selected analysis page.\n"), style );
	WriteLogMessage( wxT("Drop any supported image file type onto the display area to open that file for analysis in the selected display area.\n"), style );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("Using the analysis plots:\n"), m_boldTextStyle );
	WriteLogMessage( wxT("Right-click in one of the cells of the numerical display of any of the analysis plot for a menu of additional options.\n"), style );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("Pixel histogram:\n"), style );
	WriteLogMessage( wxT("Read: Channel (Mean value, most frequent value count / most frequent value)\n"), style );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("Noise histogram:\n"), style );
	WriteLogMessage( wxT("Read: Channel#Direction (Mean difference, most frequent value count/  value, Standard deviation)\n"), style );
	WriteLogMessage( wxT("EXAMPLE: For a single channel(Mono) image the output of 'C0Hor(3.43, 5086/  0, 9.25), C0Ver(3.26, 4840/  0, 7.30) will "), style );
	WriteLogMessage( wxT("indicate that the mean difference between pixels in horizontal direction is 3.43, the most frequent difference is 0 and this difference is present 5086 times "), style );
	WriteLogMessage( wxT("in the current AOI. The standard deviation in horizontal direction is 9.25. The C0Ver value list contains the same data but in vertical direction.\n"), style );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("Using multiple settings/displays:\n"), m_boldTextStyle );
	WriteLogMessage( wxT("This application is capable of dealing with multiple capture settings for a single device and in addition to that it can be configured to deal with "), style );
	WriteLogMessage( wxT("multiple image displays. For frame grabbers with multiple input channels this e.g. can be used to display live images from all input channels "), style );
	WriteLogMessage( wxT("simultaneously. This even works if each input channel is connected to a different video signal in terms of resolution and timing.\n"), style );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("The amount of image displays can be configured via the command line parameters 'dcx' and 'dcy'(see above) and can't be changed at runtime.\n"), style );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("Additional capture settings can be created via 'Capture -> Capture Settings -> Create Capture Settings' and the property grid will display these "), style );
	WriteLogMessage( wxT("capture settings either in 'Developers' or in 'Multiple Settings' view. A step by step guide for an example setup can be found in the GUI section "), style );
	WriteLogMessage( wxT("of the device manual.\n"), style );
	WriteLogMessage( wxT("\n") );
	WriteLogMessage( wxT("Please note that in 'Generic' or 'GenICam' interface layout multiple capture settings are NOT supported.\n"), style );
	WriteLogMessage( wxT("\n") );

#ifdef BUILD_WITH_PLUGIN_SUPPORT
	WriteLogMessage( wxString::Format( wxT("Deteced plugins: %d.\n"), m_pluginManager.getCount() ), style );
#endif // #ifdef BUILD_WITH_PLUGIN_SUPPORT

	m_pDevPropHandler = new DevicePropertyHandler( GetPropertyGrid(), boDisplayDebugInfo, boDisplayFullTree, boDisplayInvisibleComponents, boShowEvents );
	switch( m_ViewMode )
	{
	case DevicePropertyHandler::vmDeveloper:
		m_pMISettings_PropGrid_DevelopersView->Check();
		break;
	default:
		m_pMISettings_PropGrid_StandardView->Check();
		break;
	}
	UpdatePropGridViewMode();

	switch( m_defaultDeviceInterfaceLayout )
	{
	case dilGeneric:
		m_pMISettings_DefaultDeviceInterface_Generic->Check();
		break;
	case dilGenICam:
		m_pMISettings_DefaultDeviceInterface_GenICam->Check();
		break;
	default:
		m_pMISettings_DefaultDeviceInterface_DeviceSpecific->Check();
		break;
	}

	m_pMonitorImage->GetDisplayArea()->SetActive( m_pMISettings_Display_ShowMonitorImage->IsChecked() );
	m_pMonitorImage->Show( m_pMISettings_Display_ShowMonitorImage->IsChecked() && m_pCurrentAnalysisDisplay->IsActive() );
	m_pDisplayAreas[0]->RegisterMonitorDisplay( m_pMISettings_Display_ShowMonitorImage->IsChecked() ? m_pMonitorImage->GetDisplayArea() : 0 );

	SetSizeHints( 720, 400 );
	if( cmdLineRect.width != -1 )
	{
		rect.width = cmdLineRect.width;
	}
	if( cmdLineRect.height != -1 )
	{
		rect.height = cmdLineRect.height;
	}
	if( cmdLineRect.x != -1 )
	{
		rect.x = cmdLineRect.x;
	}
	if( cmdLineRect.y != -1 )
	{
		rect.y = cmdLineRect.y;
	}
	SetSize( rect );

	m_pHorizontalSplitter->SetSashPosition( ( m_HorizontalSplitterPos != -1 ) ? m_HorizontalSplitterPos : 3*rect.height/4, true );
	m_pVerticalSplitter->SetSashPosition( ( m_VerticalSplitterPos != -1 ) ? m_VerticalSplitterPos : rect.width/3, true );

	SetupDlgControls();
	UpdateTitle();

	if( ( splitterratio <= 0 ) || ( splitterratio >= 1 ) )
	{
		splitterratio = 0.5;
	}
	GetPropertyGrid()->SetSplitterRatio( splitterratio );
	UpdatePropGridSplitter();
	wxToolTip::Enable( true );

	StartPropertyGridUpdateTimer( 750 );

	if( serialToOpen.length() > 0 )
	{
		int selection = GetDesiredDeviceIndex( serialToOpen );
		if( selection != wxNOT_FOUND )
		{
			m_pDevCombo->Select( selection );
			UpdateDeviceFromComboBox();
			ToggleCurrentDevice();
			if( boOpenDeviceInLiveMode )
			{
				ConfigureLive();
			}
		}
		else
		{
			wxString msg(wxT("\nCan't directly open device "));
			msg.Append(ConvertedString(serialToOpen));
			msg.Append( wxT(" as it doesn't seem to be present or the serial number is incorrect\n"));
			WriteErrorMessage( msg );
		}
	}
	else
	{
		SetCurrentImage( wxFileName(fileToOpen), m_pCurrentAnalysisDisplay );
	}

	if( !GlobalDataStorage::Instance()->IsComponentVisibilitySupported() )
	{
		WriteErrorMessage( wxT("WARNING: This version of wxPropView tries to make use of a user access level feature that currently doesn't seem to be supported by the underlying framework! Please update all your device drivers.\n") );
	}
}

//-----------------------------------------------------------------------------
PropViewFrame::~PropViewFrame()
//-----------------------------------------------------------------------------
{
	Deinit();

	// store the current state of the application
	// main frame
	FramePositionStorage frameStorage(this, wxString(wxT("MainFrame")));
	frameStorage.store();
	wxConfigBase *pConfig = wxConfigBase::Get();
	pConfig->Write( wxT("/MainFrame/verticalSplitter"), ( m_pVerticalSplitter->IsSplit() ) ? m_pVerticalSplitter->GetSashPosition() : m_VerticalSplitterPos );
	pConfig->Write( wxT("/MainFrame/horizontalSplitter"), ( m_pHorizontalSplitter->IsSplit() ) ? m_pHorizontalSplitter->GetSashPosition() : m_HorizontalSplitterPos );
	pConfig->Write( wxT("/MainFrame/selectedPage"), m_pLowerRightWindow->GetSelection() );
	pConfig->Write( wxT("/MainFrame/selectedConfigurationMethod"), m_pNBConfigurationMethod->GetSelection() );

	const DisplayWindowContainer::size_type displayCount = m_pDisplayAreas.size();
	for( DisplayWindowContainer::size_type i=0; i<displayCount; i++ )
	{
		wxString displayToken(wxString::Format( wxT("/MainFrame/Settings/Display/%d/"), i ));
		pConfig->Write( displayToken + wxString(wxT("FitToScreen")), m_pDisplayAreas[i]->IsScaled() );
		pConfig->Write( displayToken + wxString(wxT("ShowPerformanceWarnings")), m_pDisplayAreas[i]->GetPerformanceWarningOutput() );
		pConfig->Write( displayToken + wxString(wxT("ShowRequestInfos")), m_pDisplayAreas[i]->InfoOverlayActive() );
	}

	pConfig->Write( wxT("/MainFrame/Settings/monitorDisplay"), m_pMISettings_Display_ShowMonitorImage->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/displayActive"), m_pMISettings_Display_Active->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/displayIncompleteFrames"), m_pMISettings_Display_ShowIncompleteFrames->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/silentRecording"), m_pMICapture_Recording_SlientMode->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/continuousRecording"), m_pMICapture_Recording_Continuous->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/activeDevicesOnly"), m_pMISettings_ShowConnectedOnly->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/displayLogWindow"), m_pMISettings_Analysis_ShowControls->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/synchroniseAOIs"), m_pMISettings_Analysis_SynchroniseAOIs->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/displayPropGrid"), m_pMISettings_PropGrid_Show->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/showToolBar"), m_pMISettings_ShowToolBar->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/showStatusBar"), m_pMISettings_ShowStatusBar->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/displayPropsWithHexIndices"), m_pMISettings_PropGrid_DisplayPropIndicesAsHex->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/useDisplayNameIfAvailable"), m_pMISettings_PropGrid_UseDisplayNameIfAvailable->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/useSelectorGrouping"), m_pMISettings_PropGrid_UseSelectorGrouping->IsChecked() );
	pConfig->Write( wxT("/MainFrame/Settings/propGridViewMode"), int(m_ViewMode) );
	pConfig->Write( wxT("/MainFrame/Settings/defaultDeviceInterfaceLayout"), int(m_defaultDeviceInterfaceLayout) );
	if( m_pUserExperienceCombo )
	{
		pConfig->Write( wxT("/MainFrame/Settings/UserExperience"), m_pUserExperienceCombo->GetValue() );
	}

	// property grid
	pConfig->Write( wxT("/PropGrid/splitterRatio"), GetPropertyGrid()->GetSplitterRatio() );

	for( unsigned int i=0; i<iapLAST; i++ )
	{
		m_ImageAnalysisPlots[i].Save( pConfig );
	}

	// info plot
	pConfig->Write( wxT("/Controls/InfoPlot/Enable"), m_pCBEnableInfoPlot->GetValue() );
	pConfig->Write( wxT("/Controls/InfoPlot/HistoryDepth"), m_pSCInfoPlotHistoryDepth->GetValue() );
	pConfig->Write( wxT("/Controls/InfoPlot/UpdateSpeed"), m_pSCInfoPlotUpdateSpeed->GetValue() );
	pConfig->Write( wxT("/Controls/InfoPlot/PlotSelection"), m_pInfoPlotSelectionCombo->GetSelection() );

	delete GlobalDataStorage::Instance();
}

//-----------------------------------------------------------------------------
void PropViewFrame::Abort( void )
//-----------------------------------------------------------------------------
{
	FunctionInterface* p = 0;
	m_pDevPropHandler->GetActiveDevice( &p );
	if( p )
	{
		int result = p->imageRequestReset( 0, 0 );
		if( result != DMR_NO_ERROR )
		{
			WriteErrorMessage( wxString::Format( wxT("FunctionInterface::imageRequestReset( 0, 0 ) returned an error: %s.\n"), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ) );
		}
	}
}

//-----------------------------------------------------------------------------
template<typename _Ty>
void PropViewFrame::AppendYUV444DataPixelInfo( wxPoint pixel, wxString& pixelInfo, const ImageBuffer* pIB, const int order[3] ) const
//-----------------------------------------------------------------------------
{
	_Ty* p = reinterpret_cast<_Ty*>(reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch ) + ( pixel.x * pIB->iBytesPerPixel ));
	pixelInfo.append( wxString::Format( wxT("%d(Y), %d(U), %d(V)"), p[order[0]], p[order[1]], p[order[2]] ) );
}

//-----------------------------------------------------------------------------
template<typename _Ty>
void PropViewFrame::AppendYUVDataPixelInfo( wxPoint pixel, wxString& pixelInfo, const ImageBuffer* pIB ) const
//-----------------------------------------------------------------------------
{
	_Ty* p = reinterpret_cast<_Ty*>(reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch ) + ( pixel.x * pIB->iBytesPerPixel ));
	if( ( pixel.x & 1 ) || ( pixel.x == pIB->iWidth - 1 ) )
	{
		pixelInfo.append( wxString::Format( wxT("%d(Y), %d(U), %d(V)"), p[0], p[-1], p[1] ) );
	}
	else
	{
		pixelInfo.append( wxString::Format( wxT("%d(Y), %d(U), %d(V)"), p[0], p[1], p[3] ) );
	}
}

//-----------------------------------------------------------------------------
template<typename _Ty>
void PropViewFrame::AppendUYVDataPixelInfo( wxPoint pixel, wxString& pixelInfo, const ImageBuffer* pIB ) const
//-----------------------------------------------------------------------------
{
	_Ty* p = reinterpret_cast<_Ty*>(reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch ) + ( pixel.x * pIB->iBytesPerPixel ));
	if( ( pixel.x & 1 ) || ( pixel.x == pIB->iWidth - 1 ) )
	{
		pixelInfo.append( wxString::Format( wxT("%d(Y), %d(U), %d(V)"), p[1], p[0], p[-2] ) );
	}
	else
	{
		pixelInfo.append( wxString::Format( wxT("%d(Y), %d(U), %d(V)"), p[1], p[0], p[2] ) );
	}
}

//-----------------------------------------------------------------------------
mvIMPACT::acquire::TBayerMosaicParity PropViewFrame::BayerParityFromString( const wxString& value )
//-----------------------------------------------------------------------------
{
	if( value == wxT("Red-green") )
	{
		return bmpRG;
	}
	else if( value == wxT("Green-red") )
	{
		return bmpGR;
	}
	else if( value == wxT("Blue-green") )
	{
		return bmpBG;
	}
	else if( value == wxT("Green-blue") )
	{
		return bmpGB;
	}
	else if( value == wxT("Undefined") )
	{
		return bmpUndefined;
	}

	WriteErrorMessage( wxString::Format( wxT("Unsupported bayer parity(%s).\n"), value.c_str() ) );
	return bmpUndefined;
}

//-----------------------------------------------------------------------------
void PropViewFrame::ConfigureAnalysisPlot( const wxRect* pAOI /* = 0 */ )
//-----------------------------------------------------------------------------
{
	if( m_CurrentImageAnalysisControlIndex >= 0 )
	{
		if( m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->GetImageCanvas() != m_pCurrentAnalysisDisplay )
		{
			m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->RegisterImageCanvas( m_pCurrentAnalysisDisplay );
		}
		m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->SetActive( true );
		m_pCurrentAnalysisDisplay->SetActiveAnalysisPlot( m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas );
		ConfigureAOIControlLimits( m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex] );
		if( pAOI )
		{
			ConfigureAOI( m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex], *pAOI );
		}

		m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex],
			m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIx->GetValue(),
			m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIy->GetValue(),
			m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIw->GetValue(),
			m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIh->GetValue(),
			true );
	}
	else
	{
		m_pCurrentAnalysisDisplay->SetActiveAnalysisPlot( 0 );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::ConfigureAOI( ImageAnalysisPlotControls& controls, const wxRect& rect )
//-----------------------------------------------------------------------------
{
	m_boUpdateAOIInProgress = true;
	controls.m_pSCAOIx->SetValue( rect.GetLeft() );
	controls.m_pSCAOIy->SetValue( rect.GetTop() );
	controls.m_pSCAOIw->SetValue( rect.GetWidth() );
	controls.m_pSCAOIh->SetValue( rect.GetHeight() );
	m_boUpdateAOIInProgress = false;
}

//-----------------------------------------------------------------------------
void PropViewFrame::ConfigureAOIControlLimits( ImageAnalysisPlotControls& controls )
//-----------------------------------------------------------------------------
{
	const ImageBuffer* p = m_pCurrentAnalysisDisplay->GetImage();
	if( p && p->vpData )
	{
		m_boUpdateAOIInProgress = true;
		if( ( p->iHeight > 0 ) && ( p->iHeight != controls.m_pSCAOIh->GetMax() ) )
		{
			controls.m_pSCAOIh->SetRange( 1, p->iHeight );
			controls.m_pSCAOIy->SetRange( 0, p->iHeight - 1 );
			// otherwise the limits are correct, but the displayed value might be incorrect
			controls.m_pSCAOIh->SetValue( controls.m_pSCAOIh->GetValue() );
			controls.m_pSCAOIy->SetValue( controls.m_pSCAOIy->GetValue() );
		}
		if( ( p->iWidth > 0 ) && ( p->iWidth != controls.m_pSCAOIw->GetMax() ) )
		{
			controls.m_pSCAOIw->SetRange( 1, p->iWidth );
			controls.m_pSCAOIx->SetRange( 0, p->iWidth - 1 );
			// otherwise the limits are correct, but the displayed value might be incorrect
			controls.m_pSCAOIw->SetValue( controls.m_pSCAOIw->GetValue() );
			controls.m_pSCAOIx->SetValue( controls.m_pSCAOIx->GetValue() );
		}
		m_boUpdateAOIInProgress = false;
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::ConfigureLive( void )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );

	if( pThread )
	{
		if( !pThread->GetLiveMode() )
		{
			SetupUpdateFrequencies( true );
			pThread->SetContinuousRecording( m_pMICapture_Recording_Continuous->IsChecked() );
			pThread->SetLiveMode( true, !m_pMICapture_Recording_SlientMode->IsChecked() );
		}
		else
		{
			pThread->SetLiveMode( false );
		}
		SetupDlgControls();
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::ConfigureSplitter( wxSplitterWindow* pSplitter, wxWindow* pWindowToRemove, wxWindow* pWindowToShow )
//-----------------------------------------------------------------------------
{
	if( pSplitter )
	{
		if( pSplitter->IsSplit() )
		{
			pSplitter->Unsplit( pWindowToRemove );
		}
		else if( pSplitter->GetWindow1() != pWindowToShow )
		{
			if( pSplitter->GetWindow1() == pWindowToRemove )
			{
				// switch current window. Therefore we first need to split the window again and then
				// the 'old' window can be removed
				pSplitter->SplitHorizontally( pWindowToShow, pWindowToRemove, 0 );
				pSplitter->Unsplit( pWindowToRemove );
			}
			else
			{
				pSplitter->Initialize( pWindowToShow );
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::ConfigureStatusBar( bool boShow )
//-----------------------------------------------------------------------------
{
	if( boShow )
	{
		m_pPanel->GetSizer()->Show( m_pStatusBar );
	}
	else
	{
		m_pPanel->GetSizer()->Hide( m_pStatusBar );
	}
	m_pPanel->GetSizer()->Layout();
}

//-----------------------------------------------------------------------------
void PropViewFrame::ConfigureToolBar( bool boShow )
//-----------------------------------------------------------------------------
{
	if( boShow )
	{
		m_pToolBar->Show();
	}
	else
	{
		m_pToolBar->Hide();
	}
	SendSizeEvent();
}

//-----------------------------------------------------------------------------
wxScrolledWindow* PropViewFrame::CreateImageAnalysisPlotControls( wxWindow* pParent, int windowIDOffset )
//-----------------------------------------------------------------------------
{
	int index = GetAnalysisControlIndex( windowIDOffset );
	wxScrolledWindow* pPanel = new wxScrolledWindow(pParent);
	pPanel->SetScrollRate( 10, 10 );
	wxBoxSizer* pSizer = new wxBoxSizer(wxHORIZONTAL);
	wxBoxSizer* pControlsSizer = new wxBoxSizer(wxVERTICAL);
	m_ImageAnalysisPlots[index].m_pNBDisplayMethod = new wxNotebook(pPanel, windowIDOffset + iapidNBDisplayMethod, wxDefaultPosition, wxDefaultSize);
	switch( windowIDOffset )
	{
	case widPixelHistogram:
		RegisterAnalysisPlot<PixelHistogramCanvas>( index, widPixelHistogram, widPixelHistogram | iapidGrid, wxColour(128, 0, 255) );
		break;
	case widNoiseHistogram:
		RegisterAnalysisPlot<NoiseHistogramCanvas>( index, widNoiseHistogram, widNoiseHistogram | iapidGrid, wxColour(255, 0, 128) );
		break;
	case widLineProfile:
		RegisterAnalysisPlot<LineProfileCanvas>( index, widLineProfile, widLineProfile | iapidGrid, *wxBLUE );
		break;
	case widIntensityPlot:
		RegisterAnalysisPlot<IntensityPlotCanvas>( index, widIntensityPlot, widIntensityPlot | iapidGrid, *wxBLUE );
		break;
	case widVectorScope:
		RegisterAnalysisPlot<VectorScopeCanvas>( index, widVectorScope, widVectorScope | iapidGrid, wxColour(0, 128, 255) );
		break;
	default:
		wxASSERT( false && "Invalid window ID offset for this function" );
		return 0;
	}
	m_ImageAnalysisPlots[index].m_pNBDisplayMethod->InsertPage( 0, m_ImageAnalysisPlots[index].m_pPlotCanvas, wxT("Graphical"), true );
	m_ImageAnalysisPlots[index].m_pCBAOIFullMode = new wxCheckBox(pPanel, windowIDOffset + iapidCBAOIFullMode, wxT("Full AOI mode"));
	pControlsSizer->Add( m_ImageAnalysisPlots[index].m_pCBAOIFullMode, wxSizerFlags().Left() );
	pControlsSizer->AddSpacer( 5 );

	if( m_ImageAnalysisPlots[index].m_pPlotCanvas->HasFeature( ImageAnalysisPlotCanvas::pfProcessBayerParity ) )
	{
		m_ImageAnalysisPlots[index].m_pCBProcessBayerParity = new wxCheckBox(pPanel, windowIDOffset + iapidCBProcessBayerParity, wxT("Process Bayer Parity"));
		m_ImageAnalysisPlots[index].m_pCBProcessBayerParity->SetToolTip( wxT("When enabled, Bayer raw images will be treated as 4 channel images") );
		pControlsSizer->Add( m_ImageAnalysisPlots[index].m_pCBProcessBayerParity, wxSizerFlags().Left() );
		pControlsSizer->AddSpacer( 5 );
	}

	wxFlexGridSizer* pGridSizer = new wxFlexGridSizer(2, 0);
	pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("AOI x-offset:")) );
	m_ImageAnalysisPlots[index].m_pSCAOIx = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCAOIx, wxT("0"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 639, 0);
	pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCAOIx, wxSizerFlags().Left() );
	pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("AOI y-offset:")) );
	m_ImageAnalysisPlots[index].m_pSCAOIy = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCAOIy, wxT("0"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 479, 0);
	pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCAOIy, wxSizerFlags().Left() );
	pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("AOI width:")) );
	m_ImageAnalysisPlots[index].m_pSCAOIw = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCAOIw, wxT("640"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 640, 640);
	pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCAOIw, wxSizerFlags().Left() );
	pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("AOI height:")) );
	m_ImageAnalysisPlots[index].m_pSCAOIh = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCAOIh, wxT("480"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 480, 480);
	pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCAOIh, wxSizerFlags().Left() );
	if( m_ImageAnalysisPlots[index].m_pPlotCanvas->HasPlotSelection() )
	{
		pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("Plot selection:")) );
		m_ImageAnalysisPlots[index].m_pCoBPlotSelection = new wxComboBox(pPanel, windowIDOffset + iapidCoBPlotSelection, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN);
		const std::vector<wxString>& v(m_ImageAnalysisPlots[index].m_pPlotCanvas->GetAvailablePlotSelections());
		const std::vector<wxString>::size_type cnt = v.size();
		for( std::vector<wxString>::size_type i=0; i<cnt; i++ )
		{
			int item = m_ImageAnalysisPlots[index].m_pCoBPlotSelection->Append( v[i] );
			m_ImageAnalysisPlots[index].m_pCoBPlotSelection->SetClientData( item, reinterpret_cast<void*>(i) );
		}
		m_ImageAnalysisPlots[index].m_pCoBPlotSelection->Select( 0 );
		pGridSizer->Add( m_ImageAnalysisPlots[index].m_pCoBPlotSelection, wxSizerFlags().Left() );
	}
	if( m_ImageAnalysisPlots[index].m_pPlotCanvas->HasFeature( ImageAnalysisPlotCanvas::pfHistoryDepth ) )
	{
		pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("History depth:")) );
		m_ImageAnalysisPlots[index].m_pSCHistoryDepth = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCHistoryDepth, wxT("0"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 5, 10000, 20);
		pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCHistoryDepth, wxSizerFlags().Left() );
	}
	if( m_ImageAnalysisPlots[index].m_pPlotCanvas->HasFeature( ImageAnalysisPlotCanvas::pfPercentageWindow ) )
	{
		pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("Draw start(%):")) );
		m_ImageAnalysisPlots[index].m_pSCDrawStart_percent = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCDrawStart_percent, wxT("0"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 99, 0);
		pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCDrawStart_percent, wxSizerFlags().Left() );
		pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("Draw window(%):")) );
		m_ImageAnalysisPlots[index].m_pSCDrawWindow_percent = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCDrawWindow_percent, wxT("100"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 100, 100);
		pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCDrawWindow_percent, wxSizerFlags().Left() );
	}
	if( m_ImageAnalysisPlots[index].m_pPlotCanvas->HasFeature( ImageAnalysisPlotCanvas::pfStepWidth ) )
	{
		pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("Draw step width:")) );
		m_ImageAnalysisPlots[index].m_pSCDrawStepWidth = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCDrawStepWidth, wxT("0"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, HistogramCanvas::GetDrawStepWidthMax(), 0);
		pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCDrawStepWidth, wxSizerFlags().Left() );
	}
	if( m_ImageAnalysisPlots[index].m_pPlotCanvas->HasFeature( ImageAnalysisPlotCanvas::pfGridSteps ) )
	{
		pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("Grid steps X:")) );
		m_ImageAnalysisPlots[index].m_pSCGridStepsX = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCGridStepsX, wxT("1"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 100, 1);
		pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCGridStepsX, wxSizerFlags().Left() );
		pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("Grid steps Y:")) );
		m_ImageAnalysisPlots[index].m_pSCGridStepsY = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCGridStepsY, wxT("1"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 100, 1);
		pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCGridStepsY, wxSizerFlags().Left() );
	}
	pGridSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT("Update interval:")) );
	m_ImageAnalysisPlots[index].m_pSCUpdateSpeed = new wxSpinCtrl(pPanel, windowIDOffset + iapidSCUpdateSpeed, wxT("3"), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, PlotCanvas::ulMin, PlotCanvas::ulMax, 3);
	pGridSizer->Add( m_ImageAnalysisPlots[index].m_pSCUpdateSpeed, wxSizerFlags().Left() );
	pControlsSizer->Add( pGridSizer );
	pSizer->Add( pControlsSizer, wxSizerFlags().Left() );
	m_ImageAnalysisPlots[index].m_pPlotCanvas->RegisterImageCanvas( m_pCurrentAnalysisDisplay );
	m_ImageAnalysisPlots[index].m_pNBDisplayMethod->SetMinSize( wxSize(100, 50) );
	pSizer->Add( m_ImageAnalysisPlots[index].m_pNBDisplayMethod, wxSizerFlags(1).Expand() );
	pPanel->SetSizer( pSizer );
	return pPanel;
}

//-----------------------------------------------------------------------------
void PropViewFrame::Deinit( void )
//-----------------------------------------------------------------------------
{
	StopPropertyGridUpdateTimer();
	m_boShutdownInProgress = true;
	const DisplayWindowContainer::size_type displayCount = m_pDisplayAreas.size();
	for( DisplayWindowContainer::size_type i=0; i<displayCount; i++ )
	{
		m_pDisplayAreas[i]->SetActive( false );
		m_CurrentRequestDataContainer[i] = RequestData();
	}
	delete m_pDevPropHandler;
	m_pDevPropHandler = 0;
}

//-----------------------------------------------------------------------------
ImageAnalysisPlotCanvas* PropViewFrame::DeselectAnalysisPlot( void )
//-----------------------------------------------------------------------------
{
	ImageAnalysisPlotCanvas* pCurrentAnalysisPlot = const_cast<ImageAnalysisPlotCanvas*>(m_pCurrentAnalysisDisplay->GetActiveAnalysisPlot());
	if( pCurrentAnalysisPlot )
	{
		pCurrentAnalysisPlot->SetActive( false );
	}
	return pCurrentAnalysisPlot;
}

//-----------------------------------------------------------------------------
void PropViewFrame::DisplaySettingLoadSaveErrorMessage( const wxString& msgPrefix, int originalErrorCode )
//-----------------------------------------------------------------------------
{
	wxString msg(msgPrefix);
	if( originalErrorCode != DMR_FEATURE_NOT_AVAILABLE )
	{
#if wxCHECK_VERSION(2, 7, 1)
		wxPlatformInfo platformInfo;
		if( ( platformInfo.GetOperatingSystemId() == wxOS_WINDOWS_NT ) &&
			( platformInfo.GetOSMajorVersion() >= 6 ) )
		{
			msg.append( wxString::Format( wxT(" You are running %s version %d.%d. With active UAC you must start wxPropView 'as administrator' even if you are logged on as an administrator in order to load/save settings globally."), platformInfo.GetOperatingSystemIdName().c_str(), platformInfo.GetOSMajorVersion(), platformInfo.GetOSMinorVersion() ) );
		}
#else
		msg.append( wxT(" You may be missing certain rights in order to load/save settings globally.") );
#endif // #if wxCHECK_VERSION(2, 7, 1)
	}
	WriteErrorMessage( wxString::Format( wxT("%s\n"), msg.c_str() ) );
	wxMessageBox( msg, wxT("Failed to load/save setting"), wxOK | wxICON_INFORMATION, this );
}

//-----------------------------------------------------------------------------
void PropViewFrame::EndFullScreenMode( void )
//-----------------------------------------------------------------------------
{
	if( m_boImageCanvasInFullScreenMode )
	{
		const DisplayWindowContainer::size_type displayCnt = m_pDisplayAreas.size();
		for( DisplayWindowContainer::size_type i=0; i<displayCnt; i++ )
		{
			if( m_pDisplayAreas[i]->IsFullScreen() )
			{
				m_pDisplayAreas[i]->SetFullScreenMode( false );
			}
		}
	}
	else if( ( m_pMISettings_ToggleFullScreenMode->IsChecked() ) || IsFullScreen() )
	{
		m_pMISettings_ToggleFullScreenMode->Check( false );
		ShowFullScreen( false );
	}
}

//-----------------------------------------------------------------------------
int PropViewFrame::GetAnalysisControlIndex( void ) const
//-----------------------------------------------------------------------------
{
	wxString selectedPageName = m_pLowerRightWindow->GetPageText( m_pLowerRightWindow->GetSelection() );
	for( int i=0; i<iapLAST; i++ )
	{
		if( m_ImageAnalysisPlots[i].m_pPlotCanvas && ( m_ImageAnalysisPlots[i].m_pPlotCanvas->GetName() == selectedPageName ) )
		{
			return i;
		}
	}
	return -1;
}

//-----------------------------------------------------------------------------
int PropViewFrame::GetAnalysisControlIndex( int windowID ) const
//-----------------------------------------------------------------------------
{
	return ( windowID >> 8 ) - 1;
}

//-----------------------------------------------------------------------------
int PropViewFrame::GetDesiredDeviceIndex( wxString& serial ) const
//-----------------------------------------------------------------------------
{
	const int cnt = m_pDevCombo->GetCount();
	for( int i=0; i<cnt; i++ )
	{
		if( m_pDevCombo->GetString( i ).BeforeFirst( wxT(' ') ) == serial )
		{
			return i;
		}
	}
	return wxNOT_FOUND;
}

//-----------------------------------------------------------------------------
wxString PropViewFrame::GetSelectedDeviceSerial( void ) const
//-----------------------------------------------------------------------------
{
	return m_pDevCombo->GetValue().BeforeLast( wxT('(') ).RemoveLast();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnHelp_About(wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	wxBoxSizer* pTopDownSizer;
	wxDialog dlg(this, wxID_ANY, wxString(wxT("About wxPropView")));
	wxIcon icon(mvIcon_xpm);
	dlg.SetIcon( icon );
	pTopDownSizer = new wxBoxSizer(wxVERTICAL);
	wxStaticText *pText = new wxStaticText(&dlg, wxID_ANY, wxString::Format( wxT("configure tool for %s devices"), COMPANY_NAME ));
	pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5);
	pText = new wxStaticText(&dlg, wxID_ANY, wxString::Format( wxT("(C) 2005 - %s by %s"), CURRENT_YEAR, COMPANY_NAME ));
	pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5);
	pText = new wxStaticText(&dlg, wxID_ANY, wxString::Format( wxT("Version %s"), VERSION_STRING ));
	pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5);
	pText = new wxStaticText(&dlg, wxID_ANY, wxT("Support contact: www.matrix-vision.de") );
	pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5);
	pText = new wxStaticText(&dlg, wxID_ANY, wxString::Format( wxT("This tool has been written using wxWidgets (www.wxwidgets.org) and was compiled with version %d.%d.%d of this library"), wxMAJOR_VERSION, wxMINOR_VERSION, wxRELEASE_NUMBER ));
	pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5);
	pText = new wxStaticText(&dlg, wxID_ANY, wxT("The property grid control is based on code written by Jaakko Salli"));
	pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5);
	pText = new wxStaticText(&dlg, wxID_ANY, wxT("The latest stable version can be obtained from http://wxpropgrid.sourceforge.net/cgi-bin/index"));
	pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5);
	pText = new wxStaticText(&dlg, wxID_ANY, wxString::Format( wxT("The complete source of this application can be obtained by contacting %s"), COMPANY_NAME ));
	pTopDownSizer->Add( pText, 0, wxALL | wxALIGN_CENTER, 5);
	wxButton* pBtnOK = new wxButton(&dlg, wxID_OK, wxT("OK"));
	pBtnOK->SetDefault();
	pTopDownSizer->Add( pBtnOK, 0, wxALL | wxALIGN_RIGHT, 15);
	dlg.SetSizer( pTopDownSizer );
	pTopDownSizer->Fit( &dlg );
	dlg.ShowModal();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnHelp_DriverInformation( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	try
	{
		const DeviceManager& devMgr = m_pDevPropHandler->GetDevMgr();
		ComponentIterator itDrivers(devMgr.getInternalHandle());
		ComponentLocator locator(itDrivers.parent());
		itDrivers = ComponentIterator(locator.findComponent( "Drivers" ));
		DriverInformationDlg dlg(this, wxString(wxT("Current driver information")), itDrivers);
		dlg.ShowModal();
	}
	catch( const ImpactAcquireException& e )
	{
		wxMessageBox( wxString::Format( wxT("Error while trying to build list of drivers and devices: %s(%s)."), ConvertedString(e.getErrorString()).c_str(), ConvertedString(e.getErrorCodeAsString()).c_str() ), wxString(wxT("INTERNAL ERROR")), wxOK | wxICON_INFORMATION, this );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnActivateDisplay( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	const DisplayWindowContainer::size_type displayCount = m_pDisplayAreas.size();
	for( DisplayWindowContainer::size_type i=0; i<displayCount; i++ )
	{
		m_pDisplayAreas[i]->SetActive( e.IsChecked() );
	}
	m_pMISettings_Display_Active->Check( e.IsChecked() );
	bool boShowMonitorDisplay = e.IsChecked() && m_pMISettings_Display_ShowMonitorImage->IsChecked();
	m_pMonitorImage->GetDisplayArea()->SetActive( boShowMonitorDisplay );
	m_pMonitorImage->Show( boShowMonitorDisplay );
	GetToolBar()->ToggleTool( miSettings_Display_Active, e.IsChecked() );
	SetupDisplayLogSplitter();
	SetupDlgControls();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnBtnAbort( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	Abort();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnBtnRecord( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );

	if( pThread )
	{
		pThread->SetRecordMode( e.IsChecked() );
		m_pMICapture_Record->Check( e.IsChecked() );
		GetToolBar()->ToggleTool( miCapture_Record, e.IsChecked() );
		SetupUpdateFrequencies( true );
	}
	SetupDlgControls();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnBtnLive( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	ConfigureLive();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnIncDecRecordDisplay( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );

	if( pThread )
	{
		SetupUpdateFrequencies( false );
		unsigned long int currentImage = static_cast<unsigned long int>(( e.GetId() == miCapture_Forward ) ? pThread->DisplaySequenceRequestNext() : pThread->DisplaySequenceRequestPrev());
		WriteLogMessage( wxString::Format( wxT("Recorded image %lu: "), currentImage ) );
		m_pRecordDisplaySlider->SetValue( currentImage );
		m_boCurrentImageIsFromFile = false;
		UpdateData( true, true );
	}
	SetupDlgControls();
}

//-----------------------------------------------------------------------------
void PropViewFrame::ToggleCurrentDevice( void )
//-----------------------------------------------------------------------------
{
	int devIndex = m_pDevCombo->GetSelection();
	Device* pDev = m_pDevPropHandler->GetActiveDevice();
	if( pDev )
	{
		SetCursor( *wxHOURGLASS_CURSOR );
		bool isOpen = pDev->isOpen();
		WriteLogMessage( wxString::Format( wxT("Trying to %s device %d (%s)\n"), ( isOpen ? wxT("close"): wxT("open") ), devIndex, ConvertedString(pDev->serial.read()).c_str() ) );
		try
		{
			if( isOpen )
			{
				if( !m_boCloseDeviceInProgress )
				{
					m_boCloseDeviceInProgress = true;
					if( !m_boCurrentImageIsFromFile )
					{
						const DisplayWindowContainer::size_type displayCount = m_pDisplayAreas.size();
						for( DisplayWindowContainer::size_type i=0; i<displayCount; i++ )
						{
							
							CaptureThread* pCT = 0;
							m_pDevPropHandler->GetActiveDevice( 0, 0, &pCT );
							if( pCT && ( m_CurrentRequestDataContainer[i].requestNr_ != INVALID_ID ) )
							{
								pCT->UnlockRequest( m_CurrentRequestDataContainer[i].requestNr_ );
							}
							m_CurrentRequestDataContainer[i] = RequestData();
							m_pDisplayAreas[i]->SetImage( m_CurrentRequestDataContainer[i].image_.getBuffer() );
							if( m_pDisplayAreas[i]->GetMonitorDisplay() == m_pMonitorImage->GetDisplayArea() )
							{
								m_pMonitorImage->GetDisplayArea()->SetImage( m_pDisplayAreas[i]->GetImage() );
							}
						}
					}
					{
						wxCriticalSectionLocker locker(m_CritSect);
						m_settingToDisplayDict.clear();
					}
					m_pDevPropHandler->CloseDriver( GetSelectedDeviceSerial() );
					UpdateData();
					UpdateToolTipWindow( GetPropertyGrid()->GetSelectedProperty() );
					m_boCloseDeviceInProgress = false;
				}
			}
			else
			{
				if( pDev->interfaceLayout.isValid() && ( pDev->interfaceLayout.read() == dilGeneric ) )
				{
					wxMessageBox(wxT("This interface layout has been declared deprecated. Please think about porting an application using it to the interface layout 'GenICam' instead."), wxT("WARNING"), wxOK | wxICON_EXCLAMATION, this);
				}
				
				m_pDevPropHandler->OpenDriver( GetSelectedDeviceSerial(), this );
				SetupCaptureSettingsUsageMode( m_pMICapture_CaptureSettings_UsageMode_Manual->IsChecked() ? csumManual : csumAutomatic );
				UpdateSettingTable();
			}
			WriteLogMessage( wxT(" Done...\n") );
		}
		catch( const ImpactAcquireException& e )
		{
			WriteErrorMessage( wxString::Format( wxT("\n%s(%s)\n"), ConvertedString(e.getErrorString()).c_str(), ConvertedString(e.getErrorCodeAsString()).c_str() ) );
			WriteErrorMessage( wxString::Format( wxT("Error origin: %s.\n"), ConvertedString(e.getErrorOrigin()).c_str() ) );
		}
		SetupDlgControls();
		SetCursor( wxNullCursor );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnUseDevice( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	ToggleCurrentDevice();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnBtnSnap(wxCommandEvent& )
//-----------------------------------------------------------------------------
{

	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );
	if( pThread )
	{
		SetupUpdateFrequencies( false );
		int result = pThread->RequestSingle( !m_pMICapture_Recording_SlientMode->IsChecked() );
		if( result != DMR_NO_ERROR )
		{
			WriteErrorMessage( wxString::Format( wxT("Image request failed(Reason: %s)! More information can be found in the *.log-file or the debug output.\n"), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ) );
		}
		SetupDlgControls();
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotCBAOIFullMode( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	int plotIndex = GetAnalysisControlIndex( e.GetId() );
	m_ImageAnalysisPlots[plotIndex].m_pPlotCanvas->SetAOIFullMode( e.IsChecked() );
	if( m_ImageAnalysisPlots[plotIndex].m_pPlotCanvas->IsActive() )
	{
		m_ImageAnalysisPlots[plotIndex].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex],
			m_ImageAnalysisPlots[plotIndex].m_pSCAOIx->GetValue(),
			m_ImageAnalysisPlots[plotIndex].m_pSCAOIy->GetValue(),
			m_ImageAnalysisPlots[plotIndex].m_pSCAOIw->GetValue(),
			m_ImageAnalysisPlots[plotIndex].m_pSCAOIh->GetValue(),
			true );
		m_pCurrentAnalysisDisplay->Refresh( false );
	}
	m_ImageAnalysisPlots[plotIndex].UpdateControls();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotCBProcessBayerParity( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	int plotIndex = GetAnalysisControlIndex( e.GetId() );
	m_ImageAnalysisPlots[plotIndex].m_pPlotCanvas->SetProcessBayerParity( e.IsChecked() );
	if( m_ImageAnalysisPlots[plotIndex].m_pPlotCanvas->IsActive() )
	{
		m_ImageAnalysisPlots[plotIndex].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex],
			m_ImageAnalysisPlots[plotIndex].m_pSCAOIx->GetValue(),
			m_ImageAnalysisPlots[plotIndex].m_pSCAOIy->GetValue(),
			m_ImageAnalysisPlots[plotIndex].m_pSCAOIw->GetValue(),
			m_ImageAnalysisPlots[plotIndex].m_pSCAOIh->GetValue(),
			true );
		m_pCurrentAnalysisDisplay->Refresh( false );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnCBEnableInfoPlot( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	m_pInfoPlotArea->SetActive( m_pCBEnableInfoPlot->IsChecked() );
	if( m_pCBEnableInfoPlot->IsChecked() )
	{
		m_pInfoPlotArea->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].requestInfo_, true );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnClose( wxCloseEvent& )
//-----------------------------------------------------------------------------
{
	Deinit();
	Destroy();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnConnectedOnly( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	UpdateDeviceComboBox();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnContinuousRecording( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	if( m_pDevPropHandler )
	{
		m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );
		if( pThread )
		{
			pThread->SetContinuousRecording( e.IsChecked() );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnDevComboTextChanged( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	UpdateDeviceFromComboBox();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnEventNotified( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	Device* pDevice = static_cast<Device*>(e.GetClientData());
	if( pDevice )
	{
		WriteLogMessage( wxString::Format( wxT("There has been a %s event reported by device %s.\n"), e.GetString().c_str(), ConvertedString(pDevice->serial.read()).c_str() ), wxTextAttr(wxColour(0, 150, 50)) );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnExportActiveDevice( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	wxFileDialog fileDlg( this, wxT("Select a filename"), wxT(""), wxT(""), wxT("mv-settings Files (*.xml)|*.xml"), wxSAVE | wxOVERWRITE_PROMPT );
	if( fileDlg.ShowModal() == wxID_OK )
	{
		wxString pathName = fileDlg.GetPath();
		FunctionInterface* p = 0;
		m_pDevPropHandler->GetActiveDevice( &p );
		if( p )
		{
			string pathANSI(pathName.mb_str());
			int result = p->saveSetting( pathANSI, sfDefault, sGlobal );
			if( result == DMR_NO_ERROR )
			{
				WriteLogMessage( wxString::Format( wxT("Successfully stored data to %s.\n"), pathName.c_str() ) );
			}
			else
			{
				DisplaySettingLoadSaveErrorMessage( wxString::Format( wxT("Storing of data to %s failed(error code: %d(%s))."), pathName.c_str(), result, ConvertedString(ImpactAcquireException::getErrorCodeAsString(result)).c_str() ), result );
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotDrawStartChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetDrawStartPercent( e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotDrawStartTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetDrawStartPercent( e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotDrawWindowChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetDrawWindowWidthPercent( e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotDrawWindowTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetDrawWindowWidthPercent( e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotDrawStepWidthChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	dynamic_cast<HistogramCanvas*>(m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas)->SetDrawStepWidth( e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotDrawStepWidthTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	dynamic_cast<HistogramCanvas*>(m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas)->SetDrawStepWidth( e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotGridXStepsChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetGridSteps( e.GetPosition(), -1 );
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, -1, -1, -1, true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotGridXStepsTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetGridSteps( e.GetInt(), -1 );
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, -1, -1, -1, true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotGridYStepsChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetGridSteps( -1, e.GetPosition() );
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, -1, -1, -1, true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotGridYStepsTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetGridSteps( -1, e.GetInt() );
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, -1, -1, -1, true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlot_PlotSelectionChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetPlotSelection( e.GetString() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotHistoryDepthChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetHistoryDepth( e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotHistoryDepthTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->SetHistoryDepth( e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::AnalysisPlotUpdateSpeedChanged( void )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	if( m_pDevPropHandler )
	{
		m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );
		if( pThread )
		{
			if( pThread->GetLiveMode() )
			{
				SetupUpdateFrequencies( true );
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotUpdateSpeedChanged( wxSpinEvent& )
//-----------------------------------------------------------------------------
{
	AnalysisPlotUpdateSpeedChanged();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotUpdateSpeedTextChanged( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	AnalysisPlotUpdateSpeedChanged();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnPropertyChangedCustom( wxPropertyGridEvent& )
//-----------------------------------------------------------------------------
{
	m_pDevPropHandler->SetActiveDevice( GetSelectedDeviceSerial() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnPropertyRightClickedCustom( wxPropertyGridEvent& )
//-----------------------------------------------------------------------------
{
	m_pDevPropHandler->SetActiveDevice( GetSelectedDeviceSerial() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnPropertyGridTimer( void )
//-----------------------------------------------------------------------------
{
	if( !m_boImageCanvasInFullScreenMode )
	{
		if( m_pPropGrid->IsShown() )
		{
			// while the propgrid is not displayed we don't need to update it
			m_pDevPropHandler->ValidateTrees();
		}
		SetupDlgControls();
		UpdateStatusBar();
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnPropertySelectedCustom( wxPropertyGridEvent& e )
//-----------------------------------------------------------------------------
{
	UpdateToolTipWindow( e.GetProperty() );
}


//-----------------------------------------------------------------------------
void PropViewFrame::OnRefreshAOIControls( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	if( m_CurrentImageAnalysisControlIndex < 0 )
	{
		return;
	}

	// this will reconstruct an AOI for the selected image analysis page as a result of rectangle being dragged with the right mouse button pressed down
	const AOI* const pAOI = m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->GetAOI();
	if( pAOI )
	{
		ConfigureAOI( m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex], pAOI->m_rect );
		m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], pAOI->m_rect.GetLeft(), pAOI->m_rect.GetTop(), pAOI->m_rect.GetWidth(), pAOI->m_rect.GetHeight() );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnRefreshCurrentPixelData( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_pLastMouseHooverDisplay = m_pDisplayAreas[e.GetInt()];
	RefreshCurrentPixelData();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnImageCanvasSelected( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	SelectImageCanvas( e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnImageCanvasFullScreen( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_boImageCanvasInFullScreenMode = ( e.GetInt() != 0 );
	GetPropertyGrid()->SelectProperty( wxPGId(0), true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnImageInfo( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	auto_ptr<RequestInfoData> p(reinterpret_cast<RequestInfoData*>(e.GetClientData()));
	if( m_pInfoPlotArea )
	{
		m_pInfoPlotArea->RefreshData( *p );
		if( m_pInfoPlotArea->IsActive() )
		{
			time_t t = static_cast<time_t>(p->timeStamp_us / 1000000);
			wxDateTime dt(t);
			dt.SetMillisecond( static_cast<wxDateTime::wxDateTime_t>(( p->timeStamp_us % 1000000 ) / 1000) );
			m_pTCTimestampAsTime->SetValue( wxString::Format( wxT("%02d:%02d:%02d:%03d"), dt.GetHour(), dt.GetMinute(), dt.GetSecond(), dt.GetMillisecond() ) );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnImageReady( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	m_boCurrentImageIsFromFile = false;
	UpdateData( false, true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnImageSkipped( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boShutdownInProgress )
	{
		return;
	}

	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );
	size_t cnt = 1;
	if( pThread )
	{
		cnt = pThread->GetSkippedImageCount();
	}

	int index = 0;
	{
		wxCriticalSectionLocker locker(m_CritSect);
		SettingToDisplayDict::const_iterator it = m_settingToDisplayDict.find( e.GetInt() );
		index = ( it != m_settingToDisplayDict.end() ) ? it->second : 0;
	}
	if( m_pLogWindow && !m_pDisplayAreas.empty() && m_pDisplayAreas[index]->IsActive() )
	{
		m_pDisplayAreas[index]->IncreaseSkippedCounter( cnt );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSequenceReady( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );

	if( pThread )
	{
		wxString msg(wxString::Format( wxT("All %lu ('RequestCount') images recorded.\n"), static_cast<unsigned long int>(pThread->GetRecordedSequence().size()) ));
		if( m_pLogWindow )
		{
			WriteLogMessage( msg );
		}
		if( !m_pMICapture_Recording_SlientMode->IsChecked() )
		{
			wxMessageDialog dlg( NULL, msg, wxT("Info"), wxOK | wxICON_WARNING );
			dlg.ShowModal();
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnImportActiveDevice( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	wxFileDialog fileDlg( this, wxT("Select a filename"), wxT(""), wxT(""), wxT("mv-settings Files (*.xml)|*.xml"), wxOPEN | wxFILE_MUST_EXIST );
	if( fileDlg.ShowModal() == wxID_OK )
	{
		wxString pathName = fileDlg.GetPath();
		FunctionInterface* p = 0;
		m_pDevPropHandler->GetActiveDevice( &p );
		if( p )
		{
			string pathANSI(pathName.mb_str());
			int result = p->loadSetting( pathANSI, sfDefault, sGlobal );
			if( result == DMR_NO_ERROR )
			{
				WriteLogMessage( wxString::Format( wxT("Importing data from %s successful.\n"), pathName.c_str() ) );
			}
			else
			{
				DisplaySettingLoadSaveErrorMessage( wxString::Format( wxT("Importing data from %s failed(error code: %d(%s)).\n"), pathName.c_str(), result, ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ), result );
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnManageSettings( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	if( m_pDevPropHandler )
	{
		Device* pDev = m_pDevPropHandler->GetActiveDevice();
		if( pDev && pDev->autoLoadSettingOrder.isValid() )
		{
			map<int, SettingData> data;
			wxArrayString choices;
			const unsigned int valCount = pDev->autoLoadSettingOrder.valCount();
			for( unsigned int i=0; i<valCount; i++ )
			{
				const string setting(pDev->autoLoadSettingOrder.read( i ));
				if( OBJ_IsSettingAvailable( setting.c_str(), sfNative, sUser ) == PROPHANDLING_NO_ERROR )
				{
					data.insert( make_pair( choices.GetCount(), SettingData(sUser, setting) ) );
					choices.Add( ConvertedString(setting) );
				}
				if( OBJ_IsSettingAvailable( setting.c_str(), sfNative, sGlobal ) == PROPHANDLING_NO_ERROR )
				{
					data.insert( make_pair( choices.GetCount(), SettingData(sGlobal, setting) ) );
					choices.Add( ConvertedString(setting) + wxString(wxT("(global storage)")) );
				}
			}
			if( choices.IsEmpty() )
			{
				wxMessageDialog dlg(this, wxT("There are no settings available for configuration for this device!"));
				dlg.ShowModal();
			}
			else
			{
				wxMultiChoiceDialog dlg(this, wxT("Please select the settings, that shall be deleted.\nPlease note, that settings, that have a name different from the serial\nnumber of the current device might affect the behaviour of other devices as well."), wxT("Select settings"), choices);
				if( dlg.ShowModal() == wxID_OK )
				{
					wxArrayInt selections = dlg.GetSelections();
					const size_t selectionCount = selections.GetCount();
					for( size_t j=0; j<selectionCount; j++ )
					{
						map<int, SettingData>::const_iterator it = data.find( selections[j] );
						if( it == data.end() )
						{
							WriteErrorMessage( wxT("INTERNAL ERROR! Setting can't be deleted as it can't be located in the internal hash table.\n") );
							continue;
						}
						TPROPHANDLING_ERROR result = OBJ_DeleteSetting( it->second.name_.c_str(), sfNative, it->second.scope_ );
						if( result != PROPHANDLING_NO_ERROR )
						{
							WriteErrorMessage( wxString::Format( wxT("Failed to delete setting %s(scope: %d). Error code: %s.\n"),
								ConvertedString(it->second.name_).c_str(),
								it->second.scope_,
								ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ) );
						}
					}
				}
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnNotebookPageChanged( wxNotebookEvent& )
//-----------------------------------------------------------------------------
{
	ImageAnalysisPlotCanvas* p = DeselectAnalysisPlot();
	m_CurrentImageAnalysisControlIndex = GetAnalysisControlIndex();
	if( p && m_pMISettings_Analysis_SynchroniseAOIs->IsChecked() )
	{
		wxRect activeAOI = p->GetAOIRect();
		ConfigureAnalysisPlot( &activeAOI );
	}
	else
	{
		ConfigureAnalysisPlot();
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnNBConfigurationMethodPageChanged( wxNotebookEvent& )
//-----------------------------------------------------------------------------
{
	WriteLogMessage( wxString::Format( wxT("New configuration method selected: %d.\n"), m_pNBConfigurationMethod->GetSelection() ) );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnNBDisplayMethodPageChanged( wxNotebookEvent& )
//-----------------------------------------------------------------------------
{
	if( m_CurrentImageAnalysisControlIndex >= 0 )
	{
		m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->SetDisplayMethod( static_cast<ImageAnalysisPlotCanvas::TDisplayMethod>(m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pNBDisplayMethod->GetSelection()) );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotAOIxChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boUpdateAOIInProgress )
	{
		return;
	}
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotAOIxTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boUpdateAOIInProgress )
	{
		return;
	}
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotAOIyChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boUpdateAOIInProgress )
	{
		return;
	}
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotAOIyTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boUpdateAOIInProgress )
	{
		return;
	}
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotAOIwChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boUpdateAOIInProgress )
	{
		return;
	}
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, -1, e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotAOIwTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boUpdateAOIInProgress )
	{
		return;
	}
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, -1, e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotAOIhChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boUpdateAOIInProgress )
	{
		return;
	}
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, -1, -1, e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnAnalysisPlotAOIhTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	if( m_boUpdateAOIInProgress )
	{
		return;
	}
	m_ImageAnalysisPlots[GetAnalysisControlIndex( e.GetId() )].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex], -1, -1, -1, e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnInfoPlot_PlotSelectionComboTextChanged( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	InfoPlotCanvas::TPlotSelection plotSelection = static_cast<InfoPlotCanvas::TPlotSelection>(wxPtrToUInt( m_pInfoPlotSelectionCombo->GetClientData( m_pInfoPlotSelectionCombo->GetSelection() ) ));
	m_pInfoPlotArea->SetPlotSelection( plotSelection );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnInfoPlotUpdateHistoryDepthChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	m_pInfoPlotArea->SetHistoryDepth( e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnInfoPlotUpdateHistoryDepthTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_pInfoPlotArea->SetHistoryDepth( e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnInfoPlotUpdateSpeedChanged( wxSpinEvent& e )
//-----------------------------------------------------------------------------
{
	m_pInfoPlotArea->SetUpdateFrequency( e.GetPosition() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnInfoPlotUpdateSpeedTextChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_pInfoPlotArea->SetUpdateFrequency( e.GetInt() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnLiveModeAborted( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	wxString msg(wxString::Format( wxT("The live mode has been aborted because of the following error: '%s'.\n"), e.GetString().c_str() ));
	wxMessageDialog dlg( NULL, msg, wxT("Information"), wxOK | wxICON_INFORMATION );
	dlg.ShowModal();
	WriteErrorMessage( msg );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnLoadActiveDevice( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	if( m_pDevPropHandler )
	{
		FunctionInterface* p = 0;
		m_pDevPropHandler->GetActiveDevice( &p );
		if( p )
		{
			wxArrayString choices;
			choices.Add( wxString(wxT("user specific(default)")) );
			choices.Add( wxString(wxT("system wide")) );
			wxSingleChoiceDialog dlg(this, wxT("Please select the scope from where for this setting shall be imported.\nSystem wide settings can be used by every user logged on to this system,\nbut only certain users might be able to modify them."), wxT("Select the settings scope"), choices);
			if( dlg.ShowModal() == wxID_OK )
			{
				string serialANSI(GetSelectedDeviceSerial().mb_str());
				int result = p->loadSetting( serialANSI, sfNative, ( dlg.GetSelection() == 0 ) ? sUser : sGlobal );
				if( result == DMR_NO_ERROR )
				{
					WriteLogMessage( wxString::Format( wxT("Successfully loaded current settings with %s scope for device %s.\n"), ( dlg.GetSelection() == 0 ) ? wxT("user specific") : wxT("global"), m_pDevCombo->GetValue().c_str() ) );
				}
				else
				{
					DisplaySettingLoadSaveErrorMessage( wxString::Format( wxT("Loading settings for the current device failed. Result: %s.\n"), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ), result );
				}
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnLoadCurrentProduct( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	if( m_pDevPropHandler )
	{
		FunctionInterface* p = 0;
		Device* pDev = m_pDevPropHandler->GetActiveDevice( &p );
		if( p && pDev )
		{
			wxArrayString choices;
			choices.Add( wxString(wxT("user specific(default)")) );
			choices.Add( wxString(wxT("system wide")) );
			wxSingleChoiceDialog dlg(this, wxT("Please select the scope from where for this setting shall be imported.\nSystem wide settings can be used by every user logged on to this system,\nbut only certain users might be able to modify them."), wxT("Select the settings scope"), choices);
			if( dlg.ShowModal() == wxID_OK )
			{
				int result = p->loadSetting( pDev->product.read(), sfNative, ( dlg.GetSelection() == 0 ) ? sUser : sGlobal );
				if( result == DMR_NO_ERROR )
				{
					WriteLogMessage( wxString::Format( wxT("Successfully loaded current settings with %s scope for product range %s.\n"), ( dlg.GetSelection() == 0 ) ? wxT("user specific") : wxT("global"), ConvertedString(pDev->product.read()).c_str() ) );
				}
				else
				{
					DisplaySettingLoadSaveErrorMessage( wxString::Format( wxT("Loading settings for the current product type failed. Result: %s.\n"), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ), result );
				}
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnLoadFromDefault( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	if( m_pDevPropHandler )
	{
		FunctionInterface* p = 0;
		m_pDevPropHandler->GetActiveDevice( &p );
		if( p )
		{
			int result = p->loadSettingFromDefault();
			if( result == DMR_NO_ERROR )
			{
				WriteLogMessage( wxT("Successfully loaded current settings for the current device from the default location.\n") );
			}
			else
			{
				DisplaySettingLoadSaveErrorMessage( wxString::Format( wxT("Loading settings for the current device from the default location failed. Result: %s.\n"), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ), result );
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnQuit( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	// true is to force the frame to close
	Close( true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSaveActiveDevice( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	FunctionInterface* p = 0;
	m_pDevPropHandler->GetActiveDevice( &p );
	if( p )
	{
		wxArrayString choices;
		choices.Add( wxString(wxT("user specific(default)")) );
		choices.Add( wxString(wxT("system wide")) );
		wxSingleChoiceDialog dlg(this, wxT("Please select the scope to which this setting shall be exported.\nPlease note, that storing a setting for system wide usage might\nrequire certain user privileges not available to every user.\nSystem wide settings can be used by every user logged on to this system."), wxT("Select the settings scope"), choices);
		if( dlg.ShowModal() == wxID_OK )
		{
			string pathANSI(GetSelectedDeviceSerial().mb_str());
			int result = p->saveSetting( pathANSI, sfNative, ( dlg.GetSelection() == 0 ) ? sUser : sGlobal );
			if( result == DMR_NO_ERROR )
			{
				WriteLogMessage( wxString::Format( wxT("Successfully stored current settings with %s scope for device %s.\n"), ( dlg.GetSelection() == 0 ) ? wxT("user specific") : wxT("global"), m_pDevCombo->GetValue().c_str() ) );
			}
			else
			{
				DisplaySettingLoadSaveErrorMessage( wxString::Format( wxT("Storing settings for device %s failed. Result: %s.\n"), m_pDevCombo->GetValue().c_str(), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ), result );
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSaveCurrentProduct( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	FunctionInterface* p = 0;
	Device* pDev = m_pDevPropHandler->GetActiveDevice( &p );
	if( p && pDev )
	{
		wxArrayString choices;
		choices.Add( wxString(wxT("user specific(default)")) );
		choices.Add( wxString(wxT("system wide")) );
		wxSingleChoiceDialog dlg(this, wxT("Please select the scope to which this setting shall be exported.\nPlease note, that storing a setting for system wide usage might\nrequire certain user privileges not available to every user.\nSystem wide settings can be used by every user logged on to this system."), wxT("Select the settings scope"), choices);
		if( dlg.ShowModal() == wxID_OK )
		{
			int result = p->saveSetting( pDev->product.read(), sfNative, ( dlg.GetSelection() == 0 ) ? sUser : sGlobal );
			if( result == DMR_NO_ERROR )
			{
				WriteLogMessage( wxString::Format( wxT("Successfully stored current settings with %s scope for product range %s.\n"), ( dlg.GetSelection() == 0 ) ? wxT("user specific") : wxT("global"), ConvertedString(pDev->product.read()).c_str() ) );
			}
			else
			{
				DisplaySettingLoadSaveErrorMessage( wxString::Format( wxT("Storing settings for product range %s failed. Result: %s.\n"), ConvertedString(pDev->product.read()).c_str(), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ), result );
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::SaveImage( const wxString& filenameAndPath, TFileFormat fileFilterIndex )
//-----------------------------------------------------------------------------
{
	wxString extension;
	switch( fileFilterIndex )
	{
	case 0:
		extension = wxT("bmp");
		break;
	case 1:
		extension = wxT("png");
		break;
	case 2:
	default:
		extension = wxT("raw");
		break;
	}

	if( extension == wxT("raw") )
	{
		wxFileName tmpFilename(filenameAndPath);
		wxString name(tmpFilename.GetName());
		tmpFilename.SetName( wxString::Format( wxT("%s.%dx%d.%s"), name.c_str(), m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iWidth, m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iHeight, m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].pixelFormat_.c_str() ) );
		tmpFilename.SetExt( extension );
		wxFile file(tmpFilename.GetFullPath().c_str(), wxFile::write);
		if( !file.IsOpened() )
		{
			WriteErrorMessage( wxString::Format( wxT("Storing of %s failed. Could not open file.\n"), tmpFilename.GetFullPath().c_str() ) );
			return;
		}
		size_t bytesWritten = file.Write( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->vpData, m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iSize );
		if( bytesWritten < static_cast<size_t>(m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iSize) )
		{
			WriteErrorMessage( wxString::Format( wxT("Storing of %s failed. Could not write all data.\n"), tmpFilename.GetFullPath().c_str() ) );
			return;
		}
		WriteLogMessage( wxString::Format( wxT("Storing of %s successful.\n"), tmpFilename.GetFullPath().c_str() ) );
	}
	else
	{
		wxFileName tmp(filenameAndPath);
		tmp.SetExt( extension );
		ImageCanvas::TSaveResult result = m_pCurrentAnalysisDisplay->SaveCurrentImage( tmp.GetFullPath(), extension );
		switch( result )
		{
		case ImageCanvas::srOK:
			WriteLogMessage( wxString::Format( wxT("Storing of %s successful.\n"), tmp.GetFullPath().c_str() ) );
			break;
		case ImageCanvas::srNoImage:
			WriteErrorMessage( wxT("There is no valid image to store!\n") );
			break;
		case ImageCanvas::srFailedToSave:
			WriteErrorMessage( wxString::Format( wxT("Storing of %s failed.\n"), tmp.GetFullPath().c_str() ) );
			break;
		default:
			WriteLogMessage( wxString::Format( wxT("Storing of %s return unexpected value: %d.\n"), tmp.GetFullPath().c_str(), result ) );
			break;
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::SelectImageCanvas( int index )
//-----------------------------------------------------------------------------
{
	if( m_pCurrentAnalysisDisplay != m_pDisplayAreas[index] )
	{
		m_CurrentRequestDataIndex = index;
		m_pCurrentAnalysisDisplay->RegisterMonitorDisplay( 0 );
		ImageAnalysisPlotCanvas* p = DeselectAnalysisPlot();
		if( p )
		{
			p->RegisterImageCanvas( 0 );
		}
		m_pCurrentAnalysisDisplay->Refresh();
		m_pCurrentAnalysisDisplay = m_pDisplayAreas[index];
		m_pCurrentAnalysisDisplay->RegisterMonitorDisplay( m_pMISettings_Display_ShowMonitorImage->IsChecked() ? m_pMonitorImage->GetDisplayArea() : 0 );
		m_pMonitorImage->GetDisplayArea()->SetImage( m_pCurrentAnalysisDisplay->GetImage() );
		if( p && m_pMISettings_Analysis_SynchroniseAOIs->IsChecked() )
		{
			wxRect activeAOI = p->GetAOIRect();
			ConfigureAnalysisPlot( &activeAOI );
		}
		else
		{
			ConfigureAnalysisPlot();
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnLoadImage( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	wxFileDialog fileDlg( this, wxT("Select a file"), wxT(""), wxT(""), wxT("Supported image files (*.bmp;*.gif;*.jpeg;*.jpg;*.png;*.tif;*.raw)|*.bmp;*.gif;*.jpeg;*.jpg;*.png;*.tif;*.raw"), wxOPEN | wxFILE_MUST_EXIST );
	if( fileDlg.ShowModal() == wxID_OK )
	{
		SetCurrentImage( wxFileName(fileDlg.GetPath()), m_pCurrentAnalysisDisplay );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSaveImageSequenceToFiles( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );

	if( pThread )
	{
		wxFileDialog fileDlg( this, wxT("Select a filename"), wxT(""), wxT(""), wxT("BMP files (*.bmp)|*.bmp|PNG files (*.png)|*.png|RAW files (*.raw)|*.raw"), wxSAVE );
		if( fileDlg.ShowModal() == wxID_OK )
		{
			wxString fileName = fileDlg.GetPath();
			if( fileName.IsEmpty() )
			{
				return;
			}
			wxFileName tmpFilename(fileName);
			wxString name;
			wxFileName::SplitPath( fileName, 0, &name, 0 );

			// remove number
			if( name.Len() > 3 )
			{
				wxString numstr = name.Right( 3 );
				if( numstr.IsNumber() )
				{
					name.RemoveLast( 3 );
				}
			}

			const RequestContainer &seq = pThread->GetRecordedSequence();
			RequestContainer::size_type size = seq.size();
			m_boCurrentImageIsFromFile = false;
			for( RequestContainer::size_type i=0; i<size; i++ )
			{
				pThread->DisplaySequenceRequest( i );
				UpdateData( false, true );
				tmpFilename.SetName( wxString::Format( wxT("%s%03lu"), name.c_str(), static_cast<unsigned long int>(i) ) );
				SaveImage( tmpFilename.GetFullPath(), static_cast<TFileFormat>(fileDlg.GetFilterIndex()) );
			}
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSaveImageSequenceToStream( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );

	if( pThread )
	{
		wxFileDialog fileDlg( this, wxT("Select a filename"), wxT(""), wxT(""), wxT("RAW Stream (*.rawstream)|*.rawstream"), wxSAVE );
		if( fileDlg.ShowModal() == wxID_OK )
		{
			if( fileDlg.GetPath().IsEmpty() )
			{
				return;
			}

			const RequestContainer &seq = pThread->GetRecordedSequence();
			RequestContainer::size_type size = seq.size();
			m_boCurrentImageIsFromFile = false;

			wxFile file(fileDlg.GetPath().c_str(), wxFile::write);
			if( !file.IsOpened() )
			{
				WriteErrorMessage( wxString::Format( wxT("Storing of %s failed. Could not open file.\n"), fileDlg.GetPath().c_str() ) );
				return;
			}

			for( RequestContainer::size_type i=0; i<size; i++ )
			{
				pThread->DisplaySequenceRequest( i );
				UpdateData( false, true );
				size_t bytesWritten = file.Write( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->vpData, m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iSize );
				if( bytesWritten < static_cast<size_t>(m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iSize) )
				{
					WriteErrorMessage( wxString::Format( wxT("Storing of frame %d into %s failed. Could not write all data(bytes written: %d, frame size: %d).\n"), i, fileDlg.GetPath().c_str(), bytesWritten, m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iSize ) );
					return;
				}
			}
			WriteLogMessage( wxString::Format( wxT("Successfully wrote %d frames into %s.\n"), size, fileDlg.GetPath().c_str() ) );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSaveImage( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	wxFileDialog fileDlg( this, wxT("Select a filename"), wxT(""), wxT(""), wxT("BMP files (*.bmp)|*.bmp|PNG files (*.png)|*.png|RAW files (*.raw)|*.raw"), wxSAVE | wxOVERWRITE_PROMPT );
	if( fileDlg.ShowModal() == wxID_OK )
	{
		wxString fileName = fileDlg.GetPath();
		if( fileName.IsEmpty() )
		{
			return;
		}

		wxFileName::SplitPath( fileName, 0, 0, 0 );
		SaveImage( fileName, static_cast<TFileFormat>(fileDlg.GetFilterIndex()) );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSaveToDefault( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	FunctionInterface* p = 0;
	m_pDevPropHandler->GetActiveDevice( &p );
	if( p )
	{
		int result = p->saveSettingToDefault();
		if( result == DMR_NO_ERROR )
		{
			WriteLogMessage( wxT("Successfully stored current settings for the current device to the default location.\n") );
		}
		else
		{
			DisplaySettingLoadSaveErrorMessage( wxString::Format( wxT("Storing settings for the current device to the default location failed. Result: %s.\n"), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ), result );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSaveSystemToDefault( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	FunctionInterface* p = 0;
	m_pDevPropHandler->GetActiveDevice( &p );
	if( p )
	{
		int result = p->saveSystemToDefault();
		if( result != DMR_NO_ERROR )
		{
			WriteErrorMessage( wxString::Format( wxT("Storing system settings to the default location failed. Result: %s.\n"), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ) );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnShowIncompleteFrames( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );
	if( pThread )
	{
		pThread->SetCaptureMode( e.IsChecked() );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnShowMonitorDisplay( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_pMonitorImage->GetDisplayArea()->SetActive( e.IsChecked() );
	m_pMonitorImage->Show( e.IsChecked() );
	m_pMISettings_Display_ShowMonitorImage->Check( e.IsChecked() );
	GetToolBar()->ToggleTool( miSettings_Display_ShowMonitorImage, e.IsChecked() );
	m_pCurrentAnalysisDisplay->RegisterMonitorDisplay( e.IsChecked() ? m_pMonitorImage->GetDisplayArea() : 0 );
	m_pMonitorImage->GetDisplayArea()->SetImage( e.IsChecked() ? m_pCurrentAnalysisDisplay->GetImage() : 0 );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnShowStatusBar( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	ConfigureStatusBar( e.IsChecked() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnShowToolBar( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	ConfigureToolBar( e.IsChecked() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::RefreshDisplays( bool boEraseBackground )
//-----------------------------------------------------------------------------
{
	const DisplayWindowContainer::size_type displayCount = m_pDisplayAreas.size();
	for( DisplayWindowContainer::size_type i=0; i<displayCount; i++ )
	{
		m_pDisplayAreas[i]->Refresh( boEraseBackground );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSettings_Analysis_ShowControls( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	m_pMISettings_Analysis_ShowControls->Check( e.IsChecked() );
	GetToolBar()->ToggleTool( miSettings_Analysis_ShowControls, e.IsChecked() );
	RefreshDisplays( true );
	SetupDisplayLogSplitter();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnCapture_CaptureSettings_CreateCaptureSetting( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	FunctionInterface* pFI = 0;
	CaptureThread* pCT = 0;
	Device* pDev = m_pDevPropHandler->GetActiveDevice( &pFI, 0, &pCT );
	if( pDev && pFI && pCT )
	{
		const vector<string>& settings(pFI->getAvailableSettings());
		wxString settingName = ::wxGetTextFromUser( wxT("Enter the name of the setting that shall be created(no whitespaces). A setting must have a unique name.\nPlease note that newly created settings can only be accessed via the property\ngrid is in 'Multiple Settings' or 'Developers' view mode."),
			wxT("Name of the setting"),
			wxString::Format( wxT("NewSetting%d"), settings.size() ),
			this );

		if( settingName.IsEmpty() )
		{
			WriteLogMessage( wxT("Operation canceled by the user OR empty setting name.\n") );
			return;
		}

		wxArrayString choices;
		vector<string>::const_iterator it = settings.begin();
		const vector<string>::const_iterator itEND = settings.end();
		while( it != itEND )
		{
			choices.Add( ConvertedString(*it) );
			++it;
		}
		wxSingleChoiceDialog dlg(this, wxT("Please select the setting, that shall be used as a parent for the setting to create.\nUntouched parameters in the new setting will automatically change\nwhen the parent settings parameter is modified.\nFor detailed information about the behaviour of settings please refer to the manual."), wxT("Select the parent setting"), choices);
		if( dlg.ShowModal() == wxID_OK )
		{
			wxString parentSetting(dlg.GetStringSelection());
			if( parentSetting.IsEmpty() )
			{
				WriteErrorMessage( wxT("No parent setting selected.\n") );
			}

			const string settingNameANSI(settingName.mb_str());
			const string parentSettingANSI(parentSetting.mb_str());
			int result = pFI->createSetting( settingNameANSI, parentSettingANSI );
			if( result == DMR_NO_ERROR )
			{
				UpdateSettingTable();
			}
			else
			{
				WriteErrorMessage( wxString::Format( wxT("Creation of setting %s based on %s failed. Result: %s.\n"), settingName.c_str(), parentSetting.c_str(), ConvertedString(ImpactAcquireException::getErrorCodeAsString( result )).c_str() ) );
			}
		}
		else
		{
			WriteLogMessage( wxT("Operation canceled by the user.\n") );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnCapture_CaptureSettings_CaptureSettingHierarchy( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	FunctionInterface* pFI = 0;
	Device* pDev = m_pDevPropHandler->GetActiveDevice( &pFI );
	if( pDev && pFI )
	{
		const vector<string>& settings(pFI->getAvailableSettings());
		StringToStringMap m;
		try
		{
			vector<string>::size_type cnt = settings.size();
			for( vector<string>::size_type i=0; i<cnt; i++ )
			{
				DeviceComponentLocator locator(pDev, dltSetting, settings[i]);
				PropertyS basedOn(locator.findComponent( "BasedOn" ));
				m.insert( make_pair( ConvertedString(settings[i]), ConvertedString(basedOn.read()) ) );
			}
		}
		catch( const ImpactAcquireException& e )
		{
			WriteErrorMessage( wxString::Format( wxT("Failed to create setting hierarchy: %s(%s)\n"), ConvertedString(e.getErrorString()).c_str(), ConvertedString(e.getErrorCodeAsString()).c_str() ) );
			return;
		}

		SettingHierarchyDlg dlg(this, wxString(wxT("Current Setting Hierarchy")), m);
		dlg.ShowModal();
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnCapture_CaptureSettings_AssignToDisplays( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	FunctionInterface* pFI = 0;
	Device* pDev = m_pDevPropHandler->GetActiveDevice( &pFI );
	if( pDev && pFI )
	{
		try
		{
			ImageRequestControl irc(pDev);
			vector<pair<string, int> > settings;
			irc.setting.getTranslationDict( settings );
			AssignSettingsToDisplaysDlg dlg(this, wxString(wxT("Settings To Display Setup")), settings, m_settingToDisplayDict, m_pDisplayAreas.size());
			if( dlg.ShowModal() == wxID_OK )
			{
				const std::vector<wxControl*>& ctrls = dlg.GetUserInputControls();
				wxCriticalSectionLocker locker(m_CritSect);
				m_settingToDisplayDict.clear();
				const vector<pair<string, int> >::size_type settingCount = settings.size();
				for( vector<pair<string, int> >::size_type i=0; i<settingCount; i++ )
				{
					wxString selection(dynamic_cast<wxComboBox*>(ctrls[i])->GetValue().AfterLast(wxT(' ')));
					long index = 0;
					if( selection.ToLong( &index ) )
					{
						m_settingToDisplayDict.insert( make_pair( settings[i].second, index ) );
					}
					else
					{
						WriteErrorMessage( wxString::Format( wxT("Failed to obtain display index from selection '%s'.\n"), selection.c_str() ) );
					}
				}
			}
			else
			{
				WriteLogMessage( wxT("Operation canceled by the user.\n") );
			}
		}
		catch( const ImpactAcquireException& e )
		{
			WriteErrorMessage( wxString::Format( wxT("Failed to create setting hierarchy: %s(%s)\n"), ConvertedString(e.getErrorString()).c_str(), ConvertedString(e.getErrorCodeAsString()).c_str() ) );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::SetupCaptureSettingsUsageMode( TCaptureSettingUsageMode mode )
//-----------------------------------------------------------------------------
{
	CaptureThread* pCT = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pCT );
	if( pCT )
	{
		pCT->SetCaptureSettingUsageMode( mode );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnCapture_CaptureSettings_UsageMode_Changed( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	switch( e.GetId() )
	{
	case miCapture_CaptureSettings_UsageMode_Manual:
		SetupCaptureSettingsUsageMode( csumManual );
		break;
	case miCapture_CaptureSettings_UsageMode_Automatic:
		SetupCaptureSettingsUsageMode( csumAutomatic );
		break;
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSettingsPropGrid_Show( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	SetupVerSplitter( e.IsChecked() );
	m_pMISettings_PropGrid_Show->Check( e.IsChecked() );
	GetToolBar()->ToggleTool( miSettings_PropGrid_Show, e.IsChecked() );
	RefreshDisplays( true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSettingsPropGrid_UpdateViewMode( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	UpdatePropGridViewMode();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSettingsPropGrid_ViewModeChanged( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	switch( e.GetId() )
	{
	case miSettings_PropGrid_StandardView:
		m_ViewMode = DevicePropertyHandler::vmStandard;
		break;
	case miSettings_PropGrid_DevelopersView:
		m_ViewMode = DevicePropertyHandler::vmDeveloper;
		break;
	}
	UpdatePropGridViewMode();
	m_ViewMode = m_pDevPropHandler->GetViewMode();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSettings_DefaultDeviceInterface_Changed( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	switch( e.GetId() )
	{
	case miSettings_DefaultDeviceInterface_DeviceSpecific:
		m_defaultDeviceInterfaceLayout = dilDeviceSpecific;
		break;
	case miSettings_DefaultDeviceInterface_Generic:
		m_defaultDeviceInterfaceLayout = dilGeneric;
		break;
	case miSettings_DefaultDeviceInterface_GenICam:
		m_defaultDeviceInterfaceLayout = dilGenICam;
		break;
	}
	UpdateDeviceInterfaceLayouts();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSetupCaptureQueueDepth( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	FunctionInterface* pFI = 0;
	Device* pDev = m_pDevPropHandler->GetActiveDevice( &pFI, 0, &pThread );

	if( pDev && pFI && pThread )
	{
		const int maxCaptureQueueDepth = pFI->requestCount() - 1;
		long newValue = ::wxGetNumberFromUser( wxString::Format( wxT("Enter the new capture queue depth for device %s.\nNote that this can't be larger then the number of request buffers currently allocated - 1 buffer that is currently displayed and/or analysed.\n'0' will restore the internal default behaviour."), ConvertedString(pDev->serial.read().c_str()).c_str() ),
			wxT("New capture queue depth"),
			wxT("Setup capture queue depth"),
			pThread->GetCaptureQueueDepth(),
			0,
			maxCaptureQueueDepth,
			this );
		if( newValue >= 0 )
		{
			pThread->SetCaptureQueueDepth( newValue );
		}
		else
		{
			WriteLogMessage( wxT("Operation canceled by the user.\n") );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSetupRecordSequenceSize( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	FunctionInterface* pFI = 0;
	Device* pDev = m_pDevPropHandler->GetActiveDevice( &pFI, 0, &pThread );

	if( pDev && pFI && pThread )
	{
		const int maxCaptureQueueDepth = pFI->requestCount();
		long newValue = ::wxGetNumberFromUser( wxString::Format( wxT("Enter the new record sequence length for device %s.\nNote that this can't be larger then the number of request buffers currently allocated.\n'0' will restore the internal default behaviour."), ConvertedString(pDev->serial.read().c_str()).c_str() ),
			wxT("New record sequence length"),
			wxT("Setup record sequence length"),
			pThread->GetRecordSequenceSize(),
			0,
			maxCaptureQueueDepth,
			this );
		if( newValue >= 0 )
		{
			pThread->SetRecordSequenceSize( newValue );
		}
		else
		{
			WriteLogMessage( wxT("Operation canceled by the user.\n") );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSetupHarddiscRecording( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	wxMessageDialog dlg( NULL,
		wxT("Enable harddisc recording?"),
		wxT("Configure harddisc recording"),
		wxNO_DEFAULT | wxYES_NO );

	m_harddiscRecordingParameters.boActive_ = dlg.ShowModal() == wxID_YES;
	if( !m_harddiscRecordingParameters.boActive_ )
	{
		WriteLogMessage( wxT("Harddisc recording disabled.\n") );
		return;
	}

	m_harddiscRecordingParameters.targetDirectory_ = ::wxDirSelector(wxT("Choose a target folder for the images"));
	if( m_harddiscRecordingParameters.targetDirectory_.empty() )
	{
		WriteLogMessage( wxT("Invalid target folder selected.\n") );
		m_harddiscRecordingParameters.boActive_ = false;
		return;
	}

	wxArrayString choices;
	choices.Add( wxString(wxT("*.bmp(slowest)")) );
	choices.Add( wxString(wxT("*.png")) );
	choices.Add( wxString(wxT("*.raw(fastest)")) );
	wxSingleChoiceDialog dlgFileFormat(this, wxT("Please select the file format for the recorded images. Please note that\nrecording needs an active display right now and once the storage of a frame needs\nmore time then the acquisition of the next image, the next image will neither\nbe displayed nore stored but is skipped.\nThe application might react reaaally slow when in BMP or PNG mode."), wxT("Configure harddisc recording"), choices);
	if( dlgFileFormat.ShowModal() != wxID_OK )
	{
		WriteLogMessage( wxT("Operation canceled by the user.\n") );
		m_harddiscRecordingParameters.boActive_ = false;
		return;
	}
	m_harddiscRecordingParameters.fileFormat_ = static_cast<TFileFormat>(dlgFileFormat.GetSelection());
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSize( wxSizeEvent& e )
//-----------------------------------------------------------------------------
{
	RefreshDisplays( false );
	for( unsigned int i=0; i<iapLAST; i++ )
	{
		if( m_ImageAnalysisPlots[i].m_pPlotCanvas )
		{
			m_ImageAnalysisPlots[i].m_pPlotCanvas->Refresh( false );
		}
	}
	e.Skip();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSLRecordDisplay( wxScrollEvent& e )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );

	if( pThread )
	{
		SetupUpdateFrequencies( false );
		pThread->DisplaySequenceRequest( static_cast<size_t>(e.GetPosition()) );
		WriteLogMessage( wxString::Format( wxT("Recorded image %lu: "), static_cast<unsigned long int>(e.GetPosition()) ) );
		m_boCurrentImageIsFromFile = false;
		UpdateData( true, true );
	}
	SetupDlgControls();
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnUpdateDeviceList( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	SetCursor( *wxHOURGLASS_CURSOR );
	WriteLogMessage( wxT("Updating device list...\n") );
	m_pDevPropHandler->GetDevMgr().updateDeviceList();
	WriteLogMessage( wxT("Done.\n") );
	SetCursor( wxNullCursor );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnUserExperienceComboTextChanged( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	UpdateUserExperience( m_pUserExperienceCombo->GetValue() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnSplitterSashPosChanged( wxSplitterEvent& )
//-----------------------------------------------------------------------------
{
	UpdatePropGridSplitter();
	RefreshDisplays( true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnToggleDisplayWindowSize( wxCommandEvent& )
//-----------------------------------------------------------------------------
{
	if( !m_pHorizontalSplitter->IsSplit() && !m_pVerticalSplitter->IsSplit() )
	{
		// if all hideable windows are hidden already restore them
		m_boDisplayWindowMaximized = false;
	}
	else
	{
		// else toggle current status
		m_boDisplayWindowMaximized = !m_boDisplayWindowMaximized;
	}

	m_pMISettings_PropGrid_Show->Check( !m_boDisplayWindowMaximized );
	m_pMISettings_Analysis_ShowControls->Check( !m_boDisplayWindowMaximized );
	GetToolBar()->ToggleTool( miSettings_Analysis_ShowControls, !m_boDisplayWindowMaximized );
	GetToolBar()->ToggleTool( miSettings_PropGrid_Show, !m_boDisplayWindowMaximized );
	SetupDisplayLogSplitter( !m_boDisplayWindowMaximized );
	SetupVerSplitter( !m_boDisplayWindowMaximized );
	const DisplayWindowContainer::size_type displayCount = m_pDisplayAreas.size();
	for( DisplayWindowContainer::size_type i=0; i<displayCount; i++ )
	{
		m_pDisplayAreas[i]->RefreshScrollbars();
	}
	RefreshDisplays( true );
}

//-----------------------------------------------------------------------------
void PropViewFrame::OnToggleFullScreenMode( wxCommandEvent& e )
//-----------------------------------------------------------------------------
{
	ShowFullScreen( e.IsChecked() );
}

//-----------------------------------------------------------------------------
mvIMPACT::acquire::TImageBufferPixelFormat PropViewFrame::PixelFormatFromString( const wxString& value )
//-----------------------------------------------------------------------------
{
	if( value == wxT("Mono8") )
	{
		return ibpfMono8;
	}
	else if( value == wxT("Mono10") )
	{
		return ibpfMono10;
	}
	else if( value == wxT("Mono12") )
	{
		return ibpfMono12;
	}
	else if( value == wxT("Mono12Packed_V2") )
	{
		return ibpfMono12Packed_V2;
	}
	else if( value == wxT("Mono14") )
	{
		return ibpfMono14;
	}
	else if( value == wxT("Mono16") )
	{
		return ibpfMono16;
	}
	else if( value == wxT("BGR888Packed") )
	{
		return ibpfBGR888Packed;
	}
	else if( value == wxT("BGR101010Packed_V2") )
	{
		return ibpfBGR101010Packed_V2;
	}
	else if( value == wxT("RGB888Packed") )
	{
		return ibpfRGB888Packed;
	}
	else if( value == wxT("RGB101010Packed") )
	{
		return ibpfRGB101010Packed;
	}
	else if( value == wxT("RGB121212Packed") )
	{
		return ibpfRGB121212Packed;
	}
	else if( value == wxT("RGB141414Packed") )
	{
		return ibpfRGB141414Packed;
	}
	else if( value == wxT("RGB161616Packed") )
	{
		return ibpfRGB161616Packed;
	}
	else if( value == wxT("RGBx888Packed") )
	{
		return ibpfRGBx888Packed;
	}
	else if( value == wxT("RGBx888Planar") )
	{
		return ibpfRGBx888Planar;
	}
	else if( value == wxT("YUV422Packed") )
	{
		return ibpfYUV422Packed;
	}
	else if( value == wxT("YUV422_UYVYPacked") )
	{
		return ibpfYUV422_UYVYPacked;
	}
	else if( value == wxT("YUV422_10Packed") )
	{
		return ibpfYUV422_10Packed;
	}
	else if( value == wxT("YUV422_UYVY_10Packed") )
	{
		return ibpfYUV422_UYVY_10Packed;
	}
	else if( value == wxT("YUV444_UYVPacked") )
	{
		return ibpfYUV444_UYVPacked;
	}
	else if( value == wxT("YUV444_UYV_10Packed") )
	{
		return ibpfYUV444_UYV_10Packed;
	}
	else if( value == wxT("YUV444Packed") )
	{
		return ibpfYUV444Packed;
	}
	else if( value == wxT("YUV444_10Packed") )
	{
		return ibpfYUV444_10Packed;
	}
	else if( value == wxT("YUV422Planar") )
	{
		return ibpfYUV422Planar;
	}

	WriteErrorMessage( wxString::Format( wxT("Unsupported pixel format(%s).\n"), value.c_str() ) );
	return ibpfMono8;
}

//-----------------------------------------------------------------------------
void PropViewFrame::RefreshCurrentPixelData( void )
//-----------------------------------------------------------------------------
{
	if( ( m_pStatusBar->GetFieldsCount() != NO_OF_STATUSBAR_FIELDS ) || m_boShutdownInProgress || m_boImageCanvasInFullScreenMode )
	{
		return;
	}

	double scale = 0.;
	wxPoint pixel;
	m_pLastMouseHooverDisplay->GetCurrentPixel( &scale, &pixel );
	const ImageBuffer* pIB = m_pLastMouseHooverDisplay->GetImage();
	wxString pixelInfo;

	if( pIB && pIB->vpData && ( scale > 0. ) )
	{
		if( ( pixel.x < 0 ) || ( pixel.x >= pIB->iWidth ) || ( pIB->iWidth < 1 ) )
		{
			pixel.x = -1;
		}

		if( ( pixel.y < 0 ) || ( pixel.y >= pIB->iHeight ) || ( pIB->iHeight < 1 ) )
		{
			pixel.y = -1;
		}

		pixelInfo.append( wxString::Format(wxT("(%d, %d): "), pixel.x, pixel.y ) );

		if( ( pixel.x >= 0 ) && ( pixel.y >= 0 ) )
		{
			switch( pIB->pixelFormat )
			{
			case ibpfMono10:
			case ibpfMono12:
			case ibpfMono14:
			case ibpfMono16:
				{
					unsigned short* p = reinterpret_cast<unsigned short*>(reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch )) + pixel.x;
					pixelInfo.append( wxString::Format( wxT("%d"), *p ) );
				}
				break;
			case ibpfMono12Packed_V2:
				pixelInfo.append( wxString::Format( wxT("%d"), ImageAnalysisPlotCanvas::GetMonoPacked_V2Pixel( static_cast<unsigned char*>(pIB->vpData), ( pixel.y * pIB->iWidth ) + pixel.x, 4 ) ) );
				break;
			case ibpfRGB101010Packed:
			case ibpfRGB121212Packed:
			case ibpfRGB141414Packed:
			case ibpfRGB161616Packed:
				{
					unsigned short* p = reinterpret_cast<unsigned short*>(reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch ) + ( pixel.x * pIB->iBytesPerPixel ));
					pixelInfo.append( wxString::Format( wxT("%d(R), %d(G), %d(B)"), p[2], p[1], p[0] ) );
				}
				break;
			case ibpfBGR888Packed:
				{
					unsigned char* p = reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch ) + ( pixel.x * pIB->iBytesPerPixel );
					pixelInfo.append( wxString::Format( wxT("%d(R), %d(G), %d(B)"), p[0], p[1], p[2] ) );
				}
				break;
			case ibpfBGR101010Packed_V2:
				{
					unsigned short red, green, blue;
					unsigned int* p = reinterpret_cast<unsigned int*>(reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch )) + pixel.x;
					ImageAnalysisPlotCanvas::GetBGR101010Packed_V2Pixel( *p, red, green, blue );
					pixelInfo.append( wxString::Format( wxT("%d(R), %d(G), %d(B)"), red, green, blue ) );
				}
				break;
			case ibpfRGBx888Packed:
			case ibpfRGB888Packed:
				{
					unsigned char* p = reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch ) + ( pixel.x * pIB->iBytesPerPixel );
					pixelInfo.append( wxString::Format( wxT("%d(R), %d(G), %d(B)"), p[2], p[1], p[0] ) );
				}
				break;
			case ibpfRGBx888Planar:
				{
					unsigned char* r = reinterpret_cast<unsigned char*>(pIB->vpData) + pIB->pChannels[0].iChannelOffset + ( pixel.y * pIB->pChannels[0].iLinePitch ) + pixel.x;
					unsigned char* g = reinterpret_cast<unsigned char*>(pIB->vpData) + pIB->pChannels[1].iChannelOffset + ( pixel.y * pIB->pChannels[1].iLinePitch ) + pixel.x;
					unsigned char* b = reinterpret_cast<unsigned char*>(pIB->vpData) + pIB->pChannels[2].iChannelOffset + ( pixel.y * pIB->pChannels[2].iLinePitch ) + pixel.x;
					pixelInfo.append( wxString::Format( wxT("%d(R), %d(G), %d(B)"), *r, *g, *b ) );
				}
				break;
			case ibpfMono8:
				{
					unsigned char* p = reinterpret_cast<unsigned char*>(pIB->vpData) + ( pixel.y * pIB->pChannels[0].iLinePitch ) + pixel.x;
					pixelInfo.append( wxString::Format( wxT("%d"), *p ) );
				}
				break;
			case ibpfYUV422Packed:
				AppendYUVDataPixelInfo<unsigned char>( pixel, pixelInfo, pIB );
				break;
			case ibpfYUV422_10Packed:
				AppendYUVDataPixelInfo<unsigned short>( pixel, pixelInfo, pIB );
				break;
			case ibpfYUV422_UYVYPacked:
				AppendUYVDataPixelInfo<unsigned char>( pixel, pixelInfo, pIB );
				break;
			case ibpfYUV422_UYVY_10Packed:
				AppendUYVDataPixelInfo<unsigned short>( pixel, pixelInfo, pIB );
				break;
			case ibpfYUV444_UYVPacked:
				{
					const int order[3] = { 1, 0, 2 };
					AppendYUV444DataPixelInfo<unsigned char>( pixel, pixelInfo, pIB, order );
				}
				break;
			case ibpfYUV444_UYV_10Packed:
				{
					const int order[3] = { 1, 0, 2 };
					AppendYUV444DataPixelInfo<unsigned short>( pixel, pixelInfo, pIB, order );
				}
				break;
			case ibpfYUV444Packed:
				{
					const int order[3] = { 0, 1, 2 };
					AppendYUV444DataPixelInfo<unsigned char>( pixel, pixelInfo, pIB, order );
				}
				break;
			case ibpfYUV444_10Packed:
				{
					const int order[3] = { 0, 1, 2 };
					AppendYUV444DataPixelInfo<unsigned short>( pixel, pixelInfo, pIB, order );
				}
				break;
			case ibpfYUV422Planar:
				{
					unsigned char* y = reinterpret_cast<unsigned char*>(pIB->vpData) + pIB->pChannels[0].iChannelOffset + ( pixel.y * pIB->pChannels[0].iLinePitch ) + pixel.x;
					unsigned char* u = reinterpret_cast<unsigned char*>(pIB->vpData) + pIB->pChannels[1].iChannelOffset + ( pixel.y * pIB->pChannels[1].iLinePitch ) + pixel.x / 2;
					unsigned char* v = reinterpret_cast<unsigned char*>(pIB->vpData) + pIB->pChannels[2].iChannelOffset + ( pixel.y * pIB->pChannels[2].iLinePitch ) + pixel.x / 2;
					pixelInfo.append( wxString::Format( wxT("%d(Y), %d(U), %d(V)"), *y, *u, *v ) );
				}
				break;
			default:
				pixelInfo.append( wxT("Unsupported format") );
				break;
			}
		}
		else
		{
			pixelInfo.append( wxT("-") );
		}
	}
	else
	{
		pixelInfo = wxString(wxT("-"));
	}

	m_pStatusBar->SetStatusText( pixelInfo, sbfPixelData );
}

//-----------------------------------------------------------------------------
template<class _Ty>
void PropViewFrame::RegisterAnalysisPlot( int index, wxWindowID id, wxWindowID gridID, const wxColour& AOIColour )
//-----------------------------------------------------------------------------
{
	m_ImageAnalysisPlots[index].m_pPlotCanvas = new _Ty( m_ImageAnalysisPlots[index].m_pNBDisplayMethod, id, wxDefaultPosition, wxDefaultSize );
	m_ImageAnalysisPlots[index].m_pPlotCanvas->SetAOIColour( AOIColour );
	m_ImageAnalysisPlots[index].m_pPlotCanvas->CreateGrid( m_ImageAnalysisPlots[index].m_pNBDisplayMethod, gridID );
	m_ImageAnalysisPlots[index].m_pNBDisplayMethod->AddPage( m_ImageAnalysisPlots[index].m_pPlotCanvas->GetGrid(), wxT("Numerical") );
}

//-----------------------------------------------------------------------------
void PropViewFrame::SearchAndSelectImageCanvas( ImageCanvas* pImageCanvas )
//-----------------------------------------------------------------------------
{
	int index = 0;
	const DisplayWindowContainer::size_type displayCount = m_pDisplayAreas.size();
	for( DisplayWindowContainer::size_type i=0; i<displayCount; i++ )
	{
		if( pImageCanvas == m_pDisplayAreas[i] )
		{
			index = i;
			break;
		}
	}
	SelectImageCanvas( index );
}

//-----------------------------------------------------------------------------
bool PropViewFrame::SetCurrentImage( const wxFileName& fileName, ImageCanvas* pImageCanvas )
//-----------------------------------------------------------------------------
{
	if( fileName.GetFullPath().IsEmpty() )
	{
		return false;
	}

	if( fileName.GetExt().CmpNoCase( wxT("raw") ) == 0 )
	{
		wxFile file(fileName.GetFullPath().c_str(), wxFile::read);
		if( !file.IsOpened() )
		{
			WriteErrorMessage( wxString::Format( wxT("Failed to open file %s.\n"), fileName.GetFullPath().c_str() ) );
			return false;
		}

		RawImageImportDlg dlg(this, wxT("Raw Image Import"), fileName);
		if( dlg.ShowModal() != wxID_OK )
		{
			WriteLogMessage( wxString::Format( wxT("Import of file %s canceled.\n"), fileName.GetFullPath().c_str() ) );
		}

		if( dlg.GetFormat().IsEmpty() || dlg.GetBayerParity().IsEmpty() )
		{
			WriteErrorMessage( wxT("Invalid selection.\n") );
			return false;
		}

		SearchAndSelectImageCanvas( pImageCanvas );
		m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_ = mvIMPACT::acquire::ImageBufferDesc(PixelFormatFromString( dlg.GetPixelFormat() ) , dlg.GetWidth(), dlg.GetHeight());
		m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].pixelFormat_ = dlg.GetFormat();
		m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].bayerParity_ = BayerParityFromString( dlg.GetBayerParity() );;
		const size_t imageSize = m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iSize;
		const size_t toRead = ( static_cast<size_t>(file.Length()) < imageSize ) ? static_cast<size_t>(file.Length()) : imageSize;
		file.Read( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->vpData, toRead );
	}
	else
	{
		wxImage image;
		bool boLoadedSuccessfully = image.LoadFile( fileName.GetFullPath() );
		if( !boLoadedSuccessfully )
		{
			WriteErrorMessage( wxString::Format( wxT("Failed to load file %s.\n"), fileName.GetFullPath().c_str() ) );
			return false;
		}

		SearchAndSelectImageCanvas( pImageCanvas );
		int inc = ( image.HasAlpha() ) ? 4 : 3;
		m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_ = mvIMPACT::acquire::ImageBufferDesc(ibpfRGB888Packed, image.GetWidth(), image.GetHeight());
		m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].pixelFormat_ = wxString(wxT("RGB888Packed"));
		m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].bayerParity_ = bmpUndefined;
		const int PIXEL_COUNT = m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iWidth * m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iHeight;
		unsigned char* pDst = static_cast<unsigned char*>(m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->vpData);
		unsigned char* pSrc = image.GetData();
		for( int i=0; i<PIXEL_COUNT; i++ )
		{
			*pDst++ = pSrc[2];
			*pDst++ = pSrc[1];
			*pDst++ = pSrc[0];
			pSrc += inc;
		}
	}
	m_boCurrentImageIsFromFile = true;
	UpdateData();
	return true;
}

//-----------------------------------------------------------------------------
void PropViewFrame::SetupDlgControls( void )
//-----------------------------------------------------------------------------
{
	CaptureThread* pThread = 0;
	const Device* pDev = m_pDevPropHandler->GetActiveDevice( 0, 0, &pThread );
	bool boDevOpen = false;
	bool boDevPresent = false;
	bool boDevLive = false;
	bool boSequenceBegin = true;
	bool boSequenceEnd = true;
	bool boDevRecord = false;
	RequestContainer::size_type recordedSequenceLength = 0;
	if( pDev )
	{
		boDevOpen = pDev->isOpen();
		boDevPresent = ( pDev->state.read() == dsPresent );
		if( pThread )
		{
			boDevRecord = pThread->GetRecordMode();
			boDevLive = pThread->GetLiveMode();
			pThread->SetCaptureMode( m_pMISettings_Display_ShowIncompleteFrames->IsChecked() );
			recordedSequenceLength = pThread->GetRecordedSequence().size();
			if( recordedSequenceLength > 1 )
			{
				boSequenceBegin = pThread->GetCurrentSequenceIndex() == 0;
				boSequenceEnd = pThread->GetCurrentSequenceIndex() == recordedSequenceLength - 1;
			}
		}
	}

	const DeviceManager& devMgr = m_pDevPropHandler->GetDevMgr();
	if( m_DeviceListChangedCounter != devMgr.changedCount() )
	{
		UpdateDeviceComboBox();
	}

	if( m_DeviceCount != devMgr.deviceCount() )
	{
		UpdateDeviceInterfaceLayouts();
	}

	bool isDeviceSelected = m_pDevCombo->GetValue() != m_NoDevStr;
	m_pMIAction_Use->Enable( isDeviceSelected );
	m_pMIAction_Use->Check( boDevOpen );
	m_pMICapture_Record->Check( boDevRecord );

	m_pMIAction_Settings_Save_ToDefault->Enable( boDevOpen );
	m_pMIAction_Settings_Save_SystemToDefault->Enable( boDevOpen );
	m_pMIAction_Settings_Save_CurrentProduct->Enable( boDevOpen );
	m_pMIAction_Settings_Save_ActiveDevice->Enable( boDevOpen );
	m_pMIAction_Settings_Save_ExportActiveDevice->Enable( boDevOpen );
	m_pMIAction_Settings_Load_FromDefault->Enable( boDevOpen );
	m_pMIAction_Settings_Load_CurrentProduct->Enable( boDevOpen );
	m_pMIAction_Settings_Load_ActiveDevice->Enable( boDevOpen );
	m_pMIAction_Settings_Load_ImportActiveDevice->Enable( boDevOpen );
	m_pMIAction_Settings_Manage->Enable( isDeviceSelected && pDev && pDev->autoLoadSettingOrder.isValid() );
	m_pMIAction_LoadImage->Enable( !boDevLive );
	m_pMIAction_SaveImage->Enable( boDevOpen && !boDevLive );
	m_pMIAction_SaveImageSequenceToFiles->Enable( boDevOpen && !boDevLive && ( !boSequenceEnd || !boSequenceBegin ) );
	m_pMIAction_SaveImageSequenceToStream->Enable( boDevOpen && !boDevLive && ( !boSequenceEnd || !boSequenceBegin ) );
	m_pMICapture_Live->Enable( boDevOpen && boDevPresent );
	m_pMICapture_Live->Check( boDevLive );
	m_pMICapture_Snap->Enable( boDevOpen && boDevPresent && !boDevLive );
	m_pMICapture_Abort->Enable( boDevOpen && boDevPresent );
	m_pMICapture_Record->Enable( boDevOpen && boDevPresent && !boDevLive );
	m_pMICapture_Forward->Enable( boDevOpen && boDevPresent && !boDevLive && !boSequenceEnd );
	m_pMICapture_Backward->Enable( boDevOpen && boDevPresent && !boDevLive && !boSequenceBegin );
	m_pMICapture_SetupCaptureQueueDepth->Enable( boDevOpen && !boDevLive );
	m_pMICapture_Recording_Continuous->Enable( boDevOpen );
	m_pMICapture_Recording_SlientMode->Enable( boDevOpen && !boDevLive );
	m_pMICapture_Recording_SetupSequenceSize->Enable( boDevOpen && !boDevLive );
	m_pRecordDisplaySlider->Enable( boDevOpen && boDevPresent && !boDevLive && ( recordedSequenceLength > 0 ) );
	if( m_pRecordDisplaySlider->IsEnabled() )
	{
		if( static_cast<size_t>(m_pRecordDisplaySlider->GetMax()) != recordedSequenceLength - 1 )
		{
			m_pRecordDisplaySlider->SetRange( 0, recordedSequenceLength - 1 );
		}
	}

	m_pToolBar->EnableTool( miAction_UseDevice, isDeviceSelected );
	m_pToolBar->ToggleTool( miAction_UseDevice, boDevOpen );
	m_pToolBar->EnableTool( miCapture_Abort, m_pMICapture_Abort->IsEnabled() );
	m_pToolBar->EnableTool( miCapture_Live, m_pMICapture_Live->IsEnabled() );
	m_pToolBar->ToggleTool( miCapture_Live, boDevLive );
	m_pToolBar->EnableTool( miCapture_Snap, m_pMICapture_Snap->IsEnabled() );
	m_pToolBar->EnableTool( miCapture_Record, m_pMICapture_Record->IsEnabled() );
	m_pToolBar->ToggleTool( miCapture_Record, boDevRecord );
	m_pToolBar->EnableTool( miCapture_Forward, m_pMICapture_Forward->IsEnabled() );
	m_pToolBar->EnableTool( miCapture_Backward, m_pMICapture_Backward->IsEnabled() );
	m_pToolBar->EnableTool( miSettings_Display_ShowMonitorImage, m_pMISettings_Display_Active->IsChecked() );

	m_pMICapture_CaptureSettings_CreateCaptureSetting->Enable( boDevOpen );
	m_pMICapture_CaptureSettings_CaptureSettingHierarchy->Enable( boDevOpen );
	m_pMICapture_CaptureSettings_AssignToDisplays->Enable( boDevOpen );
	m_pMICapture_CaptureSettings_UsageMode_Manual->Enable( boDevOpen && !boDevLive );
	m_pMICapture_CaptureSettings_UsageMode_Automatic->Enable( boDevOpen && !boDevLive );
}

//-----------------------------------------------------------------------------
void PropViewFrame::SetupDisplayLogSplitter( bool boForceSplit /* = false */ )
//-----------------------------------------------------------------------------
{
	if( ( m_pMISettings_Display_Active->IsChecked() && m_pMISettings_Analysis_ShowControls->IsChecked() ) || boForceSplit )
	{
		m_pHorizontalSplitter->SplitHorizontally( m_pDisplayPanel, m_pLowerRightWindow, 0 );
		m_pHorizontalSplitter->SetSashPosition( m_HorizontalSplitterPos );
		ConfigureAnalysisPlot();
	}
	else
	{
		m_HorizontalSplitterPos = m_pHorizontalSplitter->GetSashPosition();
		if( m_pMISettings_Analysis_ShowControls->IsChecked() )
		{
			ConfigureSplitter( m_pHorizontalSplitter, m_pDisplayPanel, m_pLowerRightWindow );
			ConfigureAnalysisPlot();
		}
		else
		{
			ConfigureSplitter( m_pHorizontalSplitter, m_pLowerRightWindow, m_pDisplayPanel );
			DeselectAnalysisPlot();
		}
	}
	UpdateData();
}

//-----------------------------------------------------------------------------
void PropViewFrame::SetupUpdateFrequencies( bool boCurrentValue )
//-----------------------------------------------------------------------------
{
	for( unsigned int i=0; i<iapLAST; i++ )
	{
		if( m_ImageAnalysisPlots[i].m_pPlotCanvas )
		{
			m_ImageAnalysisPlots[i].m_pPlotCanvas->SetUpdateFrequency( ( boCurrentValue ) ? m_ImageAnalysisPlots[i].m_pSCUpdateSpeed->GetValue() : 1 );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::SetupVerSplitter( bool boSplit )
//-----------------------------------------------------------------------------
{
	if( boSplit )
	{
		m_pVerticalSplitter->SplitVertically( m_pSettingsPanel, m_pHorizontalSplitter, 0 );
		m_pVerticalSplitter->SetSashPosition( m_VerticalSplitterPos );
	}
	else if( m_pVerticalSplitter->IsSplit() )
	{
		m_VerticalSplitterPos = m_pVerticalSplitter->GetSashPosition();
		m_pVerticalSplitter->Unsplit( m_pSettingsPanel );
	}
	else
	{
		m_pVerticalSplitter->Initialize( m_pHorizontalSplitter );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateData( bool boShowInfo /* = false */, bool boForceUnlock /* = false */ )
//-----------------------------------------------------------------------------
{
	// To prevent a crash when the handler OnImageReady() is called and m_pDevPropHandler is already deleted.
	if( !m_pDevPropHandler )
	{
		return;
	}

	TImageBufferPixelFormat lastPixelFormat = m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->pixelFormat;
	vector<wxString> requestInfoStrings;
	Device* pDev = 0;
	CaptureThread* pCT = 0;
	RequestData data;
	int lastRequestNr = INVALID_ID;
	int index = 0;

	pDev = m_pDevPropHandler->GetActiveDevice( 0, 0, &pCT );
	if( !m_boCurrentImageIsFromFile && boForceUnlock )
	{
		if( pCT && pDev && !m_boCloseDeviceInProgress && pDev->isOpen() )
		{
			pCT->GetImageData( data );
		}
	}
	else
	{
		lastRequestNr = m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].requestNr_;
		index = m_CurrentRequestDataIndex;
	}

	if( data.requestNr_ != INVALID_ID )
	{
		wxCriticalSectionLocker locker(m_CritSect);
		SettingToDisplayDict::const_iterator it = m_settingToDisplayDict.find( data.requestInfo_.settingUsed );
		index = ( it != m_settingToDisplayDict.end() ) ? it->second : 0;
		lastRequestNr = m_CurrentRequestDataContainer[index].requestNr_;
		lastPixelFormat = m_CurrentRequestDataContainer[index].image_.getBuffer()->pixelFormat;
		m_CurrentRequestDataContainer[index] = data;
	}

	if( !m_boCurrentImageIsFromFile )
	{
		if( m_pDisplayAreas[index]->InfoOverlayActive() || boShowInfo )
		{
			if( pCT && pDev && !m_boCloseDeviceInProgress && pDev->isOpen() )
			{
				pCT->GetImageInfo( true, requestInfoStrings );
				if( boShowInfo )
				{
					wxString msg;
					vector<wxString>::size_type vSize = requestInfoStrings.size();
					for( vector<wxString>::size_type i=0; i<vSize; i++ )
					{
						msg.append( requestInfoStrings[i] );
						msg.append( ( i < vSize - 1 ) ? wxT(", ") : wxT("\n") );
					}
					WriteLogMessage( msg );
				}
			}
			if( m_pDisplayAreas[index]->InfoOverlayActive() )
			{
				m_pDisplayAreas[index]->SetInfoOverlay( requestInfoStrings );
			}
		}
	}

	ImageBuffer* p = m_CurrentRequestDataContainer[index].image_.getBuffer();
	if( !m_boImageCanvasInFullScreenMode && ( m_pDisplayAreas[index]->GetMonitorDisplay() == m_pMonitorImage->GetDisplayArea() ) )
	{
		m_pMonitorImage->GetDisplayArea()->SetImage( p );
	}
	if( !m_boImageCanvasInFullScreenMode || m_pDisplayAreas[index]->IsFullScreen() )
	{
		if( !m_pDisplayAreas[index]->SetImage( p ) && ( lastPixelFormat != p->pixelFormat ) )
		{
			WriteErrorMessage( wxString::Format( wxT("%s: ERROR!!! Don't know how to display format %s.\n"), ConvertedString(__FUNCTION__).c_str(), m_CurrentRequestDataContainer[index].pixelFormat_.c_str() ) );
		}
	}
	if( p && p->vpData )
	{
#ifdef BUILD_WITH_PLUGIN_SUPPORT
		m_pluginManager.forwardImage( p );
#endif // #ifdef BUILD_WITH_PLUGIN_SUPPORT
		if( m_harddiscRecordingParameters.boActive_ )
		{
			wxFileName filename(m_harddiscRecordingParameters.targetDirectory_, wxString::Format( wxT("IMG%010d"), m_CurrentRequestDataContainer[index].requestInfo_.frameNr ));
			SaveImage( filename.GetFullPath(), m_harddiscRecordingParameters.fileFormat_ );
		}
		if( !m_boImageCanvasInFullScreenMode && ( m_CurrentImageAnalysisControlIndex >= 0 ) && ( index == m_CurrentRequestDataIndex ) )
		{
			ConfigureAOIControlLimits( m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex] );
			m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[index],
				m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIx->GetValue(),
				m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIy->GetValue(),
				m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIw->GetValue(),
				m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIh->GetValue() );
		}
		if( lastPixelFormat != p->pixelFormat )
		{
			switch( p->pixelFormat )
			{
			case ibpfMono10:
			case ibpfMono12:
			case ibpfMono12Packed_V2:
			case ibpfMono14:
			case ibpfMono16:
			case ibpfBGR888Packed:
			case ibpfBGR101010Packed_V2:
			case ibpfRGB101010Packed:
			case ibpfRGB121212Packed:
			case ibpfRGB141414Packed:
			case ibpfRGB161616Packed:
			case ibpfRGBx888Planar:
			case ibpfYUV422Packed:
			case ibpfYUV422_10Packed:
			case ibpfYUV422_UYVYPacked:
			case ibpfYUV422_UYVY_10Packed:
			case ibpfYUV444_UYVPacked:
			case ibpfYUV444_UYV_10Packed:
			case ibpfYUV444Packed:
			case ibpfYUV444_10Packed:
			case ibpfYUV422Planar:
				WriteLogMessage( wxString::Format( wxT("%s: Please note that pixel format %s will require additional CPU time as it needs to be converted for displaying.\n"), ConvertedString(__FUNCTION__).c_str(), m_CurrentRequestDataContainer[index].pixelFormat_.c_str() ) );
				break;
			default:
				break;
			}
		}
	}

	if( pCT && ( lastRequestNr != INVALID_ID ) &&
		( ( lastRequestNr != m_CurrentRequestDataContainer[index].requestNr_ ) || m_boCurrentImageIsFromFile || boForceUnlock ) )
	{
		pCT->UnlockRequest( lastRequestNr );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateDeviceComboBox( void )
//-----------------------------------------------------------------------------
{
	const DeviceManager& devMgr = m_pDevPropHandler->GetDevMgr();
	bool boDisplayConnectedOnly = m_pMISettings_ShowConnectedOnly->IsChecked();
	int oldIndex = m_pDevCombo->GetSelection();
	wxString oldSelection = ( oldIndex == wxNOT_FOUND ) ? m_NoDevStr : m_pDevCombo->GetString( oldIndex );
	// delete all entries
	m_pDevCombo->Clear();
	// refill the combo box with up to date data
	const unsigned int devCnt = devMgr.deviceCount();
	if( devCnt > 0 )
	{
		for( unsigned int i=0; i<devCnt; i++ )
		{
			if( !boDisplayConnectedOnly || ( devMgr[i]->state.read() == dsPresent ) )
			{
				m_pDevCombo->Append( wxString::Format( wxT("%s (%s)"), ConvertedString(devMgr[i]->serial.read()).c_str(), ConvertedString(devMgr[i]->product.read()).c_str() ) );
			}
		}
		if( m_pDevCombo->IsEmpty() )
		{
			m_pDevCombo->Append( m_NoDevStr );
		}
		if( oldSelection == m_NoDevStr )
		{
			m_pDevCombo->Select( 0 );
		}
		else
		{
			int selection = m_pDevCombo->FindString( oldSelection );
			m_pDevCombo->Select( ( selection == wxNOT_FOUND ) ? 0 : selection );
		}
	}
	else
	{
		m_pDevCombo->Append( m_NoDevStr );
		m_pDevCombo->Select( 0 );
	}

	m_DeviceListChangedCounter = devMgr.changedCount();
	if( m_pDevCombo->GetString( 0 ) != m_NoDevStr )
	{
		m_pDevPropHandler->SetActiveDevice( GetSelectedDeviceSerial() );
	}
	UpdateTitle();
	UpdateData();
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateDeviceFromComboBox( void )
//-----------------------------------------------------------------------------
{
	{
		wxCriticalSectionLocker locker(m_CritSect);
		m_settingToDisplayDict.clear();
	}
	m_pDevPropHandler->SetActiveDevice( GetSelectedDeviceSerial() );
	UpdateTitle();
	UpdateData();

	const DisplayWindowContainer::size_type displayCnt = m_pDisplayAreas.size();
	for( DisplayWindowContainer::size_type i=0; i<displayCnt; i++ )
	{
		m_pDisplayAreas[i]->SetImage( m_CurrentRequestDataContainer[i].image_.getBuffer() );
	}

	ImageBuffer* p = m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer();
	m_pMonitorImage->GetDisplayArea()->SetImage( p );
	if( p && p->vpData )
	{
#ifdef BUILD_WITH_PLUGIN_SUPPORT
		m_pluginManager.forwardImage( p );
#endif // #ifdef BUILD_WITH_PLUGIN_SUPPORT
		if( m_CurrentImageAnalysisControlIndex >= 0 )
		{
			ConfigureAOIControlLimits( m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex] );
			m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pPlotCanvas->RefreshData( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex],
				m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIx->GetValue(),
				m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIy->GetValue(),
				m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIw->GetValue(),
				m_ImageAnalysisPlots[m_CurrentImageAnalysisControlIndex].m_pSCAOIh->GetValue() );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateDeviceInterfaceLayouts( void )
//-----------------------------------------------------------------------------
{
	const DeviceManager& devMgr = m_pDevPropHandler->GetDevMgr();
	m_DeviceCount = devMgr.deviceCount();
	for( unsigned int i=0; i<m_DeviceCount; i++ )
	{
		try
		{
			if( devMgr[i]->interfaceLayout.isValid() &&
				devMgr[i]->interfaceLayout.isWriteable() &&
				( devMgr[i]->interfaceLayout.read() != m_defaultDeviceInterfaceLayout ) )
			{
				std::vector<std::pair<std::string, TDeviceInterfaceLayout> > dict;
				devMgr[i]->interfaceLayout.getTranslationDict( dict );
				std::vector<std::pair<std::string, TDeviceInterfaceLayout> >::const_iterator it = find_if( dict.begin(), dict.end(), SecondMatches<const string, TDeviceInterfaceLayout>(make_pair( "", m_defaultDeviceInterfaceLayout )) );
				if( it != dict.end() )
				{
					devMgr[i]->interfaceLayout.write( m_defaultDeviceInterfaceLayout );
					WriteLogMessage( wxString::Format( wxT("Interface layout of device %d (%s) switched to '%s'.\n"), i, ConvertedString(devMgr[i]->serial.read()).c_str(), ConvertedString(devMgr[i]->interfaceLayout.readS()).c_str() ) );
				}
			}
		}
		catch( const ImpactAcquireException& )
		{
			WriteErrorMessage( wxString::Format( wxT("Failed to update interface layout of device %d (%s).\n"), i, ConvertedString(devMgr[i]->serial.read()).c_str() ) );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdatePropGridSplitter( void )
//-----------------------------------------------------------------------------
{
	double ratio = GetPropertyGrid()->GetSplitterRatio();
	if( ratio != -1 )
	{
		m_pVerticalSplitter->UpdateSize();
		wxRect rect = GetPropertyGrid()->GetRect();
		GetPropertyGrid()->SetSplitterPosition( (int)( rect.GetWidth()* ratio ), true );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdatePropGridViewMode( void )
//-----------------------------------------------------------------------------
{
	m_pDevPropHandler->SetViewMode( m_ViewMode,
		m_pMISettings_PropGrid_DisplayPropIndicesAsHex->IsChecked(),
		m_pMISettings_PropGrid_UseDisplayNameIfAvailable->IsChecked(),
		m_pMISettings_PropGrid_UseSelectorGrouping->IsChecked() );
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateSettingTable( void )
//-----------------------------------------------------------------------------
{
	CaptureThread* pCT = 0;
	Device* pDev = m_pDevPropHandler->GetActiveDevice( 0, 0, &pCT );
	if( pDev && pCT )
	{
		pCT->UpdateSettingTable();
		ImageRequestControl irc(pDev);
		vector<pair<string, int> > settings;
		irc.setting.getTranslationDict( settings );
		if( m_pInfoPlotArea )
		{
			m_pInfoPlotArea->SetupPlotIdentifiers( settings );
		}
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateStatusBar( void )
//-----------------------------------------------------------------------------
{
	const Statistics* pS = 0;
	FunctionInterface* pFI = 0;
	CaptureThread* pCT = 0;
	m_pDevPropHandler->GetActiveDevice( &pFI, &pS, &pCT );
	bool boValidDevice = pFI && pS && pCT;
	bool boValidImage = m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer() && m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->vpData;
	if( boValidDevice || boValidImage )
	{
		if( m_pStatusBar->GetFieldsCount() != NO_OF_STATUSBAR_FIELDS )
		{
			int statusBarFieldWidths[NO_OF_STATUSBAR_FIELDS];
			statusBarFieldWidths[sbfFPS] = -1;
			statusBarFieldWidths[sbfFrameCount] = -1;
			statusBarFieldWidths[sbfImageFormat] = -3;
			statusBarFieldWidths[sbfErrorCount] = -1;
			statusBarFieldWidths[sbfExposeTime] = -1;
			statusBarFieldWidths[sbfGain] = -1;
			statusBarFieldWidths[sbfPixelData] = -2;
			m_pStatusBar->SetFieldsCount( NO_OF_STATUSBAR_FIELDS, &statusBarFieldWidths[0] );
		}

		bool boSlowDisplay = ( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->pixelFormat != ibpfMono8 ) &&
							 ( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->pixelFormat != ibpfRGBx888Packed ) &&
							 ( m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].pixelFormat_ != RequestData::UNKNOWN_PIXEL_FORMAT_STRING_ );
		if( pS )
		{
			m_pStatusBar->SetStatusText( wxString::Format(wxT("Frames/sec.: %.1f"), pS->framesPerSecond.read() ), sbfFPS );
			m_pStatusBar->SetStatusText( wxString::Format(wxT("Requests: %d"), pS->frameCount.read() ), sbfFrameCount );
			m_pStatusBar->SetStatusText( wxString::Format(wxT("Errors: %d"), pS->errorCount.read() ), sbfErrorCount );
			m_pStatusBar->SetStatusText( wxString::Format(wxT("Exposure(us): %d"), m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].requestInfo_.exposeTime_us ), sbfExposeTime );
			m_pStatusBar->SetStatusText( wxString::Format(wxT("Gain(dB): %.4f"), m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].requestInfo_.gain_dB ), sbfGain );
		}
		else
		{
			m_pStatusBar->SetStatusText( wxT("Frames/sec.: -"), sbfFPS );
			m_pStatusBar->SetStatusText( wxT("Requests: -"), sbfFrameCount );
			m_pStatusBar->SetStatusText( wxT("Errors: -"), sbfErrorCount );
			m_pStatusBar->SetStatusText( wxT("Exposure(us): -"), sbfExposeTime );
			m_pStatusBar->SetStatusText( wxT("Gain(dB): -"), sbfGain );
		}
		wxString imageFormatMsg(wxString::Format( wxT("Image format %dx%d, %s%s (%s)"),
			m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iWidth,
			m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].image_.getBuffer()->iHeight,
			m_CurrentRequestDataContainer[m_CurrentRequestDataIndex].pixelFormat_.c_str(),
			( boSlowDisplay ? wxT("(slow display because of conversion)"): wxT("") ),
			pCT ? pCT->GetLastRequestResult().c_str() : wxT("loaded from disc") ));
		m_pStatusBar->SetStatusText( imageFormatMsg, sbfImageFormat );
		RefreshCurrentPixelData();
	}
	else
	{
		if( m_pStatusBar->GetFieldsCount() != 1 )
		{
			m_pStatusBar->SetFieldsCount( 1, 0 );
		}
		m_pStatusBar->SetStatusText( wxT("no statistics available"), 0 );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateTitle( void )
//-----------------------------------------------------------------------------
{
	wxString title(wxString::Format( wxT("wxPropView(%s) [%s]"), VERSION_STRING, m_pDevCombo->GetValue().c_str() ));
	if( m_pDevPropHandler )
	{
		string serialANSI(GetSelectedDeviceSerial().mb_str());
		Device* p = m_pDevPropHandler->GetDevMgr().getDeviceBySerial( serialANSI );
		if( p && p->isOpen() )
		{
			mvIMPACT::acquire::Info info(p);
			title.append( wxString::Format( wxT("(driver version: %s)"), ConvertedString(info.driverVersion.readS()).c_str() ) );
		}
	}
	SetTitle( title );
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateToolTipWindow( wxPGId prop )
//-----------------------------------------------------------------------------
{
	m_pToolTipWindow->Clear();

	if( !wxPGIdIsOk(prop) )
	{
		return;
	}

	PropData* prop_data = static_cast<PropData*>(wxPGIdToPtr(prop)->GetClientData());
	if( prop_data )
	{
		WriteToTextCtrl( m_pToolTipWindow, wxString::Format( wxT("%s:\n"), (wxPGIdToPtr(prop))->GetLabel().c_str() ), m_boldTextStyle );
		WriteToTextCtrl( m_pToolTipWindow, wxString::Format( wxT("%s "), ConvertedString(prop_data->Component().docString()).c_str() ) );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::UpdateUserExperience( const wxString& userExperience )
//-----------------------------------------------------------------------------
{
	if( userExperience == wxString(ConvertedString(Component::visibilityAsString( cvBeginner ))) )
	{
		GlobalDataStorage::Instance()->SetComponentVisibility( cvBeginner );
	}
	else if( userExperience == wxString(ConvertedString(Component::visibilityAsString( cvExpert ))) )
	{
		GlobalDataStorage::Instance()->SetComponentVisibility( cvExpert );
	}
	else if( userExperience == wxString(ConvertedString(Component::visibilityAsString( cvGuru ))) )
	{
		GlobalDataStorage::Instance()->SetComponentVisibility( cvGuru );
	}
	else if( userExperience == wxString(ConvertedString(Component::visibilityAsString( cvInvisible ))) )
	{
		GlobalDataStorage::Instance()->SetComponentVisibility( cvInvisible );
	}
}

//-----------------------------------------------------------------------------
void PropViewFrame::WriteErrorMessage( const wxString& msg )
//-----------------------------------------------------------------------------
{
	wxTextAttr errorStyle(*wxRED);
	WriteLogMessage( msg, errorStyle );
}

//-----------------------------------------------------------------------------
void PropViewFrame::WriteLogMessage( const wxString& msg, const wxTextAttr& style /* = wxTextAttr(*wxBLACK) */ )
//-----------------------------------------------------------------------------
{
	WriteToTextCtrl( m_pLogWindow, msg, style );
}

//-----------------------------------------------------------------------------
void PropViewFrame::WriteToTextCtrl( wxTextCtrl* pTextCtrl, const wxString& msg, const wxTextAttr& style /* = wxTextAttr(*wxBLACK) */ )
//-----------------------------------------------------------------------------
{
	if( pTextCtrl )
	{
		// If you want the control to show the last line of text at the bottom, you can add "ScrollLines(1)" 
		// right after the AppendText call. AppendText will ensure the new line is visible, and ScrollLines 
		// will ensure the scroll bar is at the real end of the range, not further.
		long posBefore = pTextCtrl->GetLastPosition();
		pTextCtrl->AppendText( msg );
		long posAfter = pTextCtrl->GetLastPosition();
		pTextCtrl->SetStyle( posBefore, posAfter, style );
		pTextCtrl->ScrollLines( 1 );
		pTextCtrl->ShowPosition( m_pLogWindow->GetLastPosition() ); // ensure that this position is really visible
	}
}
