/**@file CamView/MainFrame.cpp: Form with main frame for Camera viewer. */

#include <wx/wxprec.h>
#include <wx/confbase.h>
#ifndef WX_PRECOMP
 #include <wx/wx.h>
#endif
#include <wx/dcbuffer.h> // for preview 

#include "MainFrame.h"
#include "../library/AboutDialog.h"
#include "VideoSetting.h"

#include "RT_EXEC.h"
#include "../library/wxTools.h"
#include "../library/PntwxTools.h"
#include "../library/hardware/OsSupp.h"

#define Image RsImage
#include "../library/images/Raster.h"
#undef Image
#include "../library/images/image.h"


#define AUTO_FORM_REPAINT 32	//[ms]


#define DEFINE_ONLY
#include "CamView.rc"
#undef DEFINE_ONLY


/** This string should be used inside all message boxes. */
const char APP_NAME[] = N_("Camera demo app");
const char AboutText[] =
     N_("Camera demo app\n(c) 2009-2025 Jaroslav Fojtik\nVersion " VERSIONSTR);


BEGIN_DECLARE_EVENT_TYPES()
  DECLARE_EVENT_TYPE(wxEVT_NEW_FRAME_CAM, -1)
END_DECLARE_EVENT_TYPES()


DEFINE_EVENT_TYPE(wxEVT_NEW_FRAME_CAM)

void FireSampleCB(wxFrame *pWxObj)
{
  if(pWxObj != NULL)
  {
    wxCommandEvent event(wxEVT_NEW_FRAME_CAM,pWxObj->GetId());
    //event.SetEventObject(CI);
    pWxObj->GetEventHandler()->ProcessEvent(event);
  }
}


/** Create main frame.
 *  @param[in] title The caption to be displayed on the frame's title bar
 *  @param[in] pos The window position
 *  @param[in] size The window size      */
CamViewMainFrame::CamViewMainFrame(const wxString& title, const wxPoint& pos, const wxSize& size):
     wxFrame((wxFrame*)NULL, -1, title, pos, size, wxTAB_TRAVERSAL | wxDEFAULT_FRAME_STYLE),
     mPreviewTimer(this, ID_TIMER), m_bmpBkg(NULL)
     ,FreqPlotter(NULL)
     ,mMeasureTimer(this, ID_TIMER_MEASURE)
     //,mTrigTimer(this, ID_TIMER_TRG)
{ 
  m_container.SetContainerWindow(this);

    // Make a menubar
  menuBar = new wxMenuBar;

    // create Hardware
  menuFile = new wxMenu;
  menuBar->Append(menuFile, _("&File"));    

  menuFile->Append(ID_SAVEAS, _("&Save img as .."), _("Save image 1 into a file specified."));
  menuFile->Append(ID_LOAD, _("&Load image"), _("Stop camera1 and load an image given."));
  menuFile->AppendSeparator();
  menuFile->Append(ID_SAVEAS2,_("&Save img2 as .."), _("Save image 2 into a file specified."));
  menuFile->AppendSeparator();
  menuFile->Append(ID_SAVECONFIG, _("&Save Config"), _("Save configuration to ini file."));
  menuFile->Append(ID_RELOADCONFIG, _("&Reload Config"), _("Reload configuration from ini file."));
  menuFile->AppendSeparator();
  menuFile->Append(ID_EXITAPP, _("&Exit"), _("Exit application."));


  menuSettings = new wxMenu;
  menuBar->Append(menuSettings, _("&Settings"));

  menuSettings->Append(ID_VIDEO, _("&Camera 1"), _("Setup of 1st camera."));
  menuSettings->Append(ID_VIDEO2, _("&Camera 2"), _("Setup of 2nd camera."));
  menuSettings->AppendSeparator();
  MnuMeasureFrameRate = menuSettings->AppendCheckItem(ID_MEASURE_FRAMERATE, _("&Measure framerate"), _("Measure framerate."));
  menuSettings->Append(ID_CHART_FRAMERATE, _("Ch&art framerate"), _("Show chart with a framerate."));
  wxMenuItem *TogleStatusBar = menuSettings->AppendCheckItem(ID_STATUSBAR, _("&Toggle statusbar"), _("Show/Hide statusbar."));
  TogleStatusBar->Check(true);
  menuSettings->AppendSeparator();
  menuSettings->Append(ID_SET_DEFAULT, _("&Set Factory Defaults"), _("Set default values for all options."));

    // create Camera
  menuDisplay = new wxMenu;
  menuBar->Append(menuDisplay, _("&Camera"));
		// append menu entries    
  CamBW =   menuDisplay->AppendRadioItem(ID_PAINT_BW, _("&Thresholded"), _("Paint B&W image."));
  CamGray = menuDisplay->AppendRadioItem(ID_PAINT_GRAY, _("&Raw gray"), _("Paint gray image."));
  CamColor= menuDisplay->AppendRadioItem(ID_PAINT_COLOR, _("&Raw color"), _("Paint color image."));
  menuDisplay->AppendSeparator(); 
  CamPaint = menuDisplay->AppendCheckItem(ID_PAINT_STOP, _("&Stop image"), _("Stop image."));
  CamVerticalFlip = menuDisplay->AppendCheckItem(ID_VERTICAL_FLIP, _("&Vertical flip"), _("Vertical flip image."));
  CamHorizontalFlip = menuDisplay->AppendCheckItem(ID_HORIZONTAL_FLIP, _("&Horizontal flip"), _("Horizontal flip image."));
  CamFilter= menuDisplay->AppendCheckItem(ID_FILTER_IMG, _("&Filter image"), _("Filter image data."));
  CamRectangle = menuDisplay->AppendCheckItem(ID_RECTANGLE, _("&Rectangle"), _("Cut image to rectangle shape."));
  menuDisplay->Append(ID_HISTOGRAM, _("&Histogram"), _("Show histogram."));
  CamBallSearch = menuDisplay->AppendCheckItem(ID_BALL_SEARCH, _("&Circle search"), _("Search for a ball."));

    // create Camera
  menuDisplay2 = new wxMenu;
  menuBar->Append(menuDisplay2, _("&Camera 2"));
		// append menu entries    
  CamBW2 =   menuDisplay2->AppendRadioItem(ID_PAINT_BW2, _("&Thresholded"), _("Paint B&W image."));
  CamGray2 = menuDisplay2->AppendRadioItem(ID_PAINT_GRAY2, _("&Raw gray"), _("Paint gray image."));
  CamColor2= menuDisplay2->AppendRadioItem(ID_PAINT_COLOR2, _("&Raw color"), _("Paint color image."));
  menuDisplay2->AppendSeparator(); 
  CamPaint2 = menuDisplay2->AppendCheckItem(ID_PAINT_STOP2, _("&Stop image"), _("Stop image."));
  CamVerticalFlip2 = menuDisplay2->AppendCheckItem(ID_VERTICAL_FLIP2, _("&Vertical flip"), _("Vertical flip image."));
  CamHorizontalFlip2 = menuDisplay2->AppendCheckItem(ID_HORIZONTAL_FLIP2, _("&Horizontal flip"), _("Horizontal flip image."));
  CamFilter2 = menuDisplay2->AppendCheckItem(ID_FILTER_IMG2, _("&Filter image"), _("Filter image data."));
  CamRectangle2=menuDisplay2->AppendCheckItem(ID_RECTANGLE2, _("&Rectangle"), _("Cut image to rectangle shape."));
  menuDisplay2->Append(ID_HISTOGRAM2, _("&Histogram"), _("Show histogram."));
  menuDisplay2->Append(ID_HIDE2, _("&Hide"), _("Hide camera canvas."));


    // create Help
  menuHelp = new wxMenu;
  menuBar->Append(menuHelp, _("&Help"));
    // append menu entries
  menuHelp->Append(ID_ABOUT, _("&About"), _("About the camera viewer."));
   
    // Associate the menu bar with the frame
  SetMenuBar(menuBar);

    // create frame statusbar
  statusBar = CreateStatusBar();
    // set statusbar text
  SetStatusText(_("Welcome to camera viewer!"));
    

    ////************* Arrange widgets **************************************
  CamViewMainFrame* itemFrame = this;    

      /** create vertical stack with camera canvases and combo box. */
  SzrChart = new wxBoxSizer(wxHORIZONTAL);

  camCanvas = new CameraPreview(itemFrame,&MRT.CT);	//chart with camera preview
  camCanvas2 = new CameraPreview(itemFrame,&MRT.CT2);	//chart with camera preview
        
  szitemChart = SzrChart->Add(camCanvas, 1, wxGROW|wxALL|wxSHAPED, 5);
  szitemChart2 = SzrChart->Add(camCanvas2, 1, wxGROW|wxALL|wxSHAPED, 5);

  Szr_Top = new wxBoxSizer(wxHORIZONTAL); //Main sizer for Main frame
  itemFrame->SetSizer(Szr_Top);    

  Szr_Top->Add(SzrChart,1, wxGROW|wxALL, 0);
	
  #ifdef __WXMSW__
  SetIcon(wxICON(ball));
  #endif		/// \todo set icon also for other OS
    
    // restore the control's values from the config    
  wxConfigBase *pConfig = wxConfigBase::Get();
  if(pConfig!=NULL)
  {
    pConfig->SetPath("/MainFrame");

	// restore frame position and size
    int x = pConfig->Read("x", 50),
        y = pConfig->Read("y", 50),
        w = pConfig->Read("w", 510),
        h = pConfig->Read("h", 430);
    pConfig->SetPath(_T("../"));		// SetPath() understands ".."

    int screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
    if(screen_width==0) screen_width=GetSystemMetrics(SM_CXFULLSCREEN);
    int screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
    if(screen_height==0) screen_height=GetSystemMetrics(SM_CYFULLSCREEN);
    
    if(x<screen_width && y<screen_height)	// Prevent window to fall outside display area.
    {
      Move(x, y);    
      const wxSize & minSize = wxSize(300, 180);
      itemFrame->SetSizeHints(minSize);
      const wxSize & appSize = wxSize(w, h);
      itemFrame->SetSize(appSize);
    }
  }
  
  OnLoadConfig();

  if(MRT.CT.Camera==MRT.CT2.Camera || MRT.CT2.Camera==NULL)
    camCanvas2->Hide();

  FrameTimerProcessing = false;
  m_bmpBkg = new wxBitmap;
  WxLoadBitmap(m_bmpBkg,_T("bcgmodra.bmp"));
  if(!m_bmpBkg->Ok())
      {delete m_bmpBkg; m_bmpBkg=NULL;}

  Freq1.SetDouble(0);
  Freq2.SetDouble(0);

  SetAutoLayout(true);
  Layout();

	/* Solve amount of items inside combo box. */
  wxCommandEvent EvtChRes(wxEVT_CAMERARESCHANGED,GetId());
  EvtChRes.SetEventObject(this);
  OnResolutionChange(EvtChRes);
    //GetEventHandler()->ProcessEvent(EvtChRes);

	//video refresh rate 200ms - THIS VALUE DIFFERS FROM REAL TIME PERIOD
  mPreviewTimer.Start(AUTO_FORM_REPAINT);
  if(MnuMeasureFrameRate->IsChecked()) mMeasureTimer.Start(1000);
}


CamViewMainFrame::~CamViewMainFrame() 
{
  if(mPreviewTimer.IsRunning()) mPreviewTimer.Stop();
  if(MRT.CT.Camera) MRT.CT.Camera->Stop();
  if(MRT.CT2.Camera) MRT.CT2.Camera->Stop();

  if(m_bmpBkg) {delete m_bmpBkg;m_bmpBkg=NULL;}  //release wallpaper

  if(FreqPlotter)
  {
    if(PlotGraphFrame::FindGraphFrame(FreqPlotter))
    {
      FreqPlotter->Hide();
      delete FreqPlotter;
    }
    FreqPlotter=NULL;
  }

    // save the frame position
  wxConfigBase *pConfig = wxConfigBase::Get();
  if(pConfig==NULL) return;

  if(!IsIconized())	//avoid storing garbage when iconised
  {
    int x, y, w, h;
    GetSize(&w, &h);
    GetPosition(&x, &y);
    pConfig->Write("/MainFrame/x", (long)x);
    pConfig->Write("/MainFrame/y", (long)y);
    pConfig->Write("/MainFrame/w", (long)w);
    pConfig->Write("/MainFrame/h", (long)h);
  }    
}


/**
 * // ----------------------------------------------------------------------------
 * // 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(CamViewMainFrame, wxFrame)
    EVT_TIMER(ID_TIMER,         CamViewMainFrame::OnTimer)  //place timer first to speedup table search.
    EVT_TIMER(ID_TIMER_MEASURE, CamViewMainFrame::OnTimerMeasure)
    EVT_PAINT(                  CamViewMainFrame::OnPaint)
    EVT_ERASE_BACKGROUND(       CamViewMainFrame::OnEraseBackground)

    EVT_MENU(ID_SAVEAS,         CamViewMainFrame::OnSaveAs)
    EVT_MENU(ID_LOAD,           CamViewMainFrame::OnLoad)
    EVT_MENU(ID_SAVEAS2,	CamViewMainFrame::OnSaveAs2)
    EVT_MENU(ID_ABOUT,          CamViewMainFrame::OnAbout)
    EVT_MENU(ID_MEASURE_FRAMERATE, CamViewMainFrame::OnMeasureFramerate)
    EVT_MENU(ID_CHART_FRAMERATE, CamViewMainFrame::OnChartFramerate)
    EVT_MENU(ID_PAINT_BW,	CamViewMainFrame::OnBlackWhite)
    EVT_MENU(ID_HIDE2,          CamViewMainFrame::OnHide2)
    EVT_MENU(ID_PAINT_GRAY,     CamViewMainFrame::OnGray)
    EVT_MENU(ID_PAINT_COLOR,    CamViewMainFrame::OnColor)
    EVT_MENU(ID_PAINT_STOP,     CamViewMainFrame::OnPaintStop)
    EVT_MENU(ID_VERTICAL_FLIP,  CamViewMainFrame::OnVerticalFlip)
    EVT_MENU(ID_HORIZONTAL_FLIP,CamViewMainFrame::OnHorizontalFlip)
    EVT_MENU(ID_FILTER_IMG,     CamViewMainFrame::OnPaintFilter)
    EVT_MENU(ID_RECTANGLE,      CamViewMainFrame::OnRectangle)
    EVT_MENU(ID_HISTOGRAM,      CamViewMainFrame::OnHistogram)
    EVT_MENU(ID_BALL_SEARCH,    CamViewMainFrame::OnBallSearch)
    EVT_MENU(ID_PAINT_BW2,	CamViewMainFrame::OnBlackWhite2)
    EVT_MENU(ID_PAINT_GRAY2,	CamViewMainFrame::OnGray2)
    EVT_MENU(ID_PAINT_COLOR2,	CamViewMainFrame::OnColor2)
    EVT_MENU(ID_PAINT_STOP2,	CamViewMainFrame::OnPaintStop2)
    EVT_MENU(ID_VERTICAL_FLIP2, CamViewMainFrame::OnVerticalFlip2)
    EVT_MENU(ID_HORIZONTAL_FLIP2,CamViewMainFrame::OnHorizontalFlip2)
    EVT_MENU(ID_FILTER_IMG2,	CamViewMainFrame::OnPaintFilter2)
    EVT_MENU(ID_RECTANGLE2,	CamViewMainFrame::OnRectangle2)
    EVT_MENU(ID_HISTOGRAM2,     CamViewMainFrame::OnHistogram2)
    EVT_MENU(ID_VIDEO,          CamViewMainFrame::OnVideo)
    EVT_MENU(ID_VIDEO2,         CamViewMainFrame::OnVideo2)
    EVT_MENU(ID_STATUSBAR,      CamViewMainFrame::OnStatusbar)
    EVT_MENU(ID_SAVECONFIG,     CamViewMainFrame::OnSaveConfig)
    EVT_MENU(ID_RELOADCONFIG,   CamViewMainFrame::OnReloadConfig)
    EVT_MENU(ID_EXITAPP,        CamViewMainFrame::OnExitApplication)
    //EVT_MOTION(               CamViewMainFrame::OnMouseMove)        
    //EVT_BUTTON(ID_BUTTON_RESET, CamViewMainFrame::OnCalibrate)
    //// There is conflict between RESET and SETDEFAULT Original program is confusing
    EVT_MENU(ID_SET_DEFAULT,    CamViewMainFrame::OnSetDefault)
    EVT_SIZE(                   CamViewMainFrame::OnSize)

//    EVT_COMMAND(-1, wxEVT_FORMCLOSED, CamViewMainFrame::OnPlotClose) ///< This signals that plotter form is closed
    EVT_COMMAND(-1, wxEVT_CAMERARESCHANGED, CamViewMainFrame::OnResolutionChange) ///< Camera resolution has been switched
    EVT_COMMAND(-1, wxEVT_CAMERACHANGED, CamViewMainFrame::OnCameraChange)        ///< Camera has been changed
    EVT_COMMAND(-1, wxEVT_NEW_FRAME_CAM, CamViewMainFrame::OnCamera1Frame)

    WX_EVENT_TABLE_CONTROL_CONTAINER(CamViewMainFrame) 
END_EVENT_TABLE()


WX_DELEGATE_TO_CONTROL_CONTAINER(CamViewMainFrame,wxWindow)


/** Plot window was shut down - Reactive the plot button */
void CamViewMainFrame::OnPlotClose(wxCommandEvent & WXUNUSED(event))
{
//  BtnPlot->Enable(true);
}


/** Repaint wallpaper of BP GUI. */
void CamViewMainFrame::OnPaint(wxPaintEvent &WXUNUSED(event))
{
int width;
int height;

  wxPaintDC dc(this);
  GetClientSize(&width, &height);

  if(m_bmpBkg && !ProblemsWithBrush)
    {        
    wxBrush BackBrush(*m_bmpBkg);
    BackBrush.SetStyle(wxSTIPPLE);
    
    dc.SetBrush(BackBrush);
    dc.SetLogicalFunction(wxCOPY);	//paint rectangle without a frame
    dc.SetPen(*wxTRANSPARENT_PEN); 	// - also avoid crash on W9x systems
    dc.DrawRectangle(0,0,width,height);
    }
  else dc.Clear();
}


/** Periodic timer actualises a form and repaints a bitmap from camera. */
void CamViewMainFrame::OnTimer(wxTimerEvent & event)
{
bool Cam1Grab = false;

  event.Skip();

  if(CamPaint==NULL || CamPaint->IsChecked()) goto NoCamera1;

  if(FrameTimerProcessing) return;
  FrameTimerProcessing = true;;

  if(camCanvas->CT->Camera == NULL) goto NoCamera1;
  if(camCanvas->CT->Camera->GetLastScan()==LastImageTimestamp)
    {
    if(camCanvas->CT==camCanvas2->CT) goto ExitProc; // cameras are same
    goto NoCamera1;
    }
  LastImageTimestamp = camCanvas->CT->Camera->GetLastScan();

  try {
      if(!MRT.TimerRunning()) 
	 {  //capture image only if it is not captured from RT
	 camCanvas->CT->Execute();
	 }

      //UpdateValueFromPnt(itcVideoX,MRT.VideoX);
      //UpdateValueFromPnt(itcVideoY,MRT.VideoY);

      if(camCanvas)
        if(camCanvas->IsShown())
        {
          if(camCanvas->CaptureImage(camCanvas->CT->Camera!=camCanvas2->CT->Camera))
            PlotHistogram::MarkDirtyImage(camCanvas->GetImageBuf(), camCanvas->GetPreviewStatus()==RAW_COLOR);
        }
      }
  catch(...) {}

  if(camCanvas) 
    if(camCanvas->IsShown())
      {
      camCanvas->OnPreviewImageTimer(event);  //Update BP frame
      Cam1Grab = true;
      }

NoCamera1:
  if(CamPaint2==NULL || CamPaint2->IsChecked()) goto ExitProc;
  if(camCanvas2->CT->Camera == NULL) goto ExitProc;
  if(camCanvas->CT!=camCanvas2->CT || !Cam1Grab)
    if(camCanvas2->CT->Camera->GetLastScan()==LastImageTimestamp2) goto ExitProc;
  LastImageTimestamp2 = camCanvas2->CT->Camera->GetLastScan();

  try {
      if(!MRT.TimerRunning()) 
	 {  //capture image only if it is not captured from RT
         if(camCanvas->CT!=camCanvas2->CT  || !Cam1Grab)
	   if(camCanvas2->IsShown())
	     camCanvas2->CT->Execute();
	 }

      if(camCanvas2 && camCanvas2->IsShown())
        {
          if(camCanvas2->CaptureImage(true))
              PlotHistogram::MarkDirtyImage(camCanvas2->GetImageBuf(), camCanvas2->GetPreviewStatus()==RAW_COLOR);
        }
      else
        {
	if(camCanvas->CT->Camera==camCanvas2->CT->Camera)
            camCanvas2->CT->Camera->ClearImediaSample();
        }
      }
  catch(...) {}  

  if(camCanvas2)
    if(camCanvas2->IsShown())
      camCanvas2->OnPreviewImageTimer(event);  //Update BP frame

ExitProc:
  FrameTimerProcessing = false;
}


void CamViewMainFrame::OnCamera1Frame(wxCommandEvent & event)
{
wxTimerEvent Dummy;
  event.Skip();
  if(!mPreviewTimer.IsRunning()) return;
  OnTimer(Dummy);
}


/*void CamViewMainFrame::OnCamera2Frame(wxCommandEvent & event)
{
}*/


/// Measure frame rate.
void CamViewMainFrame::OnTimerMeasure(wxTimerEvent & event)
{
char Buffer[160];
int Time1, Time2;

  if(camCanvas) 
    Time1 = camCanvas->getFrameCounter();
  else
    Time1 = 0;

  if(camCanvas2)
    Time2 = camCanvas2->getFrameCounter();
  else
    Time2 = 0;

  Freq1.SetDouble(Time1);
  Freq2.SetDouble(Time2);
  sprintf(Buffer,_("Frame rate #1:%d; Frame rate #2:%d"), Time1, Time2);
  
  SetStatusText(Buffer);
}


/// Hide camera #2 window.
void CamViewMainFrame::OnHide2(wxCommandEvent& WXUNUSED(event))
{ 
  if(camCanvas2)
    if(camCanvas2->IsShown())
      {
      camCanvas2->Hide();
      if(camCanvas2->CT!=NULL && camCanvas2->CT->Camera!=NULL)
        {
        if(camCanvas!=NULL && camCanvas->CT!=NULL && 
	   camCanvas->CT->Camera!=camCanvas2->CT->Camera)	// Stop only when using different cameras
          {
          camCanvas2->CT->Camera->Stop();
	  }
	}
      SetAutoLayout(true);
      Layout();
      Refresh();
      }
}  


/** Opens an about dialog 
 *  @param[in] event Unused event  */
void CamViewMainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{ 
  AboutDialog *dlg = new AboutDialog(this,"ballshow.bmp",_("About Camera Viewer"));
  dlg->SetText(_(AboutText));
  dlg->wxDialog::ShowModal();
}


/** Store everything into a configuration file. */
void CamViewMainFrame::OnSaveConfig(wxCommandEvent & WXUNUSED(event))
{
wxString Str;

  wxConfigBase *pConfig = wxConfigBase::Get();
  if(pConfig == NULL)
    {
    wxMessageBox(_("Cannot obtain manipulation object for camera.ini file."),
	 		_(APP_NAME), wxOK|wxICON_EXCLAMATION);
    return;  
    }

  // save a sampling period
  pConfig->SetPath("/HwSetting/");
  pConfig->Write(_T("timer"), MRT.GetPeriodMs());
  pConfig->SetPath("../");

  // save camera properties
  pConfig->SetPath("/camera1/");
  if(MRT.threshold!=NULL)
      pConfig->Write(_T("threshold"), MRT.threshold->GetDouble());

  if(MRT.CT.Camera)
    if(MRT.CT.Camera->GetWidth()>0 && MRT.CT.Camera->GetHeight()!=0)
      {
      pConfig->Write(_T("width"), MRT.CT.Camera->GetWidth());
      pConfig->Write(_T("height"), MRT.CT.Camera->GetHeight());
      pConfig->Write(_T("depth"), MRT.CT.Camera->GetDepth());
      if(MRT.CT.Camera->GetFrameRate()>0)
        pConfig->Write(_T("framerate"), MRT.CT.Camera->GetFrameRate());
      }
   if(camCanvas)
      {
      pConfig->Write(_T("viewmode"), camCanvas->GetPreviewStatus());
      pConfig->Write(_T("vflip"), camCanvas->vflip);
      pConfig->Write(_T("hflip"), camCanvas->hflip);
      }
   pConfig->SetPath("../"); 


// save camera2 properties
  pConfig->SetPath("/camera2/");
//  if(MRT.threshold2!=NULL)
//    pConfig->Write(_T("threshold"), MRT.threshold2->GetDouble());

  if(MRT.CT2.Camera)
    if(MRT.CT2.Camera->GetWidth()>0 && MRT.CT.Camera->GetHeight()!=0)
      {
      pConfig->Write(_T("width"), MRT.CT2.Camera->GetWidth());
      pConfig->Write(_T("height"), MRT.CT2.Camera->GetHeight());
      pConfig->Write(_T("depth"), MRT.CT2.Camera->GetDepth());
      if(MRT.CT2.Camera->GetFrameRate()>0)
        pConfig->Write(_T("framerate"), MRT.CT2.Camera->GetFrameRate());
      }
   if(camCanvas2)
      {
      pConfig->Write(_T("viewmode"), camCanvas2->GetPreviewStatus());
      pConfig->Write(_T("vflip"), camCanvas2->vflip);
      pConfig->Write(_T("hflip"), camCanvas2->hflip);
      pConfig->Write(_T("visible"), camCanvas2->IsShown());
      }
   pConfig->SetPath("../"); 


    // save a frame position
  int x, y, w, h;
  GetSize(&w, &h);
  GetPosition(&x, &y);
  pConfig->Write(_T("/MainFrame/x"), x);
  pConfig->Write(_T("/MainFrame/y"), y);
  pConfig->Write(_T("/MainFrame/w"), w);
  pConfig->Write(_T("/MainFrame/h"), h);
  
  IniFileEmpty = false;
  if(!pConfig->Flush(true)) ///< store a value into configuration file  
    {
    wxMessageBox(_("Cannot save camera.ini file."),
	 		_(APP_NAME), wxOK|wxICON_EXCLAMATION);
    }
}


void CamViewMainFrame::OnReloadConfig(wxCommandEvent & WXUNUSED(event))
{
  wxConfigBase *pConfig = wxConfigBase::Get();
  if (pConfig==NULL) return;

  if(IniFileEmpty)
    if(!pConfig->HasGroup("/HwSetting") || !pConfig->HasGroup("/MainFrame") 
		/* || !pConfig->HasGroup(DEFAULT_PID_GROUP)*/)
      {    
      wxMessageBox(_("File camera.ini does not exist,\n"
                      "or there are missing items inside camera.ini."),
	 		_(APP_NAME), wxOK|wxICON_EXCLAMATION);
      return;
      }

  OnLoadConfig();
}


void CamViewMainFrame::OnExitApplication(wxCommandEvent & event)
{
  Destroy();
}


/** Load all configuretion stuff. */
void CamViewMainFrame::OnLoadConfig()
{
long period;
int Width=DEFAULT_VIDEO_WIDTH;	  ///< Default camera video resolution - width
int Height=DEFAULT_VIDEO_HEIGHT;  ///< Default camera video resolution - height
int Depth=24;			  ///< Default camera depth
double FrameRate=30;
//CamRtExec::CTR_MODES OldControlMode;

  period = 10;

  wxConfigBase *pConfig = wxConfigBase::Get();
  if(pConfig==NULL)
    {
    MRT.SetPeriodMs(period); 
    return;
    }

	// load a sampling period
  // period = pConfig->Read(_T("/HwSetting/timer"), HwSetting::DEF_TIME);
  MRT.SetPeriodMs(period); 

	// load camera properties
  pConfig->SetPath("/HwSetting/");
  if(MRT.threshold)
      MRT.threshold->SetDouble(pConfig->Read(_T("threshold"), 
		CameraTool::DEFAULT_THR));
  pConfig->SetPath("../");

  pConfig->SetPath("/camera1/");
  if(MRT.CT.Camera)
    {  
    Width = pConfig->Read("width", DEFAULT_VIDEO_WIDTH);
    Height = pConfig->Read("height", DEFAULT_VIDEO_HEIGHT);
    Depth = pConfig->Read("depth", Depth);
    FrameRate = pConfig->Read("framerate", 0.0);	// 0 means default value
        
    if(Width!=MRT.CT.Camera->GetWidth() || labs(Height)!=labs(MRT.CT.Camera->GetHeight()) ||
       Depth!=MRT.CT.Camera->GetDepth() || 
       (abs(FrameRate-MRT.CT.Camera->GetFrameRate())>1e-3 && FrameRate>0))
      {
      MRT.CT.Camera->Stop();
      MRT.CT.Camera->SelectVideoMode(Width,Height,Depth,FrameRate);
      MRT.CT.Camera->Start();

	 /* Emit event about resolution change. */
      wxCommandEvent EvtDummy(wxEVT_CAMERARESCHANGED,GetId());
      OnResolutionChange(EvtDummy);
	     /* Traverse through all opened VideoProperty - "event" don't go to childs. */
      std::list<VideoSetting *>::iterator IterVideoProp;
      for(IterVideoProp=VideoSetting::Instances.begin(); IterVideoProp!=VideoSetting::Instances.end(); IterVideoProp++)
        (*IterVideoProp)->OnResolutionChanged(EvtDummy);
      }  
    }
  camCanvas->SetPreviewStatus(
      (VISION_STATES)pConfig->Read(_T("viewmode"),camCanvas->GetPreviewStatus()));
  camCanvas->vflip = pConfig->Read(_T("vflip"),camCanvas->vflip);
  if(CamVerticalFlip->IsChecked() ^ camCanvas->vflip)
      CamVerticalFlip->Check(camCanvas->vflip);
  camCanvas->hflip = pConfig->Read(_T("hflip"),camCanvas->hflip);
  if(CamHorizontalFlip->IsChecked() ^ camCanvas->hflip)
      CamHorizontalFlip->Check(camCanvas->hflip);
  pConfig->SetPath("../");


  pConfig->SetPath("/camera2/");
  if(MRT.CT2.Camera)
  {  
    Width = pConfig->Read("width", DEFAULT_VIDEO_WIDTH);
    Height = pConfig->Read("height", DEFAULT_VIDEO_HEIGHT);
    Depth = pConfig->Read("depth", 8);
    FrameRate = pConfig->Read("framerate", 0.0);	// 0 means default value
    int Visible = pConfig->Read("visible", 1);
    
    if(Visible)
    {
      if(Width!=MRT.CT2.Camera->GetWidth() || labs(Height)!=labs(MRT.CT2.Camera->GetHeight()) ||
       Depth!=MRT.CT2.Camera->GetDepth() || 
       (abs(FrameRate-MRT.CT2.Camera->GetFrameRate())>1e-3 && FrameRate>0))
      {
        MRT.CT2.Camera->Stop();
        MRT.CT2.Camera->SelectVideoMode(Width,Height,Depth,FrameRate);
        MRT.CT2.Camera->Start();

	 /* Emit event about resolution change. */
        wxCommandEvent EvtDummy(wxEVT_CAMERARESCHANGED,GetId());
        OnResolutionChange(EvtDummy);
	     /* Traverse through all opened VideoProperty - "event" don't go to childs. */
        std::list<VideoSetting *>::iterator IterVideoProp;
        for(IterVideoProp=VideoSetting::Instances.begin(); IterVideoProp!=VideoSetting::Instances.end(); IterVideoProp++)
          (*IterVideoProp)->OnResolutionChanged(EvtDummy);
      }
    }
    else
    {
      if(camCanvas2->IsShown())
      {
        wxCommandEvent evt; 
        OnHide2(evt);
      }
    }
  }
  camCanvas2->SetPreviewStatus(
      (VISION_STATES)pConfig->Read(_T("viewmode"),camCanvas2->GetPreviewStatus()));
  camCanvas2->vflip = pConfig->Read(_T("vflip"),camCanvas2->vflip);
  if(CamVerticalFlip2->IsChecked() ^ camCanvas2->vflip)
      CamVerticalFlip2->Check(camCanvas2->vflip);
  camCanvas2->hflip = pConfig->Read(_T("hflip"),camCanvas2->hflip);
  if(CamHorizontalFlip2->IsChecked() ^ camCanvas2->hflip)
      CamHorizontalFlip2->Check(camCanvas2->hflip);
  pConfig->SetPath("../");

  switch(camCanvas->GetPreviewStatus())
  {
    case RAW_PIC:         CamGray->Check();  break;
    case THRESHOLDED_PIC: CamBW->Check();    break;
    case RAW_COLOR:	  CamColor->Check(); break;
    default: return;  //no capture needed
  }
  switch(camCanvas2->GetPreviewStatus())
  {
    case RAW_PIC:         CamGray2->Check(); break;
    case THRESHOLDED_PIC: CamBW2->Check();   break;
    case RAW_COLOR:	  CamColor2->Check();   break;
    default: return;  //no capture needed
  }

//   if(OldControlMode>=CamRtExec::CTR_RUN_1ST) MRT.StartControl();
}


/** Shrink combo box, when camerachanges mode. */
void CamViewMainFrame::OnResolutionChange(wxCommandEvent & event)
{
int ComboCount;

  event.Skip();		//This event should be spread widely, don't remove.

  if(MRT.CT.Camera)
  {
    if(camCanvas)
      szitemChart->SetRatio(MRT.CT.Camera->GetWidth(), labs(MRT.CT.Camera->GetHeight()));

    if(camCanvas)
      szitemChart->SetRatio(MRT.CT.Camera->GetWidth(), labs(MRT.CT.Camera->GetHeight()));

      /* Emit event about resolution change. */
    if(m_bmpBkg!=NULL) // not fully initialised form?
    {
      SetAutoLayout(true);
      Layout();
    }

     ComboCount = camCanvas->GetPreviewStatus();
  //  ComboCount = itemComboBox->GetCount();
    if(MRT.CT.Camera->GetDepth()<24) 
    {					// B&W mode
      if(ComboCount==4)
      {
        //itemComboBox->Delete(3);
//        if(itemComboBox->GetSelection()==wxNOT_FOUND)
        {
	  //itemComboBox->Select(RAW_PIC);
	  //OnComboBox(event);		// Software Select() do not generate event, call its handler directly!
					// Even direct call does not work!
          camCanvas->SetPreviewStatus(RAW_PIC);	
        }
      }
    }
    else					// color mode
    {
//    if(ComboCount==3)
//	itemComboBox->Append(itemComboBoxStrings[3]);
    }

    //camCanvas->HookTimer(&mTrigTimer);
    camCanvas->HookFrame(this);
  }


  if(MRT.CT2.Camera)
    {
    if(camCanvas2)
      szitemChart2->SetRatio(MRT.CT2.Camera->GetWidth(), labs(MRT.CT2.Camera->GetHeight()));

    if(camCanvas2)
      szitemChart2->SetRatio(MRT.CT2.Camera->GetWidth(), labs(MRT.CT2.Camera->GetHeight()));

      /* Emit event about resolution change. */
    if(m_bmpBkg!=NULL) // not fully initialised form?
      {
      SetAutoLayout(true);
      Layout();
      }

     ComboCount = camCanvas2->GetPreviewStatus();
  //  ComboCount = itemComboBox->GetCount();
    if(MRT.CT2.Camera->GetDepth()<24) 
      {					// B&W mode
      if(ComboCount==4)
        {
        //itemComboBox->Delete(3);
//        if(itemComboBox->GetSelection()==wxNOT_FOUND)
          {
	    //itemComboBox->Select(RAW_PIC);
	    //OnComboBox(event);		// Software Select() do not generate event, call its handler directly!
					// Even direct call does not work!
	      camCanvas2->SetPreviewStatus(RAW_PIC);	
          }
        }
      }
    else					// color mode
      {
//    if(ComboCount==3)
//	itemComboBox->Append(itemComboBoxStrings[3]);
      }

    //camCanvas2->HookTimer(&mTrigTimer);
    camCanvas->HookFrame(this);
  }

}


void CamViewMainFrame::OnCameraChange(wxCommandEvent & event)
{
  if(camCanvas)
    camCanvas->OnCameraChange(event);
  if(camCanvas2)
    camCanvas2->OnCameraChange(event);      
}


/** Store image from buffer into a user selected file. */
void CamViewMainFrame::OnLoad(wxCommandEvent & event)
{
unsigned y;
TImageFileHandler *LoadPicture_XXX;
wxString FileNames;

  FileNames = _("Any file (*.*)|*.*");
  for(LoadPicture_XXX=TImageFileHandler::first();LoadPicture_XXX!=NULL;LoadPicture_XXX=LoadPicture_XXX->next())
  {
    if(LoadPicture_XXX->LoadPicture==NULL) continue;

    const char *Ext = LoadPicture_XXX->extension();
    if(Ext==NULL) continue;
    if(*Ext==0) continue;
    if(*Ext == '.') Ext++;

    FileNames += _T("|");
    FileNames += Ext;
    FileNames += _(" file (*.");
    FileNames += Ext;
    FileNames += _T(")|*.");
    FileNames += Ext;    
  } 

 wxFileDialog LoadDialog(this,
                       _("Load image into buffer ..."),
                       wxEmptyString,
                       wxEmptyString,
                       FileNames,
                       0);
  if(LoadDialog.ShowModal() == wxID_OK)
  {    
    Image I = LoadPicture(LoadDialog.GetPath());
    if(I.Raster==NULL)
      {
      wxMessageBox(_("Image load failed or image is empty!"),
			_(APP_NAME), wxOK|wxICON_EXCLAMATION);
      return;
      }
    if(I.Raster->Size1D==0 || I.Raster->Size2D==0)
      {
      wxMessageBox(_("Image is empty!"), _(APP_NAME), wxOK|wxICON_EXCLAMATION);
      return;
      }

    CamPaint->Check(true);
    OnPaintStop(event);

    Raster2DAbstract *Ras = I.Raster;
    Raster2DAbstract *pImageBuf = camCanvas->GetImageBuf();

    if(pImageBuf==NULL)
      {
      wxMessageBox(_("pImageBuf of camCanvas is NULL!"), APP_NAME, wxOK|wxICON_EXCLAMATION);
      return;
      }
    
    if(Ras)
    {
      InterlockedExchangeAdd(&pImageBuf->UsageCount,WRITE_BARIER);
      pImageBuf->Allocate2D(Ras->Size1D,Ras->Size2D);

      InterlockedExchangeAdd(&pImageBuf->UsageCount,READ_BARIER-WRITE_BARIER);
      
      if(pImageBuf->Size1D>0 && pImageBuf->Size2D>0)
      {
        for(y=0;y<Ras->Size2D;y++)
        {
          pImageBuf->GetRowRaster(y)->Set(*Ras->GetRowRaster(y));	
        }
      }

      InterlockedExchangeAdd(&pImageBuf->UsageCount,-READ_BARIER);

      PlotHistogram::MarkDirtyImage(pImageBuf,true);
	
      camCanvas->CT->InvalidateVideoPos();	// Hide ellipse
    }
    
    camCanvas->SetImage(pImageBuf);
      
    camCanvas->SetPreviewStatus(EXTERN_COLOR);

    wxString MsgStatus(_("Image loaded: "));
    MsgStatus += LoadDialog.GetPath();
    SetStatusText(MsgStatus);
      
    camCanvas->Show();
    camCanvas->Refresh();
    if(szitemChart)  szitemChart->SetRatio(pImageBuf->Size1D, pImageBuf->Size2D);      
    SetAutoLayout(true);
    Layout();
  }
}

/** Store image from buffer into a user selected file. */
void CamViewMainFrame::OnSaveAs(wxCommandEvent & WXUNUSED(event))
{
  TImageFileHandler *LoadPicture_XXX;
  wxString FileNames;
  for(LoadPicture_XXX=TImageFileHandler::first();LoadPicture_XXX!=NULL;LoadPicture_XXX=LoadPicture_XXX->next())
    {
    if(LoadPicture_XXX->SavePicture==NULL) continue;
    const char *Ext = LoadPicture_XXX->extension();
    if(Ext==NULL) continue;
    if(*Ext==0) continue;
    if(*Ext == '.') Ext++;

    if(LoadPicture_XXX->description())
      FileNames += LoadPicture_XXX->description();
    else
      FileNames += Ext;    
    FileNames += _(" file (*.");
    FileNames += Ext;
    FileNames += _T(")|*.");
    FileNames += Ext;
    FileNames += _T("|");    
    }
  FileNames += _("Any file (*)|*");

  wxFileDialog SaveDialog( this,
                       _("Save image As ..."),
                       wxEmptyString,
                       wxEmptyString,
		       FileNames,
                       wxSAVE|wxOVERWRITE_PROMPT
                     );
  if(SaveDialog.ShowModal() == wxID_OK)
    {
    Image I;

    Raster2DAbstract *Ras = camCanvas->GetImageBuf();
    const unsigned char *pImageBuf = camCanvas->GetImageData();
    const unsigned char *raw_data = pImageBuf;
    if(raw_data==NULL) return;

    switch(camCanvas->GetPreviewStatus())
      {
      case THRESHOLDED_PIC:
		{
                I.Create(Ras->Size1D, Ras->Size2D, 1);
	        if(I.Raster==NULL) goto CANNOT_CREATE_RASTER;
                for(unsigned y=0;y<Ras->Size2D;y++)
                  for(unsigned x=0;x<Ras->Size1D;x++)
                    {
                    I.SetPixel(x,y, (*raw_data>128) ? 1 : 0);
	            raw_data+=3;
	            }
                break;
                }      
      case RAW_PIC:
		{
                I.Create(Ras->Size1D, Ras->Size2D, 8);
		if(I.Raster==NULL) goto CANNOT_CREATE_RASTER;
                for(unsigned y=0;y<Ras->Size2D;y++)
                  for(unsigned x=0;x<Ras->Size1D;x++)
                    {
                    I.SetPixel(x,y, *raw_data);
	            raw_data+=3;
	            }
                break;
                }
      case RAW_COLOR:
      default:	
		{
                I.Create(Ras->Size1D, Ras->Size2D, 8|ImageTrueColor);
		if(I.Raster==NULL) goto CANNOT_CREATE_RASTER;
                for(unsigned y=0; y<Ras->Size2D; y++)
		  {
		  I.Raster->GetRowRaster(y)->Set(*Ras->GetRowRaster(y));
                  }
                break;
                }
      }

    if(SavePicture(SaveDialog.GetPath(),I)<0)
       wxMessageBox(_("Cannot save image into a file specified"),
			APP_NAME, wxOK|wxICON_EXCLAMATION);
    }
  return;

CANNOT_CREATE_RASTER:
  wxMessageBox(_("Cannot create temporary image raster."), APP_NAME, wxOK|wxICON_EXCLAMATION);
  return;
}


/** Store image from buffer into a user selected file. */
void CamViewMainFrame::OnSaveAs2(wxCommandEvent & WXUNUSED(event))
{
  TImageFileHandler *LoadPicture_XXX;
  wxString FileNames;
  for(LoadPicture_XXX=TImageFileHandler::first();LoadPicture_XXX!=NULL;LoadPicture_XXX=LoadPicture_XXX->next())
    {
    if(LoadPicture_XXX->SavePicture==NULL) continue;
    const char *Ext = LoadPicture_XXX->extension();
    if(Ext==NULL) continue;
    if(*Ext==0) continue;
    if(*Ext == '.') Ext++;
    
    if(LoadPicture_XXX->description())
      FileNames += LoadPicture_XXX->description();
    else
      FileNames += Ext;
    FileNames += _(" file (*.");
    FileNames += Ext;
    FileNames += _T(")|*.");
    FileNames += Ext;
    FileNames += _T("|");
    }
  FileNames += _("Any file (*)|*");
  wxFileDialog SaveDialog( this,
                       _("Save image 2 As ..."),
                       wxEmptyString,
                       wxEmptyString,
		       FileNames,                       
                       wxSAVE|wxOVERWRITE_PROMPT
                     );
  if(SaveDialog.ShowModal() == wxID_OK)
    {
    Image I;

    const unsigned char *pImageBuf = camCanvas2->GetImageData();
    const unsigned char *raw_data = pImageBuf;
    Raster2DAbstract *Ras = camCanvas2->GetImageBuf();
    if(raw_data==NULL) return;

    switch(camCanvas2->GetPreviewStatus())
      {
      case THRESHOLDED_PIC:
		{
                I.Create(Ras->Size1D, Ras->Size2D, 1);
		if(I.Raster==NULL) goto CANNOT_CREATE_RASTER;
                for(unsigned y=0;y<Ras->Size2D;y++)
                  for(unsigned x=0;x<Ras->Size1D;x++)
                    {
                    I.SetPixel(x,y, (*raw_data>128) ? 1 : 0);
	            raw_data+=3;
	            }
                break;
                }      
      case RAW_PIC:
		{
                I.Create(Ras->Size1D, Ras->Size2D, 8);
		if(I.Raster==NULL) goto CANNOT_CREATE_RASTER;		
                for(unsigned y=0;y<Ras->Size2D;y++)
                  for(unsigned x=0;x<Ras->Size1D;x++)
                    {
                    I.SetPixel(x,y, *raw_data);
	            raw_data+=3;
	            }
                break;
                }
      case RAW_COLOR:
      default:	
		{
                I.Create(Ras->Size1D, Ras->Size2D, 8|ImageTrueColor);
		if(I.Raster==NULL) goto CANNOT_CREATE_RASTER;
                for(unsigned y=0;y<Ras->Size2D;y++)
		  I.Raster->GetRowRaster(y)->Set(*Ras->GetRowRaster(y));
                break;
                }
      }

    if(SavePicture(SaveDialog.GetPath(),I)<0)
       wxMessageBox(_("Cannot save image into a file specified"), APP_NAME, wxOK|wxICON_EXCLAMATION);
    }
  return;

CANNOT_CREATE_RASTER:
  wxMessageBox(_("Cannot create temporary image raster."), APP_NAME, wxOK|wxICON_EXCLAMATION);
  return;
}



void CamViewMainFrame::OnBlackWhite(wxCommandEvent & WXUNUSED(event))
{
  Switch(THRESHOLDED_PIC);
}

void CamViewMainFrame::OnGray(wxCommandEvent & WXUNUSED(event))
{
  Switch(RAW_PIC);
}

void CamViewMainFrame::OnColor(wxCommandEvent & WXUNUSED(event))
{
  Switch(RAW_COLOR);
}

/**  
 *  Manages the position view, video capture view  and thresholed view of the model.
 *  @param[in] event Unused event */
void CamViewMainFrame::Switch(VISION_STATES choice)
{
  if(MRT.CT.Camera==NULL)
    {
    if(choice!=RAW_PIC)
      {
      camCanvas->SetPreviewStatus(RAW_PIC);
      //itemComboBox->Select(GRAPH);
      }
    return;
    }

  switch(choice)
    {
    case GRAPH: camCanvas->SetPreviewStatus(GRAPH);
	    break;
    case RAW_PIC:camCanvas->SetPreviewStatus(RAW_PIC);
	    break;
    case THRESHOLDED_PIC:
            camCanvas->SetPreviewStatus(THRESHOLDED_PIC);
	    break;
    case RAW_COLOR:
	    camCanvas->SetPreviewStatus(RAW_COLOR);
	    if(MRT.CT.Camera)
              if(MRT.CT.Camera->GetDepth()<12 && MRT.CT.Camera->VideoFormat!=vfRGB8 && MRT.CT.Camera->VideoFormat!=vfI420)
		wxMessageBox(_("Camera must be switched to color mode.\n"
			"Please open dialog MainMenu/Settings/Camera 1/ChangeResolution and switch mode."),
			APP_NAME, wxOK|wxICON_EXCLAMATION);
            Raster2DAbstract *pImg = camCanvas->GetImageBuf();
            if(pImg!=NULL && pImg->Channels()!=3)
            {
              PlotHistogram *pH = PlotHistogram::FindHistogram(pImg);
              if(pH!=NULL)
              {
                pH->AssignImage(NULL);
                camCanvas->CaptureImage(true);
                pImg = camCanvas->GetImageBuf();
                if(pImg!=NULL && pImg->Channels()==3)
                  pH->AssignImage(pImg);		// Replace with a new raster.
                else
                  pH->Destroy();			// Something gets wrong, close rather histogram window.
              }
            }
	    break;
    }
  camCanvas->Refresh(); // ???
}


void CamViewMainFrame::OnBlackWhite2(wxCommandEvent & WXUNUSED(event))
{
  Switch2(THRESHOLDED_PIC);
}

void CamViewMainFrame::OnGray2(wxCommandEvent & WXUNUSED(event))
{
  Switch2(RAW_PIC);
}

void CamViewMainFrame::OnColor2(wxCommandEvent & WXUNUSED(event))
{
  Switch2(RAW_COLOR);
}


/**  
 *  Manages the position view, video capture view  and thresholed view of the model.
 *  @param[in] event Unused event */
void CamViewMainFrame::Switch2(VISION_STATES choice)
{
  if(MRT.CT2.Camera==NULL)
    {
    if(choice!=RAW_PIC)
      {
      camCanvas2->SetPreviewStatus(RAW_PIC);
      //itemComboBox->Select(GRAPH);
      }
    return;
    }

  switch(choice)
    {
    case GRAPH: camCanvas2->SetPreviewStatus(GRAPH);
	    break;
    case RAW_PIC:camCanvas2->SetPreviewStatus(RAW_PIC);
	    break;
    case THRESHOLDED_PIC:
            camCanvas2->SetPreviewStatus(THRESHOLDED_PIC);
	    break;
    case RAW_COLOR:
	    camCanvas2->SetPreviewStatus(RAW_COLOR);
	    if(MRT.CT2.Camera)
              if(MRT.CT2.Camera->GetDepth()<16 && MRT.CT.Camera->VideoFormat!=vfRGB8 && MRT.CT.Camera->VideoFormat!=vfI420)
		wxMessageBox(_("Camera 2 must be switched to color mode.\n"
			"Please open dialog MainMenu/Settings/Camera 2/ChangeResolution and switch mode."),
			APP_NAME, wxOK|wxICON_EXCLAMATION);
            Raster2DAbstract *pImg = camCanvas2->GetImageBuf();
            if(pImg!=NULL && pImg->Channels()!=3)
            {
              PlotHistogram *pH = PlotHistogram::FindHistogram(pImg);
              if(pH!=NULL)
              {
                pH->AssignImage(NULL);			// Detach image from histogram.
                camCanvas2->CaptureImage(true);
                pImg = camCanvas2->GetImageBuf();
                if(pImg!=NULL && pImg->Channels()==3)
                  pH->AssignImage(pImg);		// Replace with a new raster.
                else
                  pH->Destroy();			// Something gets wrong, close rather histogram window.
              }
            }
	    break;
    }
  camCanvas2->Refresh(); // ???
}


/** Display a video setting dialog for camera1. */
void CamViewMainFrame::OnVideo(wxCommandEvent& WXUNUSED(event))
{
  if(!camCanvas->IsShown())
    {
    camCanvas->Show();
    SetAutoLayout(true);
    Layout();
    }
  if(!VideoSetting::Instances.empty())	// Is a dialog already opened?
    {
    std::list<VideoSetting *>::iterator IterVideoProp;
    for(IterVideoProp=VideoSetting::Instances.begin(); IterVideoProp!=VideoSetting::Instances.end(); IterVideoProp++)
      {
      if((*IterVideoProp)->CT == &MRT.CT)
        {
        (*IterVideoProp)->SetFocus();
        return;
        }
      }    
    }
  VideoSetting *VideoSet = new VideoSetting(this,&MRT.CT," #1");
  VideoSet->Show();
}

/** Display a video setting dialog for camera2. */
void CamViewMainFrame::OnVideo2(wxCommandEvent& WXUNUSED(event))
{
  if(!camCanvas2->IsShown())
    {
    camCanvas2->Show();
    SetAutoLayout(true);
    Layout();
    if(camCanvas2->CT!=NULL && camCanvas2->CT->Camera!=NULL)
      {
      if(camCanvas->CT==NULL || camCanvas->CT->Camera==NULL)
        {
        camCanvas2->CT->Camera->Start();  // Attempt to start camera that has been hidden, no camera 1.
        }
      else if(camCanvas2->CT->Camera != camCanvas->CT->Camera)
        {
        camCanvas2->CT->Camera->Start();  // Attempt to start camera that has been hidden.
        }
      }
    }
  if(!VideoSetting::Instances.empty())	// Is a dialog already opened?
    {
    std::list<VideoSetting *>::iterator IterVideoProp;
    for(IterVideoProp=VideoSetting::Instances.begin(); IterVideoProp!=VideoSetting::Instances.end(); IterVideoProp++)
      {
      if((*IterVideoProp)->CT == &MRT.CT2)
        {
        (*IterVideoProp)->SetFocus();
        return;
        }
      }    
    }
  VideoSetting *VideoSet = new VideoSetting(this,&MRT.CT2," #2");
  VideoSet->Show();

  if(camCanvas)
    if(camCanvas->IsShown())
      {		// camCanvas must be refreshed otherwise it is not repainted correctly
      camCanvas->Refresh(false);
      }
}


void CamViewMainFrame::OnStatusbar(wxCommandEvent& WXUNUSED(event))
{
  if(statusBar==NULL) return;
  if(statusBar->IsShown())
      statusBar->Hide();
  else
      statusBar->Show();

  SetAutoLayout(true);
  Layout();
  Refresh();
}


/** Opens plot frame for the graphs of signals
 *  @param[in] event Unused event  */
void CamViewMainFrame::OnHistogram(wxCommandEvent& WXUNUSED(event))
{ 
PlotHistogram *pgf = NULL;

  if(camCanvas==NULL) return;
  if(!PlotHistogram::Instances.empty())	// Is a dialog already opened?
  {
    for(std::list<PlotHistogram*>::iterator it=PlotHistogram::Instances.begin(); it!=PlotHistogram::Instances.end(); ++it)
    {
      if(*it==NULL) continue;
      if((*it)->Image == camCanvas->GetImageBuf())
      {
        pgf = *it;
        break;
      }
    }    
  }
  if(pgf==NULL)
  {
    pgf = new PlotHistogram(this);
    pgf->AssignImage(camCanvas->GetImageBuf());
  }
  
  pgf->Show();
  pgf->SetFocus();
}


/** Opens plot frame for the graphs of signals
 *  @param[in] event Unused event  */
void CamViewMainFrame::OnHistogram2(wxCommandEvent& WXUNUSED(event))
{ 
PlotHistogram *pgf = NULL;

  if(camCanvas2==NULL) return;
  if(!PlotHistogram::Instances.empty())	// Is a dialog already opened?
  {
    for(std::list<PlotHistogram*>::iterator it=PlotHistogram::Instances.begin(); it!=PlotHistogram::Instances.end(); ++it)
    {
      if(*it==NULL) continue;
      if((*it)->Image == camCanvas2->GetImageBuf())
      {
        pgf = *it;
        break;
      }
    }
  }

  if(pgf==NULL)
  {
    pgf = new PlotHistogram(this,_("Histogram 2"));
    pgf->AssignImage(camCanvas2->GetImageBuf());
  }  
  pgf->Show();
  pgf->SetFocus();
}


void CamViewMainFrame::OnBallSearch(wxCommandEvent& WXUNUSED(event))
{
  camCanvas->CT->BalSearchAlloved = CamBallSearch->IsChecked();
}


/** Stops the timer */
void CamViewMainFrame::StopCapturing(void)
{
  if(mPreviewTimer.IsRunning())
    {
    mPreviewTimer.Stop();
    mMeasureTimer.Stop();
    //mTrigTimer.Stop();
    }
}


/** Starts the timer. */
void CamViewMainFrame::StartCapturing(void)
{
 if(!mPreviewTimer.IsRunning())
   {
   if(MnuMeasureFrameRate->IsChecked())
       mPreviewTimer.Start();
   mMeasureTimer.Start(1000);
   }
}


void CamViewMainFrame::OnMeasureFramerate(wxCommandEvent& WXUNUSED(event))
{
  if(MnuMeasureFrameRate==NULL) return;

  if(mPreviewTimer.IsRunning())
  {
    if(MnuMeasureFrameRate->IsChecked())
    {
      if(!mMeasureTimer.IsRunning())
      {
	if(camCanvas) camCanvas->getFrameCounter();  
        if(camCanvas2)camCanvas2->getFrameCounter();
        mMeasureTimer.Start(1000);
      }
    }
    else
      mMeasureTimer.Stop();
  }
  else
    mMeasureTimer.Stop();
}


void CamViewMainFrame::OnChartFramerate(wxCommandEvent& WXUNUSED(event))
{
  if(MnuMeasureFrameRate==NULL) return;
  if(!mMeasureTimer.IsRunning())
  {
    if(camCanvas) camCanvas->getFrameCounter();  
    if(camCanvas2)camCanvas2->getFrameCounter();
    mMeasureTimer.Start(1000);
  }
  if(!MnuMeasureFrameRate->IsChecked())
  {
    MnuMeasureFrameRate->Check(true);
  }
  if(!PlotGraphFrame::FindGraphFrame(FreqPlotter)) FreqPlotter=NULL;
  if(FreqPlotter==NULL)
  {
    FreqPlotter = new PlotGraphFrame(this);
    FreqPlotter->Frequency1 = &Freq1;
    FreqPlotter->Frequency2 = &Freq2;
  }
  if(!FreqPlotter->IsShown())
      FreqPlotter->Show();
}



/**
 *  Stops the controller, but timer still paints image
 *  @param[in] event Unused event   */
void CamViewMainFrame::OnPaintStop(wxCommandEvent& WXUNUSED(event))
{
  if(CamPaint->IsChecked())
    SetStatusText(_("Painting mode off."));
  else
    {
    SetStatusText(_("Painting mode on."));
    if(camCanvas->GetPreviewStatus()==EXTERN_COLOR)
      {
      camCanvas->SetPreviewStatus(RAW_COLOR);
      if(szitemChart) szitemChart->SetRatio(MRT.CT.GetWidth(), labs(MRT.CT.GetHeight()));
      SetAutoLayout(true);
      Layout();
      Refresh();
      }
    }
}


void CamViewMainFrame::OnPaintFilter(wxCommandEvent& WXUNUSED(event))
{
  if(camCanvas==NULL) return;

  if(CamFilter->IsChecked())
    camCanvas->filter = 1;
  else
    camCanvas->filter = 0;
}


void CamViewMainFrame::OnVerticalFlip(wxCommandEvent& WXUNUSED(event))
{
  if(camCanvas==NULL) return;

  if(CamVerticalFlip->IsChecked())
    camCanvas->vflip = 1;
  else
    camCanvas->vflip = 0;
}


void CamViewMainFrame::OnHorizontalFlip(wxCommandEvent& WXUNUSED(event))
{
  if(camCanvas==NULL) return;

  if(CamHorizontalFlip->IsChecked())
    camCanvas->hflip = 1;
  else
    camCanvas->hflip = 0;
}


void CamViewMainFrame::OnRectangle(wxCommandEvent& WXUNUSED(event))
{
  if(camCanvas==NULL) return;

  if(CamRectangle->IsChecked())
    camCanvas->rectangle = 1;
  else
    camCanvas->rectangle = 0;

  camCanvas->FlushFilter();
  if(camCanvas->CaptureImage(true))
      PlotHistogram::MarkDirtyImage(camCanvas->GetImageBuf(), camCanvas->GetPreviewStatus()==RAW_COLOR);
  szitemChart->SetRatio(MRT.CT.GetWidth(), labs(MRT.CT.GetHeight()));
  szitemChart2->SetRatio(MRT.CT2.GetWidth(), labs(MRT.CT2.GetHeight()));
  SetAutoLayout(true);
  Layout();
  Refresh();
}

void CamViewMainFrame::OnPaintFilter2(wxCommandEvent& WXUNUSED(event))
{
  if(camCanvas2==NULL) return;

  if(CamFilter2->IsChecked())
    camCanvas2->filter = 1;
  else
    camCanvas2->filter = 0;
}


void CamViewMainFrame::OnVerticalFlip2(wxCommandEvent& WXUNUSED(event))
{
  if(camCanvas2==NULL) return;

  if(CamVerticalFlip2->IsChecked())
    camCanvas2->vflip = 1;
  else
    camCanvas2->vflip = 0;
}


void CamViewMainFrame::OnHorizontalFlip2(wxCommandEvent& WXUNUSED(event))
{
  if(camCanvas2==NULL) return;

  if(CamHorizontalFlip2->IsChecked())
    camCanvas2->hflip = 1;
  else
    camCanvas2->hflip = 0;
}


void CamViewMainFrame::OnRectangle2(wxCommandEvent& WXUNUSED(event))
{
  if(camCanvas2==NULL) return;

  if(CamRectangle2->IsChecked())
    camCanvas2->rectangle = 1;
  else
    camCanvas2->rectangle = 0;

  camCanvas2->FlushFilter();
  if(camCanvas2->CaptureImage(true))
      PlotHistogram::MarkDirtyImage(camCanvas2->GetImageBuf(), camCanvas2->GetPreviewStatus()==RAW_COLOR);
  if(szitemChart)  szitemChart->SetRatio(MRT.CT.GetWidth(), labs(MRT.CT.GetHeight()));
  if(szitemChart2) szitemChart2->SetRatio(MRT.CT2.GetWidth(), labs(MRT.CT2.GetHeight()));
  SetAutoLayout(true);
  Layout();
  Refresh();
}

/**
 *  Stops the controller, but timer still paints image
 *  @param[in] event Unused event   */
void CamViewMainFrame::OnPaintStop2(wxCommandEvent& WXUNUSED(event))
{
  if(CamPaint2->IsChecked())
    SetStatusText(_("Painting mode 2 off."));
  else
    SetStatusText(_("Painting mode 2 on."));
}



/** Initializes all the values to the default one.
 *  @param[in] event Unused event  */
void CamViewMainFrame::OnSetDefault(wxCommandEvent& WXUNUSED(event))
{
	//reset timer to default
//  MRT.SetPeriodMs(HwSetting::DEF_TIME);
        //reset video to default
  if(MRT.threshold!=NULL)
    MRT.threshold->SetDouble(CameraTool::DEFAULT_THR);

  camCanvas->Reset();
}


/**
 *  When the size is changed, it is called and then it refreshs the screen and sets the layouts   
 *
 *  @param[in] event Unused event
 *
 *  \warning If the drawing depends on the size of the window, 
 *  \warning clearing the DC explicitly may be needed and repainting the whole window. 
 *  \warning In which case, calling <CODE>wxWindow::Refresh()</CODE> may be needed to invalidate the entire window.  */
void CamViewMainFrame::OnSize(wxSizeEvent& WXUNUSED(event))
{   // if your drawing depends on the size of the window, 
    // you may need to clear the DC explicitly and repaint the whole window. 
    // In which case, you may need to call wxWindow::Refresh() to invalidate the entire window.
  SetAutoLayout(true);
  Layout();
  Refresh();
}


/** When a size is changed, it is called and then it refreshs the screen and sets the layouts 
 *  @param[in] event Unused event
 *  \warning If the drawing depends on the size of the window, 
 *  \warning clearing the DC explicitly may be needed and repainting the whole window. 
 *  \warning In which case, calling <CODE>wxWindow::Refresh()</CODE> may be needed to invalidate the entire window. */
void CamViewMainFrame::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
{
 // do nothing
}
