GLPreviewFrame.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00026 #include <bitset>
00027 #include <limits>
00028 #include <iostream>
00029 
00030 #include "hugin_config.h"
00031 
00032 #include <GL/glew.h>
00033 
00034 #include "panoinc_WX.h"
00035 #include "panoinc.h"
00036 
00037 #include "base_wx/platform.h"
00038 #include "base_wx/wxPlatform.h"
00039 #include "base_wx/LensTools.h"
00040 #include "algorithms/optimizer/ImageGraph.h"
00041 #include "algorithms/basic/LayerStacks.h"
00042 #include <algorithms/basic/CalculateOptimalROI.h>
00043 #include <algorithms/basic/CalculateCPStatistics.h>
00044 #include <algorithms/nona/FitPanorama.h>
00045 #include <algorithms/basic/CalculateMeanExposure.h>
00046 
00047 #include "base_wx/MyProgressDialog.h"
00048 #include "base_wx/wxPanoCommand.h"
00049 
00050 #include "hugin/config_defaults.h"
00051 #include "hugin/GLPreviewFrame.h"
00052 #include "hugin/huginApp.h"
00053 #include "hugin/MainFrame.h"
00054 #include "hugin/ImagesPanel.h"
00055 #include "base_wx/CommandHistory.h"
00056 #include "hugin/GLViewer.h"
00057 #include "hugin/TextKillFocusHandler.h"
00058 #include "hugin/PanoOperation.h"
00059 #include "hugin/PanoOutputDialog.h"
00060 #include "base_wx/PTWXDlg.h"
00061 #include "vigra_ext/InterestPoints.h"
00062 #include "vigra_ext/Correlation.h"
00063 #include "algorithms/control_points/CleanCP.h"
00064 #include "hugin_utils/openmp_lock.h"
00065 
00066 extern "C" {
00067 #include <pano13/queryfeature.h>
00068 }
00069 
00070 #include "ToolHelper.h"
00071 #include "Tool.h"
00072 #include "DragTool.h"
00073 #include "PreviewCropTool.h"
00074 #include "PreviewIdentifyTool.h"
00075 #include "PreviewDifferenceTool.h"
00076 #include "PreviewPanoMaskTool.h"
00077 #include "PreviewControlPointTool.h"
00078 #include "PreviewLayoutLinesTool.h"
00079 #include "PreviewColorPickerTool.h"
00080 #include "PreviewGuideTool.h"
00081 #include "PreviewEditCPTool.h"
00082 
00083 #include "ProjectionGridTool.h"
00084 #include "PanosphereSphereTool.h"
00085 
00086 #include "OverviewCameraTool.h"
00087 #include "OverviewOutlinesTool.h"
00088 
00089 #include <wx/progdlg.h>
00090 #include <wx/infobar.h>
00091 
00092 // a random id, hope this doesn't break something..
00093 enum {
00094     ID_TOGGLE_BUT = wxID_HIGHEST+500,
00095     PROJ_PARAM_NAMES_ID = wxID_HIGHEST+1300,
00096     PROJ_PARAM_VAL_ID = wxID_HIGHEST+1400,
00097     PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1500,
00098     PROJ_PARAM_RESET_ID = wxID_HIGHEST+1550,
00099     ID_TOGGLE_BUT_LEAVE = wxID_HIGHEST+1600,
00100     ID_FULL_SCREEN = wxID_HIGHEST+1710,
00101     ID_SHOW_ALL = wxID_HIGHEST+1711,
00102     ID_SHOW_NONE = wxID_HIGHEST+1712,
00103     ID_HIDE_HINTS = wxID_HIGHEST+1715
00104 };
00105 
00107 enum{
00108     mode_assistant=0,
00109     mode_preview,
00110     mode_layout,
00111     mode_projection,
00112     mode_drag,
00113     mode_crop
00114 };
00115 
00116 //------------------------------------------------------------------------------
00117 BEGIN_EVENT_TABLE(GLwxAuiFloatingFrame, wxAuiFloatingFrame)
00118     EVT_ACTIVATE(GLwxAuiFloatingFrame::OnActivate)
00119 END_EVENT_TABLE()
00120 
00121 BEGIN_EVENT_TABLE(GLPreviewFrame, wxFrame)
00122     EVT_CLOSE(GLPreviewFrame::OnClose)
00123     EVT_SHOW(GLPreviewFrame::OnShowEvent)
00124     //for some reason only key up is sent, key down event is not sent
00125 //    EVT_KEY_DOWN(GLPreviewFrame::KeyDown)
00126 //    EVT_KEY_UP(GLPreviewFrame::KeyUp)
00127     EVT_BUTTON(XRCID("preview_center_tool"), GLPreviewFrame::OnCenterHorizontally)
00128     EVT_BUTTON(XRCID("preview_fit_pano_tool"), GLPreviewFrame::OnFitPano)
00129     EVT_BUTTON(XRCID("preview_fit_pano_tool2"), GLPreviewFrame::OnFitPano)
00130     EVT_BUTTON(XRCID("preview_straighten_pano_tool"), GLPreviewFrame::OnStraighten)
00131     EVT_BUTTON(XRCID("apply_num_transform"), GLPreviewFrame::OnNumTransform)
00132     EVT_TEXT_ENTER(XRCID("input_yaw"), GLPreviewFrame::OnNumTransform)
00133     EVT_TEXT_ENTER(XRCID("input_pitch"), GLPreviewFrame::OnNumTransform)
00134     EVT_TEXT_ENTER(XRCID("input_roll"), GLPreviewFrame::OnNumTransform)
00135     EVT_TEXT_ENTER(XRCID("input_x"), GLPreviewFrame::OnNumTransform)
00136     EVT_TEXT_ENTER(XRCID("input_y"), GLPreviewFrame::OnNumTransform)
00137     EVT_TEXT_ENTER(XRCID("input_z"), GLPreviewFrame::OnNumTransform)
00138     EVT_BUTTON(ID_SHOW_ALL, GLPreviewFrame::OnShowAll)
00139     EVT_BUTTON(ID_SHOW_NONE, GLPreviewFrame::OnShowNone)
00140     EVT_CHECKBOX(XRCID("preview_photometric_tool"), GLPreviewFrame::OnPhotometric)
00141     EVT_TOGGLEBUTTON(XRCID("preview_identify_toggle_button"), GLPreviewFrame::OnIdentify)
00142     EVT_TOGGLEBUTTON(XRCID("preview_color_picker_toggle_button"), GLPreviewFrame::OnColorPicker)
00143     EVT_TOGGLEBUTTON(XRCID("preview_edit_cp_toggle_button"), GLPreviewFrame::OnEditCPTool)
00144     EVT_CHECKBOX(XRCID("preview_control_point_tool"), GLPreviewFrame::OnControlPoint)
00145     EVT_BUTTON(XRCID("preview_autocrop_tool"), GLPreviewFrame::OnAutocrop)
00146     EVT_BUTTON(XRCID("preview_stack_autocrop_tool"), GLPreviewFrame::OnStackAutocrop)
00147     EVT_NOTEBOOK_PAGE_CHANGED(XRCID("mode_toolbar_notebook"), GLPreviewFrame::OnSelectMode)
00148     EVT_NOTEBOOK_PAGE_CHANGING(XRCID("mode_toolbar_notebook"), GLPreviewFrame::OnToolModeChanging)
00149     EVT_BUTTON(ID_HIDE_HINTS, GLPreviewFrame::OnHideProjectionHints)
00150     EVT_BUTTON(XRCID("exposure_default_button"), GLPreviewFrame::OnDefaultExposure)
00151     EVT_SPIN_DOWN(XRCID("exposure_spin"), GLPreviewFrame::OnDecreaseExposure)
00152     EVT_SPIN_UP(XRCID("exposure_spin"), GLPreviewFrame::OnIncreaseExposure)
00153     EVT_CHOICE(XRCID("blend_mode_choice"), GLPreviewFrame::OnBlendChoice)
00154     EVT_CHOICE(XRCID("drag_mode_choice"), GLPreviewFrame::OnDragChoice)
00155     EVT_CHOICE(XRCID("projection_choice"), GLPreviewFrame::OnProjectionChoice)
00156     EVT_CHOICE(XRCID("overview_mode_choice"), GLPreviewFrame::OnOverviewModeChoice)
00157     EVT_CHOICE(XRCID("preview_guide_choice_crop"), GLPreviewFrame::OnGuideChanged)
00158     EVT_CHOICE(XRCID("preview_guide_choice_drag"), GLPreviewFrame::OnGuideChanged)
00159     EVT_CHOICE(XRCID("preview_guide_choice_proj"), GLPreviewFrame::OnGuideChanged)
00160     EVT_MENU(XRCID("action_show_overview"), GLPreviewFrame::OnOverviewToggle)
00161     EVT_MENU(XRCID("action_show_grid"), GLPreviewFrame::OnSwitchPreviewGrid)
00162     EVT_MENU(ID_CREATE_CP, GLPreviewFrame::OnCreateCP)
00163     EVT_MENU(ID_REMOVE_CP, GLPreviewFrame::OnRemoveCP)
00164     EVT_MENU_CLOSE(GLPreviewFrame::OnMenuClose)
00165 #ifndef __WXMAC__
00166         EVT_COMMAND_SCROLL(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
00167         EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV)
00168         EVT_COMMAND_SCROLL_CHANGED(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
00169 #else
00170     EVT_SCROLL_THUMBRELEASE(GLPreviewFrame::OnChangeFOV)
00171     EVT_COMMAND_SCROLL(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
00172     EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV)
00173     EVT_COMMAND_SCROLL_THUMBTRACK(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
00174 #endif
00175         EVT_SCROLL_THUMBTRACK(GLPreviewFrame::OnTrackChangeFOV)
00176     EVT_TEXT_ENTER(XRCID("pano_text_hfov"), GLPreviewFrame::OnHFOVChanged )
00177     EVT_TEXT_ENTER(XRCID("pano_text_vfov"), GLPreviewFrame::OnVFOVChanged )
00178     EVT_TEXT_ENTER(XRCID("pano_val_roi_left"), GLPreviewFrame::OnROIChanged)
00179     EVT_TEXT_ENTER(XRCID("pano_val_roi_top"), GLPreviewFrame::OnROIChanged)
00180     EVT_TEXT_ENTER(XRCID("pano_val_roi_right"), GLPreviewFrame::OnROIChanged)
00181     EVT_TEXT_ENTER(XRCID("pano_val_roi_bottom"), GLPreviewFrame::OnROIChanged)
00182     EVT_BUTTON(XRCID("reset_crop_button"), GLPreviewFrame::OnResetCrop)
00183     EVT_TEXT_ENTER(XRCID("exposure_text"), GLPreviewFrame::OnExposureChanged)
00184     EVT_COMMAND_RANGE(PROJ_PARAM_VAL_ID,PROJ_PARAM_VAL_ID+PANO_PROJECTION_MAX_PARMS,wxEVT_COMMAND_TEXT_ENTER,GLPreviewFrame::OnProjParameterChanged)
00185     EVT_BUTTON(PROJ_PARAM_RESET_ID, GLPreviewFrame::OnProjParameterReset)
00186     EVT_TOOL(ID_FULL_SCREEN, GLPreviewFrame::OnFullScreen)
00187     EVT_COLOURPICKER_CHANGED(XRCID("preview_background"), GLPreviewFrame::OnPreviewBackgroundColorChanged)
00188     EVT_MENU(XRCID("ID_SHOW_FULL_SCREEN_PREVIEW"), GLPreviewFrame::OnFullScreen)
00189     EVT_MENU(XRCID("action_show_main_frame"), GLPreviewFrame::OnShowMainFrame)
00190     EVT_MENU(XRCID("action_exit_preview"), GLPreviewFrame::OnUserExit)
00191     EVT_CHOICE     ( XRCID("ass_lens_type"), GLPreviewFrame::OnLensTypeChanged)
00192     EVT_TEXT_ENTER ( XRCID("ass_focal_length"), GLPreviewFrame::OnFocalLengthChanged)
00193     EVT_TEXT_ENTER ( XRCID("ass_crop_factor"), GLPreviewFrame::OnCropFactorChanged)
00194     EVT_BUTTON     ( XRCID("ass_load_images_button"), GLPreviewFrame::OnLoadImages)
00195     EVT_BUTTON     ( XRCID("ass_align_button"), GLPreviewFrame::OnAlign)
00196     EVT_BUTTON     ( XRCID("ass_create_button"), GLPreviewFrame::OnCreate)
00197     // context menu of select all button
00198     EVT_MENU(XRCID("selectMenu_selectAll"), GLPreviewFrame::OnSelectAllMenu)
00199     EVT_MENU(XRCID("selectMenu_selectMedian"), GLPreviewFrame::OnSelectMedianMenu)
00200     EVT_MENU(XRCID("selectMenu_selectBrightest"), GLPreviewFrame::OnSelectDarkestMenu)
00201     EVT_MENU(XRCID("selectMenu_selectDarkest"), GLPreviewFrame::OnSelectBrightestMenu)
00202     EVT_MENU(XRCID("selectMenu_keepCurrentSelection"), GLPreviewFrame::OnSelectKeepSelection)
00203     EVT_MENU(XRCID("selectMenu_resetSelection"), GLPreviewFrame::OnSelectResetSelection)
00204 END_EVENT_TABLE()
00205 
00206 BEGIN_EVENT_TABLE(ImageToogleButtonEventHandler, wxEvtHandler)
00207     EVT_ENTER_WINDOW(ImageToogleButtonEventHandler::OnEnter)
00208     EVT_LEAVE_WINDOW(ImageToogleButtonEventHandler::OnLeave)
00209     EVT_TOGGLEBUTTON(-1, ImageToogleButtonEventHandler::OnChange)
00210 END_EVENT_TABLE()
00211 
00212 BEGIN_EVENT_TABLE(ImageGroupButtonEventHandler, wxEvtHandler)
00213     EVT_ENTER_WINDOW(ImageGroupButtonEventHandler::OnEnter)
00214     EVT_LEAVE_WINDOW(ImageGroupButtonEventHandler::OnLeave)
00215     EVT_CHECKBOX(-1, ImageGroupButtonEventHandler::OnChange)
00216 END_EVENT_TABLE()
00217 
00218 #define PF_STYLE (wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN)
00219 GLwxAuiFloatingFrame* GLwxAuiManager::CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& p)
00220 {
00221     DEBUG_DEBUG("CREATING FLOATING FRAME");
00222     frame->PauseResize();
00223     GLwxAuiFloatingFrame* fl_frame = new GLwxAuiFloatingFrame(parent, this, p);
00224     DEBUG_DEBUG("CREATED FLOATING FRAME");
00225     return fl_frame;
00226 }
00227 
00228 void GLwxAuiFloatingFrame::OnActivate(wxActivateEvent& evt)
00229 {
00230     DEBUG_DEBUG("FRAME ACTIVATE");
00231     GLPreviewFrame * frame = ((GLwxAuiManager*) GetOwnerManager())->getPreviewFrame();
00232     frame->ContinueResize();
00233     evt.Skip();
00234 }
00235 
00236 void GLwxAuiFloatingFrame::OnMoveFinished()
00237 {
00238     DEBUG_DEBUG("FRAME ON MOVE FINISHED");
00239     GLPreviewFrame * frame = ((GLwxAuiManager*) GetOwnerManager())->getPreviewFrame();
00240     frame->PauseResize();
00241     wxAuiFloatingFrame::OnMoveFinished();
00242     DEBUG_DEBUG("FRAME AFTER ON MOVE FINISHED");
00243 }
00244 
00245 void GLPreviewFrame::PauseResize()
00246 {
00247     DEBUG_DEBUG("PAUSE RESIZE");
00248     GLresize = false;
00249 }
00250 
00251 void GLPreviewFrame::ContinueResize()
00252 {
00253     GLresize = true;
00254     wxSizeEvent event = wxSizeEvent(wxSize());
00255     m_GLPreview->Resized(event);
00256     m_GLOverview->Resized(event);
00257 }
00258 
00259 #include <iostream>
00260 GLPreviewFrame::GLPreviewFrame(wxFrame * frame, HuginBase::Panorama &pano)
00261     : wxFrame(frame,-1, _("Fast Panorama preview"), wxDefaultPosition, wxDefaultSize,
00262               PF_STYLE),
00263       m_pano(pano)
00264 {
00265 
00266         DEBUG_TRACE("");
00267 
00268     // initialize pointer
00269     preview_helper = NULL;
00270     panosphere_overview_helper = NULL;
00271     plane_overview_helper = NULL;
00272     crop_tool = NULL;
00273     drag_tool = NULL;
00274     color_picker_tool = NULL;
00275     edit_cp_tool = NULL;
00276     overview_drag_tool = NULL;
00277     identify_tool = NULL ;
00278     panosphere_overview_identify_tool = NULL;
00279     plane_overview_identify_tool = NULL;
00280     difference_tool = NULL;
00281     plane_difference_tool = NULL;
00282     panosphere_difference_tool = NULL;
00283     pano_mask_tool = NULL;
00284     preview_guide_tool = NULL;
00285     m_guiLevel=GUI_SIMPLE;
00286 #ifdef __WXGTK__
00287     loadedLayout=false;
00288 #endif
00289 
00290     m_mode = -1;
00291     m_oldProjFormat = -1;
00292     // add a status bar
00293     CreateStatusBar(3);
00294     int widths[3] = {-3, 150, 150};
00295     SetStatusWidths(3, widths);
00296     SetStatusText(wxT(""),1);
00297     SetStatusText(wxT(""),2);
00298     wxConfigBase * cfg = wxConfigBase::Get();
00299 
00300     wxPanel *tool_panel = wxXmlResource::Get()->LoadPanel(this,wxT("mode_panel"));
00301     XRCCTRL(*this,"preview_center_tool",wxButton)->SetBitmapMargins(0,0);
00302     XRCCTRL(*this,"preview_fit_pano_tool",wxButton)->SetBitmapMargins(0,0);
00303     XRCCTRL(*this,"preview_straighten_pano_tool",wxButton)->SetBitmapMargins(0,0);
00304     XRCCTRL(*this,"preview_fit_pano_tool2",wxButton)->SetBitmapMargins(0,0);
00305     XRCCTRL(*this,"preview_autocrop_tool",wxButton)->SetBitmapMargins(0,0);
00306     XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->SetBitmapMargins(0,0);
00307 
00308     m_tool_notebook = XRCCTRL(*this, "mode_toolbar_notebook", wxNotebook);
00309     m_identify_togglebutton = XRCCTRL(*this, "preview_identify_toggle_button", wxToggleButton);
00310     m_colorpicker_togglebutton = XRCCTRL(*this, "preview_color_picker_toggle_button", wxToggleButton);
00311     m_editCP_togglebutton = XRCCTRL(*this, "preview_edit_cp_toggle_button", wxToggleButton);
00312     wxBitmap bitmap;
00313 #if !wxCHECK_VERSION(3,1,1)
00314     bitmap.LoadFile(huginApp::Get()->GetXRCPath() + wxT("data/identify_tool.png"), wxBITMAP_TYPE_PNG);
00315     m_identify_togglebutton->SetBitmap(bitmap, wxTOP);
00316     bitmap.LoadFile(huginApp::Get()->GetXRCPath() + wxT("data/preview_white_balance.png"), wxBITMAP_TYPE_PNG);
00317     m_colorpicker_togglebutton->SetBitmap(bitmap, wxTOP);
00318     bitmap.LoadFile(huginApp::Get()->GetXRCPath() + wxT("data/preview_control_point_tool.png"), wxBITMAP_TYPE_PNG);
00319     m_editCP_togglebutton->SetBitmap(bitmap, wxTOP);
00320 #endif
00321 
00322     //build menu bar
00323 #ifdef __WXMAC__
00324     wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
00325 #endif
00326     wxMenuBar* simpleMenu=wxXmlResource::Get()->LoadMenuBar(this, wxT("preview_simple_menu"));
00327     m_filemenuSimple=wxXmlResource::Get()->LoadMenu(wxT("preview_file_menu"));
00328     m_filemenuAdvanced = wxXmlResource::Get()->LoadMenu(wxT("preview_file_menu_advanced"));
00329     MainFrame::Get()->GetFileHistory()->UseMenu(m_filemenuSimple->FindItem(XRCID("menu_mru_preview"))->GetSubMenu());
00330     MainFrame::Get()->GetFileHistory()->UseMenu(m_filemenuAdvanced->FindItem(XRCID("menu_mru_preview"))->GetSubMenu());
00331     MainFrame::Get()->GetFileHistory()->AddFilesToMenu();
00332     simpleMenu->Insert(0, m_filemenuSimple, _("&File"));
00333     SetMenuBar(simpleMenu);
00334 
00335     // initialize preview background color
00336     wxString c = cfg->Read(wxT("/GLPreviewFrame/PreviewBackground"),wxT(HUGIN_PREVIEW_BACKGROUND));
00337     m_preview_background_color = wxColour(c);
00338     XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->SetColour(m_preview_background_color);
00339     XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->Refresh();
00340     XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->Update();
00341   
00342     m_topsizer = new wxBoxSizer( wxVERTICAL );
00343 
00344     wxPanel * toggle_panel = new wxPanel(this);
00345 
00346     bool overview_hidden;
00347     cfg->Read(wxT("/GLPreviewFrame/overview_hidden"), &overview_hidden, false);
00348     GetMenuBar()->FindItem(XRCID("action_show_overview"))->Check(!overview_hidden);
00349 
00350     m_ToggleButtonSizer = new wxStaticBoxSizer(
00351         new wxStaticBox(toggle_panel, -1, _("displayed images")),
00352     wxHORIZONTAL );
00353     toggle_panel->SetSizer(m_ToggleButtonSizer);
00354 
00355         m_ButtonPanel = new wxScrolledWindow(toggle_panel, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
00356         //Horizontal scroll bars only
00357         m_ButtonPanel->SetScrollRate(10, 0);
00358     m_ButtonSizer = new wxBoxSizer(wxHORIZONTAL);
00359     m_ButtonPanel->SetAutoLayout(true);
00360         m_ButtonPanel->SetSizer(m_ButtonSizer);
00361 
00362     wxPanel *panel = new wxPanel(toggle_panel);
00363     bitmap.LoadFile(huginApp::Get()->GetXRCPath()+wxT("data/preview_show_all.png"),wxBITMAP_TYPE_PNG);
00364     wxString showAllLabel(_("All"));
00365     showAllLabel.Append(wxT("\u25bc"));
00366     m_selectAllButton = new wxButton(panel, ID_SHOW_ALL, showAllLabel, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
00367     m_selectAllButton->SetBitmap(bitmap, wxLEFT);
00368     m_selectAllButton->SetBitmapMargins(0, 0);
00369     m_selectAllButton->Connect(wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(GLPreviewFrame::OnSelectContextMenu), NULL, this);
00370     m_selectAllMenu = wxXmlResource::Get()->LoadMenu(wxT("preview_select_menu"));
00371     // read last used setting
00372     long mode = cfg->Read(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
00373     m_selectAllMode = static_cast<SelectAllMode>(mode);
00374     switch (m_selectAllMode)
00375     {
00376         case SELECT_MEDIAN_IMAGES:
00377             m_selectAllMenu->Check(XRCID("selectMenu_selectMedian"), true);
00378             break;
00379         case SELECT_DARKEST_IMAGES:
00380             m_selectAllMenu->Check(XRCID("selectMenu_selectDarkest"), true);
00381             break;
00382         case SELECT_BRIGHTEST_IMAGES:
00383             m_selectAllMenu->Check(XRCID("selectMenu_selectBrightest"), true);
00384             break;
00385         case SELECT_ALL_IMAGES:
00386         default:
00387             m_selectAllMenu->Check(XRCID("selectMenu_selectAll"), true);
00388             break;
00389     };
00390     m_selectKeepSelection = (cfg->Read(wxT("/GLPreviewFrame/SelectAllKeepSelection"), 1l) == 1l);
00391     if (m_selectKeepSelection)
00392     {
00393         m_selectAllMenu->Check(XRCID("selectMenu_keepCurrentSelection"), true);
00394     }
00395     else
00396     {
00397         m_selectAllMenu->Check(XRCID("selectMenu_resetSelection"), true);
00398     };
00399     bitmap.LoadFile(huginApp::Get()->GetXRCPath()+wxT("data/preview_show_none.png"),wxBITMAP_TYPE_PNG);
00400     wxButton* select_none=new wxButton(panel,ID_SHOW_NONE,_("None"),wxDefaultPosition,wxDefaultSize,wxBU_EXACTFIT);
00401     select_none->SetBitmap(bitmap,wxLEFT);
00402     select_none->SetBitmapMargins(0,0);
00403 
00404     wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
00405     sizer->Add(m_selectAllButton,0,wxALIGN_CENTER_VERTICAL | wxLEFT | wxTOP | wxBOTTOM,5);
00406     sizer->Add(select_none,0,wxALIGN_CENTER_VERTICAL | wxRIGHT | wxTOP | wxBOTTOM,5);
00407     panel->SetSizer(sizer);
00408     m_ToggleButtonSizer->Add(panel, 0, wxALIGN_CENTER_VERTICAL);
00409     m_ToggleButtonSizer->Add(m_ButtonPanel, 1, wxALIGN_CENTER_VERTICAL, 0);
00410 
00411     m_topsizer->Add(tool_panel, 0, wxEXPAND | wxALL, 2);
00412     m_topsizer->Add(toggle_panel, 0, wxEXPAND | wxBOTTOM, 5);
00413 
00414     m_infoBar = new wxInfoBar(this);
00415     m_infoBar->AddButton(ID_HIDE_HINTS,_("Hide"));
00416     m_infoBar->Connect(ID_HIDE_HINTS,wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(GLPreviewFrame::OnHideProjectionHints),NULL,this);
00417     m_topsizer->Add(m_infoBar, 0, wxEXPAND);
00418 
00419     //create panel that will hold gl canvases
00420     wxPanel * vis_panel = new wxPanel(this);
00421 
00422     wxPanel * preview_panel = new wxPanel(vis_panel);
00423     wxPanel * overview_panel = new wxPanel(vis_panel);
00424 
00425     // create our Viewers
00426     int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0};
00427     m_GLPreview = new GLPreview(preview_panel, pano, args, this);
00428     m_GLOverview = new GLOverview(overview_panel, pano, args, this, m_GLPreview->GetContext());
00429     m_GLOverview->SetMode(GLOverview::PANOSPHERE);
00430       
00431 #ifdef __WXGTK__
00432     // on wxGTK we can not create the OpenGL context with a hidden window
00433     // therefore we need to create the overview window open and later hide it
00434     overview_hidden=false;
00435 #endif
00436     m_GLOverview->SetActive(!overview_hidden);
00437 
00438     // set the AUI manager to our panel
00439     m_mgr = new GLwxAuiManager(this, m_GLPreview, m_GLOverview);
00440     m_mgr->SetManagedWindow(vis_panel);
00441     vis_panel->SetMinSize(wxSize(200,150));
00442     
00443     //create the sizer for the preview
00444     wxFlexGridSizer * flexSizer = new wxFlexGridSizer(2,0,5,5);
00445     flexSizer->AddGrowableCol(0);
00446     flexSizer->AddGrowableRow(0);
00447 
00448     //overview sizer
00449     wxBoxSizer * overview_sizer = new wxBoxSizer(wxVERTICAL);
00450 
00451 
00452     flexSizer->Add(m_GLPreview,
00453                   1,        // not vertically stretchable
00454                   wxEXPAND | // horizontally stretchable
00455                   wxALL,    // draw border all around
00456                   5);       // border width
00457 
00458     m_VFOVSlider = new wxSlider(preview_panel, -1, 1,
00459                                 1, 180,
00460                                 wxDefaultPosition, wxDefaultSize,
00461                                 wxSL_VERTICAL | wxSL_AUTOTICKS,
00462                                 wxDefaultValidator,
00463                                 _("VFOV"));
00464     m_VFOVSlider->SetLineSize(1);
00465     m_VFOVSlider->SetPageSize(10);
00466     m_VFOVSlider->SetTickFreq(5);
00467     m_VFOVSlider->SetToolTip(_("drag to change the vertical field of view"));
00468 
00469     flexSizer->Add(m_VFOVSlider, 0, wxEXPAND);
00470 
00471     m_HFOVSlider = new wxSlider(preview_panel, -1, 1,
00472                                 1, 360,
00473                                 wxDefaultPosition, wxDefaultSize,
00474                                 wxSL_HORIZONTAL | wxSL_AUTOTICKS,
00475                                 wxDefaultValidator,
00476                                 _("HFOV"));
00477     m_HFOVSlider->SetPageSize(10);
00478     m_HFOVSlider->SetLineSize(1);
00479     m_HFOVSlider->SetTickFreq(5);
00480 
00481     m_HFOVSlider->SetToolTip(_("drag to change the horizontal field of view"));
00482 
00483     m_exposureText = XRCCTRL(*this, "exposure_text", wxTextCtrl);
00484     DEBUG_ASSERT(m_exposureText);
00485     m_exposureText->PushEventHandler(new TextKillFocusHandler(this));
00486     m_HFOVText = XRCCTRL(*this, "pano_text_hfov" ,wxTextCtrl);
00487     DEBUG_ASSERT(m_HFOVText);
00488     m_HFOVText->PushEventHandler(new TextKillFocusHandler(this));
00489     m_VFOVText = XRCCTRL(*this, "pano_text_vfov" ,wxTextCtrl);
00490     DEBUG_ASSERT(m_VFOVText);
00491     m_VFOVText->PushEventHandler(new TextKillFocusHandler(this));
00492 
00493     m_ROILeftTxt = XRCCTRL(*this, "pano_val_roi_left", wxTextCtrl);
00494     DEBUG_ASSERT(m_ROILeftTxt);
00495     m_ROILeftTxt->PushEventHandler(new TextKillFocusHandler(this));
00496 
00497     m_ROIRightTxt = XRCCTRL(*this, "pano_val_roi_right", wxTextCtrl);
00498     DEBUG_ASSERT(m_ROIRightTxt);
00499     m_ROIRightTxt->PushEventHandler(new TextKillFocusHandler(this));
00500 
00501     m_ROITopTxt = XRCCTRL(*this, "pano_val_roi_top", wxTextCtrl);
00502     DEBUG_ASSERT(m_ROITopTxt);
00503     m_ROITopTxt->PushEventHandler(new TextKillFocusHandler(this));
00504 
00505     m_ROIBottomTxt = XRCCTRL(*this, "pano_val_roi_bottom", wxTextCtrl);
00506     DEBUG_ASSERT(m_ROIBottomTxt);
00507     m_ROIBottomTxt->PushEventHandler(new TextKillFocusHandler(this));
00508 
00509     m_GuideChoiceCrop = XRCCTRL(*this, "preview_guide_choice_crop", wxChoice);
00510     m_GuideChoiceProj = XRCCTRL(*this, "preview_guide_choice_proj", wxChoice);
00511     m_GuideChoiceDrag = XRCCTRL(*this, "preview_guide_choice_drag", wxChoice);
00512     int guide=cfg->Read(wxT("/GLPreviewFrame/guide"),0l);
00513     m_GuideChoiceCrop->SetSelection(guide);
00514     m_GuideChoiceProj->SetSelection(guide);
00515     m_GuideChoiceDrag->SetSelection(guide);
00516 
00517     flexSizer->Add(m_HFOVSlider, 0, wxEXPAND);
00518 
00519     wxPanel *overview_command_panel = wxXmlResource::Get()->LoadPanel(overview_panel,wxT("overview_command_panel"));
00520     m_OverviewModeChoice = XRCCTRL(*this, "overview_mode_choice", wxChoice);
00521     overview_command_panel->SetSize(0,0,200,20,wxSIZE_AUTO_WIDTH);
00522 
00523     overview_sizer->Add(overview_command_panel, 0, wxEXPAND);
00524     overview_sizer->Add(m_GLOverview, 1, wxEXPAND);
00525 
00526     bool showGrid;
00527     cfg->Read(wxT("/GLPreviewFrame/showPreviewGrid"),&showGrid,true);
00528     GetMenuBar()->FindItem(XRCID("action_show_grid"))->Check(showGrid);
00529 
00530     preview_panel->SetSizer(flexSizer);
00531     overview_panel->SetSizer(overview_sizer);
00532 
00533     m_mgr->AddPane(preview_panel, 
00534         wxAuiPaneInfo(
00535             ).Name(wxT("preview")
00536             ).MinSize(300,200
00537             ).CloseButton(false
00538             ).CaptionVisible(false
00539             ).Caption(_("Preview")
00540             ).Floatable(false
00541             ).Dockable(false
00542             ).Center(
00543             )
00544         );
00545 
00546     m_mgr->AddPane(overview_panel, 
00547         wxAuiPaneInfo(
00548             ).Name(wxT("overview")
00549             ).MinSize(300,200
00550             ).CloseButton(false
00551             ).CaptionVisible(
00552             ).Caption(_("Overview")
00553             ).FloatingSize(100,100
00554             ).FloatingPosition(500,500
00555             ).Dockable(true
00556             ).PinButton(
00557             ).Left(
00558             ).Show(!overview_hidden
00559             )
00560         );
00561 
00562 
00563     m_topsizer->Add(vis_panel, 1, wxEXPAND);
00564 
00565     //assistant related controls
00566     m_imagesText = XRCCTRL(*this, "ass_load_images_text", wxStaticText);
00567     DEBUG_ASSERT(m_imagesText);
00568 
00569     m_lensTypeChoice = XRCCTRL(*this, "ass_lens_type", wxChoice);
00570     DEBUG_ASSERT(m_lensTypeChoice);
00571     FillLensProjectionList(m_lensTypeChoice);
00572     m_lensTypeChoice->SetSelection(0);
00573 
00574     m_focalLengthText = XRCCTRL(*this, "ass_focal_length", wxTextCtrl);
00575     DEBUG_ASSERT(m_focalLengthText);
00576     m_focalLengthText->PushEventHandler(new TextKillFocusHandler(this));
00577 
00578     m_cropFactorText = XRCCTRL(*this, "ass_crop_factor", wxTextCtrl);
00579     DEBUG_ASSERT(m_cropFactorText);
00580     m_cropFactorText->PushEventHandler(new TextKillFocusHandler(this));
00581 
00582     m_alignButton = XRCCTRL(*this, "ass_align_button", wxButton);
00583     DEBUG_ASSERT(m_alignButton);
00584     m_alignButton->Disable();
00585 
00586     m_createButton = XRCCTRL(*this, "ass_create_button", wxButton);
00587     DEBUG_ASSERT(m_createButton);
00588     m_createButton->Disable();
00589 
00590     m_ProjectionChoice = XRCCTRL(*this,"projection_choice",wxChoice);
00591 
00592     /* populate with all available projection types */
00593     int nP = panoProjectionFormatCount();
00594     for(int n=0; n < nP; n++) {
00595         pano_projection_features proj;
00596         if (panoProjectionFeaturesQuery(n, &proj)) {
00597             wxString str2(proj.name, wxConvLocal);
00598             m_ProjectionChoice->Append(wxGetTranslation(str2));
00599         }
00600     }
00601     m_ProjectionChoice->SetSelection(2);
00602 
00604     // Blend mode
00605     // remaining blend mode should be added after OpenGL context has been created
00606     // see FillBlendMode()
00607     m_differenceIndex = -1;
00608     // create choice item
00609     m_BlendModeChoice = XRCCTRL(*this,"blend_mode_choice",wxChoice);
00610     m_BlendModeChoice->Append(_("normal"));
00611     m_BlendModeChoice->SetSelection(0);
00612 
00613     m_DragModeChoice = XRCCTRL(*this, "drag_mode_choice", wxChoice);
00614     SetGuiLevel(GUI_SIMPLE);
00615     bool individualDrag;
00616     cfg->Read(wxT("/GLPreviewFrame/individualDragMode"), &individualDrag, false);
00617     if(individualDrag)
00618     {
00619         m_DragModeChoice->SetSelection(1);
00620     }
00621     else
00622     {
00623         m_DragModeChoice->SetSelection(0);
00624     };
00625     // default drag mode
00626     GLPreviewFrame::DragChoiceLayout(0);
00627 
00628     // TODO implement hdr display in OpenGL, if possible?
00629     // Disabled until someone can figure out HDR display in OpenGL.
00630     /*
00632     // LDR, HDR
00633     blendModeSizer->Add(new wxStaticText(this, -1, _("Output:")),
00634                         0,        // not vertically strechable
00635                         wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
00636                         5);       // border width
00637 
00638     m_choices[0] = _("LDR");
00639     m_choices[1] = _("HDR");
00640     m_outputModeChoice = new wxChoice(this, ID_OUTPUTMODE_CHOICE,
00641                                       wxDefaultPosition, wxDefaultSize,
00642                                       2, m_choices);
00643     m_outputModeChoice->SetSelection(0);
00644     blendModeSizer->Add(m_outputModeChoice,
00645                         0,
00646                         wxALL | wxALIGN_CENTER_VERTICAL,
00647                         5);
00648     */
00649     
00651     // exposure
00652     m_defaultExposureBut = XRCCTRL(*this, "exposure_default_button", wxBitmapButton);
00653 
00654     m_exposureTextCtrl = XRCCTRL(*this, "exposure_text", wxTextCtrl);
00655     m_exposureSpinBut = XRCCTRL(*this, "exposure_spin", wxSpinButton); 
00656     m_exposureSpinBut->SetValue(0);
00657 
00658     m_projection_panel = XRCCTRL(*this, "projection_panel", wxPanel);
00659     m_projParamSizer = new wxBoxSizer(wxHORIZONTAL);
00660 
00661     wxBitmapButton * resetProjButton=new wxBitmapButton(m_projection_panel, PROJ_PARAM_RESET_ID, 
00662         wxArtProvider::GetBitmap(wxART_REDO));
00663     resetProjButton->SetToolTip(_("Resets the projection's parameters to their default values."));
00664     m_projParamSizer->Add(resetProjButton, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
00665 
00666     m_projParamNamesLabel.resize(PANO_PROJECTION_MAX_PARMS);
00667     m_projParamTextCtrl.resize(PANO_PROJECTION_MAX_PARMS);
00668     m_projParamSlider.resize(PANO_PROJECTION_MAX_PARMS);
00669 
00670     for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++) {
00671 
00672         wxBoxSizer* paramBoxSizer = new wxBoxSizer(wxVERTICAL);
00673         m_projParamNamesLabel[i] = new wxStaticText(m_projection_panel, PROJ_PARAM_NAMES_ID+i, _("param:"));
00674         paramBoxSizer->Add(m_projParamNamesLabel[i],
00675                         0,        // not vertically strechable
00676                         wxLEFT | wxRIGHT, // draw border all around
00677                         5);       // border width
00678         m_projParamTextCtrl[i] = new wxTextCtrl(m_projection_panel, PROJ_PARAM_VAL_ID+i, wxT("0"),
00679                                     wxDefaultPosition, wxSize(35,-1), wxTE_PROCESS_ENTER);
00680         m_projParamTextCtrl[i]->PushEventHandler(new TextKillFocusHandler(this));
00681         paramBoxSizer->Add(m_projParamTextCtrl[i],
00682                         0,        // not vertically strechable
00683                         wxLEFT | wxRIGHT, // draw border all around
00684                         5);       // border width
00685 
00686         m_projParamSizer->Add(paramBoxSizer);
00687         m_projParamSlider[i] = new wxSlider(m_projection_panel, PROJ_PARAM_SLIDER_ID+i, 0, -90, 90);
00688         m_projParamSizer->Add(m_projParamSlider[i],
00689                         1,        // not vertically strechable
00690                         wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL , // draw border all around
00691                         5);       // border width
00692     }
00693 
00694     m_projection_panel->GetSizer()->Add(m_projParamSizer, 1, wxALIGN_CENTER_VERTICAL);
00695 
00696     // do not show projection param sizer
00697     m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
00698 
00699     // the initial size as calculated by the sizers
00700     this->SetSizer( m_topsizer );
00701     m_topsizer->SetSizeHints( this );
00702 
00703     // set the minimize icon
00704 #ifdef __WXMSW__
00705     wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
00706 #else
00707     wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
00708 #endif
00709     SetIcon(myIcon);
00710 
00711     m_pano.addObserver(this);
00712 
00713     RestoreFramePosition(this, wxT("GLPreviewFrame"));
00714     
00715 #ifdef __WXMSW__
00716     // wxFrame does have a strange background color on Windows..
00717     this->SetBackgroundColour(m_GLPreview->GetBackgroundColour());
00718 #endif
00719 
00720     m_showProjectionHints = cfg->Read(wxT("/GLPreviewFrame/ShowProjectionHints"), HUGIN_SHOW_PROJECTION_HINTS) == 1;
00721     m_degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigitsEdit"),3);
00722 
00723      // tell the manager to "commit" all the changes just made
00724     m_mgr->Update();
00725 
00726     if (cfg->Read(wxT("/GLPreviewFrame/isShown"), 0l) != 0)
00727     {
00728 #if defined __WXMSW__ || defined __WXMAC__
00729         InitPreviews();
00730         Show();
00731 #else
00732         Show();
00733         LoadOpenGLLayout();
00734 #endif
00735     }
00736     SetDropTarget(new PanoDropTarget(m_pano, true));
00737 #if defined __WXMAC__
00738     Layout();
00739     Update();
00740 #endif
00741 }
00742 
00743 void GLPreviewFrame::LoadOpenGLLayout()
00744 {
00745 #ifdef __WXGTK__
00746     if(loadedLayout)
00747     {
00748         return;
00749     };
00750     loadedLayout=true;
00751 #endif
00752     wxString OpenGLLayout=wxConfig::Get()->Read(wxT("/GLPreviewFrame/OpenGLLayout"));
00753     if(!OpenGLLayout.IsEmpty())
00754     {
00755         m_mgr->LoadPerspective(OpenGLLayout,true);
00756 #ifdef __WXGTK__
00757         if(!GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked())
00758         {
00759             wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
00760             if (inf.IsOk())
00761             {
00762                 inf.Hide();
00763             }
00764             m_GLOverview->SetActive(false);
00765         };
00766         m_mgr->Update();
00767         wxShowEvent dummy;
00768         dummy.SetShow(true);
00769         OnShowEvent(dummy);
00770 #endif
00771     };
00772     FillBlendChoice();
00773 };
00774 
00775 GLPreviewFrame::~GLPreviewFrame()
00776 {
00777     DEBUG_TRACE("dtor writing config");
00778     wxConfigBase * cfg = wxConfigBase::Get();
00779 
00780     StoreFramePosition(this, wxT("GLPreviewFrame"));
00781 
00782     if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) {
00783         cfg->Write(wxT("/GLPreviewFrame/isShown"), 1l);
00784     } else {
00785         cfg->Write(wxT("/GLPreviewFrame/isShown"), 0l);
00786     }
00787 
00788     cfg->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection());
00789     cfg->Write(wxT("/GLPreviewFrame/OpenGLLayout"), m_mgr->SavePerspective());
00790     cfg->Write(wxT("/GLPreviewFrame/overview_hidden"), !(GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()));
00791     cfg->Write(wxT("/GLPreviewFrame/showPreviewGrid"), GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked());
00792     cfg->Write(wxT("/GLPreviewFrame/individualDragMode"), individualDragging());
00793     cfg->Write(wxT("/GLPreviewFrame/guide"),m_GuideChoiceProj->GetSelection());
00794     
00795     // delete all of the tools. When the preview is never used we never get an
00796     // OpenGL context and therefore don't create the tools.
00797     if (crop_tool)
00798     {
00799         preview_helper->DeactivateTool(crop_tool); delete crop_tool;
00800         preview_helper->DeactivateTool(drag_tool); delete drag_tool;
00801         preview_helper->DeactivateTool(color_picker_tool); delete color_picker_tool;
00802         preview_helper->DeactivateTool(edit_cp_tool); delete edit_cp_tool;
00803         preview_helper->DeactivateTool(identify_tool); delete identify_tool;
00804         preview_helper->DeactivateTool(difference_tool); delete difference_tool;
00805         preview_helper->DeactivateTool(pano_mask_tool); delete pano_mask_tool;
00806         preview_helper->DeactivateTool(preview_control_point_tool); delete preview_control_point_tool;
00807         preview_helper->DeactivateTool(m_preview_layoutLinesTool); delete m_preview_layoutLinesTool;
00808         preview_helper->DeactivateTool(preview_projection_grid); delete preview_projection_grid;
00809         preview_helper->DeactivateTool(preview_guide_tool); delete preview_guide_tool;
00810     }
00811     if (panosphere_overview_identify_tool) {
00812         panosphere_overview_helper->DeactivateTool(overview_drag_tool); delete overview_drag_tool;
00813         panosphere_overview_helper->DeactivateTool(panosphere_overview_camera_tool); delete panosphere_overview_camera_tool;
00814         panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool); delete panosphere_overview_identify_tool;
00815         panosphere_overview_helper->DeactivateTool(panosphere_sphere_tool); delete panosphere_sphere_tool;
00816         panosphere_overview_helper->DeactivateTool(overview_projection_grid); delete overview_projection_grid;
00817         panosphere_overview_helper->DeactivateTool(overview_outlines_tool); delete overview_outlines_tool;
00818         panosphere_overview_helper->DeactivateTool(panosphere_difference_tool); delete panosphere_difference_tool;
00819         panosphere_overview_helper->DeactivateTool(m_panosphere_layoutLinesTool); delete m_panosphere_layoutLinesTool;
00820         panosphere_overview_helper->DeactivateTool(panosphere_control_point_tool); delete panosphere_control_point_tool;
00821     }
00822     if (plane_overview_identify_tool) {
00823         plane_overview_helper->DeactivateTool(plane_overview_identify_tool); delete plane_overview_identify_tool;
00824         plane_overview_helper->DeactivateTool(plane_overview_camera_tool); delete plane_overview_camera_tool;
00825         plane_overview_helper->DeactivateTool(plane_difference_tool); delete plane_difference_tool;
00826         plane_overview_helper->DeactivateTool(plane_overview_outlines_tool); delete plane_overview_outlines_tool;
00827         plane_overview_helper->DeactivateTool(m_plane_layoutLinesTool); delete m_plane_layoutLinesTool;
00828         plane_overview_helper->DeactivateTool(plane_control_point_tool); delete plane_control_point_tool;
00829     }
00830     m_focalLengthText->PopEventHandler(true);
00831     m_cropFactorText->PopEventHandler(true);
00832     m_exposureText->PopEventHandler(true);
00833     m_HFOVText->PopEventHandler(true);
00834     m_VFOVText->PopEventHandler(true);
00835     m_ROILeftTxt->PopEventHandler(true);
00836     m_ROIRightTxt->PopEventHandler(true);
00837     m_ROITopTxt->PopEventHandler(true);
00838     m_ROIBottomTxt->PopEventHandler(true);
00839     for (int i=0; i < m_ToggleButtons.size(); i++)
00840     {
00841         m_ToggleButtons[i]->PopEventHandler(true);
00842         m_GroupToggleButtons[i]->PopEventHandler(true);
00843     }
00844     for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++)
00845     {
00846         m_projParamTextCtrl[i]->PopEventHandler(true);
00847     };
00848     m_pano.removeObserver(this);
00849 
00850      // deinitialize the frame manager
00851      m_mgr->UnInit();
00852      if (m_mgr) {
00853         delete m_mgr;
00854      }
00855      if(m_guiLevel!=GUI_SIMPLE)
00856      {
00857          delete m_filemenuSimple;
00858      }
00859      else
00860      {
00861          delete m_filemenuAdvanced;
00862      };
00863 
00864     DEBUG_TRACE("dtor end");
00865 }
00866 
00867 void GLPreviewFrame::InitPreviews()
00868 {
00869     if(preview_helper==NULL || panosphere_overview_helper==NULL || plane_overview_helper==NULL)
00870     {
00871         m_GLPreview->SetUpContext();
00872         m_GLOverview->SetUpContext();
00873         LoadOpenGLLayout();
00874     };
00875 };
00876 
00880 void GLPreviewFrame::updateBlendMode()
00881 {
00882     if (m_BlendModeChoice != NULL)
00883     {
00884         int index=m_BlendModeChoice->GetSelection();
00885         if(index==0)
00886         {
00887             // normal mode
00888             if (preview_helper != NULL 
00889                 && difference_tool != NULL)
00890             {
00891                 preview_helper->DeactivateTool(difference_tool);
00892             };
00893 
00894             if (panosphere_overview_helper != NULL 
00895                 && panosphere_difference_tool != NULL)
00896             {
00897                 panosphere_overview_helper->DeactivateTool(panosphere_difference_tool);
00898             };
00899 
00900             if (plane_overview_helper != NULL 
00901                 && plane_difference_tool != NULL)
00902             {
00903                 plane_overview_helper->DeactivateTool(plane_difference_tool);
00904             };
00905 
00906 
00907         }
00908         else
00909         {
00910             if(index==m_differenceIndex)
00911             {
00912                 // difference mode
00913                 if (preview_helper != NULL 
00914                     && identify_tool != NULL 
00915                     && difference_tool != NULL )
00916                 {
00917                     identify_tool->setConstantOn(false);
00918 //                    preview_helper->DeactivateTool(identify_tool);
00919                     m_identify_togglebutton->SetValue(false);
00920                     preview_helper->ActivateTool(difference_tool);
00921                     CleanButtonColours();
00922                 };
00923 
00924                 // difference mode
00925                 if (panosphere_overview_helper != NULL 
00926                     && panosphere_overview_identify_tool != NULL 
00927                     && panosphere_difference_tool != NULL)
00928                 {
00929 //                    panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
00930                     panosphere_overview_identify_tool->setConstantOn(false);
00931                     panosphere_overview_helper->ActivateTool(panosphere_difference_tool);
00932                 };
00933 
00934                 // difference mode
00935                 if (plane_overview_helper != NULL 
00936                     && plane_overview_identify_tool != NULL 
00937                     && plane_difference_tool != NULL)
00938                 {
00939 //                    plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
00940                     plane_overview_identify_tool->setConstantOn(false);
00941                     plane_overview_helper->ActivateTool(plane_difference_tool);
00942                 };
00943 
00944             }
00945             else
00946             {
00947                 DEBUG_WARN("Unknown blend mode selected");
00948             };
00949         }
00950     }
00951 }
00952 
00953 void GLPreviewFrame::UpdateRoiDisplay(const HuginBase::PanoramaOptions opts)
00954 {
00955     m_ROILeftTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().left() ));
00956     m_ROIRightTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().right() ));
00957     m_ROITopTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().top() ));
00958     m_ROIBottomTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().bottom() ));
00959 };
00960 
00961 void GLPreviewFrame::panoramaChanged(HuginBase::Panorama &pano)
00962 {
00963     m_lensTypeChoice->Enable(pano.getNrOfImages()>0);
00964     m_focalLengthText->Enable(pano.getNrOfImages()>0);
00965     m_cropFactorText->Enable(pano.getNrOfImages()>0);
00966     m_alignButton->Enable(pano.getNrOfImages()>0);
00967 
00968     if(pano.getNrOfImages()==0)
00969     {
00970         m_createButton->Disable();
00971         m_imagesText->SetLabel(_("No images loaded."));
00972     }
00973     else
00974     {
00975         bool enableCreate = false;
00976         // check if images are at position 0
00977         for (size_t i = 0; i < pano.getNrOfImages(); ++i)
00978         {
00979             const HuginBase::SrcPanoImage& img = pano.getImage(i);
00980             if (img.getYaw() != 0.0 || img.getPitch() != 0.0 || img.getRoll() != 0.0)
00981             {
00982                 enableCreate = true;
00983                 break;
00984             };
00985         };
00986         if (!enableCreate && pano.getNrOfImages() == 1)
00987         {
00988             // some more checks for single image projects
00989             if (pano.getOptions().getProjection() != HuginBase::PanoramaOptions::EQUIRECTANGULAR)
00990             {
00991                 enableCreate = true;
00992             };
00993             if (pano.getOptions().getROI() != vigra::Rect2D(pano.getOptions().getSize()))
00994             {
00995                 enableCreate = true;
00996             };
00997         };
00998         // disable create button after loading images
00999         const std::string lastCmd=PanoCommand::GlobalCmdHist::getInstance().getLastCommandName();
01000         if (lastCmd == "add images" || lastCmd== "add and distribute images")
01001         {
01002             enableCreate = false;
01003         }
01004         m_createButton->Enable(enableCreate);
01005 
01006         // in wxWidgets 2.9, format must have types that exactly match.
01007         // However std::size_t could be any unsiged integer, so we cast it to
01008         // unsigned long.int to be on the safe side.
01009         wxString imgMsg = wxString::Format(_("%lu images loaded."), (unsigned long int) pano.getNrOfImages());
01010         m_imagesText->SetLabel(imgMsg);
01011 
01012         // update data in lens display
01013         const HuginBase::SrcPanoImage& img = pano.getImage(0);
01014         SelectListValue(m_lensTypeChoice, img.getProjection());
01015         double focal_length = HuginBase::SrcPanoImage::calcFocalLength(img.getProjection(), img.getHFOV(), img.getCropFactor(), img.getSize());
01016         // use ChangeValue explicit, SetValue would create EVT_TEXT event which collides with our TextKillFocusHandler
01017         m_focalLengthText->ChangeValue(hugin_utils::doubleTowxString(focal_length,m_degDigits));
01018         m_cropFactorText->ChangeValue(hugin_utils::doubleTowxString(img.getCropFactor(),m_degDigits));
01019     }
01020 
01021     if (pano.getNrOfImages() > 1)
01022     {
01023         // in wxWidgets 2.9, format must have types that exactly match.
01024         // However std::size_t could be any unsiged integer, so we cast it to
01025         // unsigned long.int to be on the safe side.
01026         wxString alignMsg = wxString::Format(_("Images are connected by %lu control points.\n"), (unsigned long int) pano.getCtrlPoints().size());
01027 
01028         if (m_pano.getNrOfCtrlPoints() > 0)
01029         {
01030             // find components..
01031             HuginGraph::ImageGraph graph(m_pano);
01032             const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
01033             if (comps.size() > 1)
01034             {
01035                 alignMsg += wxString::Format(_("%lu unconnected image groups found: %s\n"), static_cast<unsigned long int>(comps.size()), Components2Str(comps).c_str());
01036             }
01037             else
01038             {
01039                 if (m_pano.needsOptimization())
01040                 {
01041                     alignMsg += _("Images or control points have changed, new alignment is needed.");
01042                 }
01043                 else
01044                 {
01045                     HuginBase::CalculateCPStatisticsError calcStats(m_pano, MainFrame::Get()->GetOptimizeOnlyActiveImages(), MainFrame::Get()->GetOptimizeIgnoreLineCp());
01046                     calcStats.run();
01047                     const double max = calcStats.getResultMax();
01048                     const double mean = calcStats.getResultMean();
01049 
01050                     if (max != 0.0)
01051                     {
01052                         alignMsg = alignMsg + wxString::Format(_("Mean error after optimization: %.1f pixel, max: %.1f"), mean, max); 
01053                     }
01054                 }
01055             }
01056         }
01057         XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(alignMsg);
01058         m_tool_notebook->GetPage(0)->Layout();
01059         Refresh();
01060     }
01061     else
01062     {
01063         XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(wxT(""));
01064     };
01065 
01066     GetMenuBar()->Enable(XRCID("ID_EDITUNDO"), PanoCommand::GlobalCmdHist::getInstance().canUndo());
01067     GetMenuBar()->Enable(XRCID("ID_EDITREDO"), PanoCommand::GlobalCmdHist::getInstance().canRedo());
01068 
01069     // TODO: update meaningful help text and dynamic links to relevant tabs
01070 
01071     const HuginBase::PanoramaOptions & opts = pano.getOptions();
01072 
01073     wxString projection;
01074     m_ProjectionChoice->SetSelection(opts.getProjection());
01075     m_VFOVSlider->Enable( opts.fovCalcSupported(opts.getProjection()) );
01076     
01077     // No HDR display yet.
01078     /*
01079     m_outputModeChoice->SetSelection(opts.outputMode);
01080     if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) {
01081         m_exposureTextCtrl->Hide();
01082         m_defaultExposureBut->Hide();
01083         m_decExposureBut->Hide();
01084         m_incExposureBut->Hide();
01085     } else {
01086         m_exposureTextCtrl->Show();
01087         m_defaultExposureBut->Show();
01088         m_decExposureBut->Show();
01089         m_incExposureBut->Show();
01090     }*/
01091     m_exposureTextCtrl->ChangeValue(wxString(hugin_utils::doubleToString(opts.outputExposureValue,2).c_str(), wxConvLocal));
01092 
01093     bool activeImgs = pano.getActiveImages().size() > 0;
01094 
01095     // TODO: enable display of parameters and set their limits, if projection has some.
01096 
01097     int nParam = opts.m_projFeatures.numberOfParameters;
01098     bool relayout = false;
01099     // if the projection format has changed
01100     if (opts.getProjection() != m_oldProjFormat) {
01101         DEBUG_DEBUG("Projection format changed");
01102         if (nParam) {
01103             // show parameters and update labels.
01104             m_projection_panel->GetSizer()->Show(m_projParamSizer, true, true);
01105             int i;
01106             for (i=0; i < nParam; i++) {
01107                 const pano_projection_parameter * pp = & (opts.m_projFeatures.parm[i]);
01108                 wxString str2(pp->name, wxConvLocal);
01109                 str2 = wxGetTranslation(str2);
01110                 m_projParamNamesLabel[i]->SetLabel(str2);
01111                 m_projParamSlider[i]->SetRange(hugin_utils::roundi(pp->minValue), hugin_utils::roundi(pp->maxValue));
01112             }
01113             for(;i < PANO_PROJECTION_MAX_PARMS; i++) {
01114                 m_projParamNamesLabel[i]->Hide();
01115                 m_projParamSlider[i]->Hide();
01116                 m_projParamTextCtrl[i]->Hide();
01117             }
01118             relayout = true;
01119         } else {
01120             m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
01121             relayout = true;
01122         }
01123     }
01124     if (nParam) {
01125         // display new values
01126         std::vector<double> params = opts.getProjectionParameters();
01127         assert((int) params.size() == nParam);
01128         for (int i=0; i < nParam; i++) {
01129             wxString val = wxString(hugin_utils::doubleToString(params[i],1).c_str(), wxConvLocal);
01130             m_projParamTextCtrl[i]->ChangeValue(wxString(val.wc_str(), wxConvLocal));
01131             m_projParamSlider[i]->SetValue(hugin_utils::roundi(params[i]));
01132         }
01133     }
01134     if (relayout) {
01135         m_projection_panel->Layout();
01136         Refresh();
01137     }
01138     SetStatusText(wxString::Format(wxT("%.1f x %.1f"), opts.getHFOV(), opts.getVFOV()),2);
01139     m_HFOVSlider->SetValue(hugin_utils::roundi(opts.getHFOV()));
01140     m_VFOVSlider->SetValue(hugin_utils::roundi(opts.getVFOV()));
01141     std::string val;
01142     val = hugin_utils::doubleToString(opts.getHFOV(),1);
01143     m_HFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
01144     val = hugin_utils::doubleToString(opts.getVFOV(),1);
01145     m_VFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
01146     m_VFOVText->Enable(opts.fovCalcSupported(opts.getProjection()));
01147 
01148     m_oldProjFormat = opts.getProjection();
01149 
01150     XRCCTRL(*this,"preview_autocrop_tool",wxButton)->Enable(activeImgs);
01151     XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->Enable(activeImgs);
01152     UpdateRoiDisplay(opts);
01153     
01154     if(m_showProjectionHints)
01155     {
01156         ShowProjectionWarnings();
01157     };
01158     redrawPreview();
01159 }
01160 
01161 void GLPreviewFrame::panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
01162 {
01163     DEBUG_TRACE("");
01164 
01165     bool dirty = false;
01166 
01167     unsigned int nrImages = pano.getNrOfImages();
01168     unsigned int nrButtons = m_ToggleButtons.size();
01169     
01170     GetMenuBar()->Enable(XRCID("action_optimize"), nrImages > 0);
01171 
01172 //    m_displayedImgs.clear();
01173 
01174     // remove items for nonexisting images
01175     for (int i=nrButtons-1; i>=(int)nrImages; i--)
01176     {
01177         m_ButtonSizer->Detach(m_ToggleButtonPanel[i]);
01178         // Image toggle buttons have a event handler on the stack which
01179         // must be removed before the buttons get destroyed.
01180         m_ToggleButtons[i]->PopEventHandler();
01181         m_GroupToggleButtons[i]->PopEventHandler();
01182         delete m_ToggleButtons[i];
01183         delete m_GroupToggleButtons[i];
01184         delete m_ToggleButtonPanel[i];
01185         m_ToggleButtons.pop_back();
01186         m_GroupToggleButtons.pop_back();
01187         m_ToggleButtonPanel.pop_back();
01188         delete toogle_button_event_handlers[i];
01189         toogle_button_event_handlers.pop_back();
01190         delete toggle_group_button_event_handlers[i];
01191         toggle_group_button_event_handlers.pop_back();
01192         dirty = true;
01193     }
01194 
01195     //change overview mode to panosphere if the translation plane parameter are non zero
01196     if (m_GLOverview->GetMode() == GLOverview::PLANE)
01197     {
01198         if (HasNonZeroTranslationPlaneParameters())
01199         {
01200             m_GLOverview->SetMode(GLOverview::PANOSPHERE);
01201             m_OverviewModeChoice->SetSelection(0);
01202             //check if drag mode is mosaic, if so reset to normal
01203             if(drag_tool)
01204             {
01205                 if(drag_tool->getDragMode()==DragTool::drag_mode_mosaic)
01206                 {
01207                     m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
01208                     drag_tool->setDragMode(DragTool::drag_mode_normal);
01209                     EnableGroupCheckboxes(individualDragging());
01210                     // adjust the layout
01211                     DragChoiceLayout(m_DragModeChoice->GetSelection());
01212                 };
01213             };
01214         }
01215     }
01216 
01217     // add buttons
01218     if ( nrImages >= nrButtons ) {
01219         for(HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it){
01220             if (*it >= nrButtons) {
01221                 // create new item.
01222 //                wxImage * bmp = new wxImage(sz.GetWidth(), sz.GetHeight());
01223                 //put wxToggleButton in a wxPanel because 
01224                 //on Windows the background colour of wxToggleButton can't be changed
01225                 wxPanel *pan = new wxPanel(m_ButtonPanel);
01226                 wxBoxSizer * siz = new wxBoxSizer(wxVERTICAL);
01227                 pan->SetSizer(siz);
01228                 wxToggleButton * but = new wxToggleButton(pan,
01229                                                           ID_TOGGLE_BUT + *it,
01230                                                           wxString::Format(wxT("%d"),*it),
01231                                                           wxDefaultPosition, wxDefaultSize,
01232                                                           wxBU_EXACTFIT);
01233                 
01234                 wxCheckBox *butcheck = new wxCheckBox(pan, wxID_ANY, wxT(""));
01235 
01236 #if defined __WXMSW__ || defined __WXMAC__
01237                 //we need a border around the button to see the colored panel
01238                 //because changing backgroundcolor of wxToggleButton does not work in wxMSW
01239                 siz->AddSpacer(5);
01240                 siz->Add(butcheck, 0, wxALIGN_CENTRE_HORIZONTAL | wxFIXED_MINSIZE, 0);
01241                 siz->Add(but,0,wxLEFT | wxRIGHT | wxBOTTOM , 5);
01242 #else
01243                 siz->Add(but,0,wxALL ,0);
01244                 siz->Add(butcheck, 0, wxALL | wxFIXED_MINSIZE, 0);
01245 #endif
01246                 // for the identification tool to work, we need to find when the
01247                 // mouse enters and exits the button. We use a custom event
01248                 // handler, which will also toggle the images:
01249                 ImageToogleButtonEventHandler * event_handler = new ImageToogleButtonEventHandler(*it, m_identify_togglebutton, &m_pano);
01250                 event_handler->AddIdentifyTool(&identify_tool);
01251                 event_handler->AddIdentifyTool(&panosphere_overview_identify_tool);
01252                 event_handler->AddIdentifyTool(&plane_overview_identify_tool);
01253                 toogle_button_event_handlers.push_back(event_handler);
01254                 but->PushEventHandler(event_handler);
01255 
01256                 ImageGroupButtonEventHandler * group_event_handler = new 
01257                     ImageGroupButtonEventHandler(*it, this, &m_pano);
01258                 group_event_handler->AddDragTool((DragTool**) &drag_tool);
01259                 group_event_handler->AddDragTool((DragTool**) &overview_drag_tool);
01260                 group_event_handler->AddIdentifyTool(&identify_tool);
01261                 group_event_handler->AddIdentifyTool(&panosphere_overview_identify_tool);
01262                 group_event_handler->AddIdentifyTool(&plane_overview_identify_tool);
01263                 toggle_group_button_event_handlers.push_back(group_event_handler);
01264                 butcheck->PushEventHandler(group_event_handler);
01265                 butcheck->Show(individualDragging() && m_mode==mode_drag);
01266 
01267                 but->SetValue(true);
01268                 m_ButtonSizer->Add(pan,
01269                                    0,
01270                                    wxLEFT | wxTOP,
01271                                    0);
01272                 m_ToggleButtons.push_back(but);
01273                 m_GroupToggleButtons.push_back(butcheck);
01274                 m_ToggleButtonPanel.push_back(pan);
01275                 dirty = true;
01276             }
01277         }
01278     }
01279 
01280     // update existing items
01281     HuginBase::UIntSet displayedImages = m_pano.getActiveImages();
01282     for (unsigned i=0; i < nrImages; i++) {
01283         m_ToggleButtons[i]->SetValue(set_contains(displayedImages, i));
01284         wxFileName tFilename(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
01285         m_ToggleButtons[i]->SetToolTip(tFilename.GetFullName());
01286     }
01287 
01288     if (dirty) {
01289         m_ButtonSizer->FitInside(m_ButtonPanel);
01290                 Layout();
01291                 DEBUG_INFO("New m_ButtonPanel width: " << (m_ButtonPanel->GetSize()).GetWidth());
01292                 DEBUG_INFO("New m_ButtonPanel Height: " << (m_ButtonPanel->GetSize()).GetHeight());
01293     }
01294     if(nrImages==0)
01295     {
01296         SetMode(mode_assistant);
01297         m_tool_notebook->ChangeSelection(mode_assistant);
01298     };
01299     for(size_t i=2; i<m_tool_notebook->GetPageCount();i++)
01300     {
01301         m_tool_notebook->GetPage(i)->Enable(nrImages!=0);
01302     };
01303     redrawPreview();
01304 }
01305 
01306 void GLPreviewFrame::redrawPreview()
01307 {
01308     m_GLPreview->Refresh();
01309     m_GLOverview->Refresh();
01310 }
01311 
01312 void GLPreviewFrame::OnShowEvent(wxShowEvent& e)
01313 {
01314 
01315     DEBUG_TRACE("OnShow");
01316     bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
01317     wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
01318     if (inf.IsOk()) {
01319         if (e.IsShown()) {
01320             if (!inf.IsShown() && toggle_on ) {
01321                 inf.Show();
01322                 m_mgr->Update();
01323             }
01324         } else {
01325             if (inf.IsFloating() && inf.IsShown()) {
01326                 DEBUG_DEBUG("hiding overview float");
01327                 inf.Hide();
01328                 m_mgr->Update();
01329             }
01330         }
01331     }
01332 
01333 }
01334 
01335 //the following methods are to substitude the GLViewer KeyUp and KeyDown methods
01336 //so that tools use key events that happen globally to the preview frame
01337 //however only key up event is sent, and not key down
01338 //so until this is resolved they will remain to be handled by GLViewer
01339 void GLPreviewFrame::KeyDown(wxKeyEvent& e)
01340 {
01341     if (preview_helper) {
01342         preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
01343     }
01344     if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
01345         if(m_GLOverview->GetMode() == GLOverview::PLANE) {
01346             if (plane_overview_helper) {
01347                 plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
01348             }
01349         } else if (m_GLOverview->GetMode() == GLOverview::PANOSPHERE) {
01350             if (panosphere_overview_helper) {
01351                 panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
01352             }
01353         }
01354     
01355     }
01356     e.Skip();
01357 }
01358 
01359 void GLPreviewFrame::KeyUp(wxKeyEvent& e)
01360 {
01361     if (preview_helper) {
01362         preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
01363     }
01364     if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
01365         if(m_GLOverview->GetMode() == GLOverview::PLANE) {
01366             if (plane_overview_helper) {
01367                 plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
01368             }
01369         } else if (m_GLOverview->GetMode() == GLOverview::PANOSPHERE) {
01370             if (panosphere_overview_helper) {
01371                 panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
01372             }
01373         }
01374     
01375     }
01376     e.Skip();
01377 }
01378 
01379 
01380 
01381 void GLPreviewFrame::OnOverviewToggle(wxCommandEvent& e)
01382 {
01383     DEBUG_TRACE("overview toggle");
01384     bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
01385     wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
01386     if (inf.IsOk()) {
01387         if (inf.IsShown() && !toggle_on) {
01388             inf.Hide();
01389             m_GLOverview->SetActive(false);
01390             m_mgr->Update();
01391         } else if (!(inf.IsShown() && toggle_on)) {
01392             inf.Show();
01393 #if defined __WXMSW__ || defined __WXMAC__
01394             m_GLOverview->SetActive(true);
01395             m_mgr->Update();
01396 #else
01397             m_mgr->Update();
01398             m_GLOverview->SetActive(true);
01399 #endif
01400         }
01401     }
01402 }
01403 
01404 void GLPreviewFrame::OnSwitchPreviewGrid(wxCommandEvent & e)
01405 {
01406     if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
01407     {
01408         preview_helper->ActivateTool(preview_projection_grid);
01409         panosphere_overview_helper->ActivateTool(overview_projection_grid);
01410     }
01411     else
01412     {
01413         preview_helper->DeactivateTool(preview_projection_grid);
01414         panosphere_overview_helper->DeactivateTool(overview_projection_grid);
01415     }
01416     m_GLPreview->Refresh();
01417     m_GLOverview->Refresh();
01418 }
01419 
01420 void GLPreviewFrame::OnClose(wxCloseEvent& event)
01421 {
01422     DEBUG_TRACE("OnClose")
01423     // do not close, just hide if we're not forced
01424     if(m_guiLevel==GUI_SIMPLE)
01425     {
01426         if(!MainFrame::Get()->CloseProject(event.CanVeto(), MainFrame::CLOSE_PROGRAM))
01427         {
01428            if (event.CanVeto())
01429            {
01430                event.Veto();
01431                return;
01432            };
01433         };
01434         MainFrame::Get()->Close(true);
01435     }
01436     else
01437     {
01438         if (event.CanVeto())
01439         {
01440             event.Veto();
01441             Hide();
01442             DEBUG_DEBUG("hiding");
01443         }
01444         else
01445         {
01446             DEBUG_DEBUG("closing");
01447             this->Destroy();
01448         }
01449     };
01450 }
01451 
01452 #if 0
01453 // need to add the wxChoice somewhere
01454 void PreviewFrame::OnProjectionChanged()
01455 {
01456     PanoramaOptions opt = m_pano.getOptions();
01457     int lt = m_ProjectionChoice->GetSelection();
01458     wxString Ip;
01459     switch ( lt ) {
01460     case PanoramaOptions::RECTILINEAR:       Ip = _("Rectilinear"); break;
01461     case PanoramaOptions::CYLINDRICAL:       Ip = _("Cylindrical"); break;
01462     case PanoramaOptions::EQUIRECTANGULAR:   Ip = _("Equirectangular"); break;
01463     }
01464     opt.projectionFormat = (PanoramaOptions::ProjectionFormat) lt;
01465     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01466         new PanoCommand::SetPanoOptionsCmd( pano, opt )
01467         );
01468     DEBUG_DEBUG ("Projection changed: "  << lt << ":" << Ip )
01469 
01470 
01471 }
01472 #endif
01473 
01474 void GLPreviewFrame::OnCenterHorizontally(wxCommandEvent & e)
01475 {
01476     if (m_pano.getActiveImages().size() == 0) return;
01477 
01478     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01479         new PanoCommand::CenterPanoCmd(m_pano)
01480         );
01481 }
01482 
01483 void GLPreviewFrame::OnStraighten(wxCommandEvent & e)
01484 {
01485     if (m_pano.getNrOfImages() == 0) return;
01486 
01487     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01488         new PanoCommand::StraightenPanoCmd(m_pano)
01489         );
01490 }
01491 
01492 void GLPreviewFrame::OnFitPano(wxCommandEvent & e)
01493 {
01494     if (m_pano.getActiveImages().size() == 0) return;
01495 
01496     DEBUG_TRACE("");
01497     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01498     HuginBase::CalculateFitPanorama fitPano(m_pano);
01499     fitPano.run();
01500     opt.setHFOV(fitPano.getResultHorizontalFOV());
01501     opt.setHeight(hugin_utils::roundi(fitPano.getResultHeight()));
01502 
01503     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01504         new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01505         );
01506 
01507     DEBUG_INFO ( "new fov: [" << opt.getHFOV() << " "<< opt.getVFOV() << "] => height: " << opt.getHeight() );
01508 }
01509 
01510 void GLPreviewFrame::OnShowAll(wxCommandEvent & e)
01511 {
01512     if (m_pano.getNrOfImages() == 0) return;
01513 
01514     HuginBase::UIntSet displayedImgs;
01515     if (m_selectAllMode == SELECT_ALL_IMAGES)
01516     {
01517         fill_set(displayedImgs, 0, m_pano.getNrOfImages() - 1);
01518     }
01519     else
01520     {
01521         if (m_selectKeepSelection)
01522         {
01523             displayedImgs = m_pano.getActiveImages();
01524         };
01525         std::vector<HuginBase::UIntVector> stackedImg = HuginBase::getSortedStacks(&m_pano);
01526         for (size_t i = 0; i < stackedImg.size(); ++i)
01527         {
01528             switch (m_selectAllMode)
01529             {
01530                 case SELECT_BRIGHTEST_IMAGES:
01531                     displayedImgs.insert(*(stackedImg[i].rbegin()));
01532                     break;
01533                 case SELECT_DARKEST_IMAGES:
01534                     displayedImgs.insert(*(stackedImg[i].begin()));
01535                     break;
01536                 case SELECT_MEDIAN_IMAGES:
01537                 default:
01538                     displayedImgs.insert(stackedImg[i][stackedImg[i].size() / 2]);
01539                     break;
01540             };
01541         };
01542     };
01543     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01544         new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
01545         );
01546 }
01547 
01548 void GLPreviewFrame::OnShowNone(wxCommandEvent & e)
01549 {
01550     if (m_pano.getNrOfImages() == 0) return;
01551 
01552     DEBUG_ASSERT(m_pano.getNrOfImages() == m_ToggleButtons.size());
01553     for (unsigned int i=0; i < m_pano.getNrOfImages(); i++) {
01554         m_ToggleButtons[i]->SetValue(false);
01555     }
01556     HuginBase::UIntSet displayedImgs;
01557     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01558         new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
01559         );
01560 }
01561 
01562 void GLPreviewFrame::OnNumTransform(wxCommandEvent & e)
01563 {
01564     if (m_pano.getNrOfImages() == 0) return;
01565 
01566     wxString text;
01567     double y;
01568     double p;
01569     double r;
01570     double x;
01571     double z;
01572 
01573     int index = m_DragModeChoice->GetSelection();
01574     switch (index) {
01575         case 0: //normal
01576         case 1: //normal, individual
01577             //@TODO limit numeric transform to selected images
01578             text = XRCCTRL(*this,"input_yaw",wxTextCtrl)->GetValue();
01579             if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
01580             {
01581                 wxBell();
01582                 wxMessageBox(_("Yaw value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01583                 return;
01584             }
01585             text = XRCCTRL(*this,"input_pitch",wxTextCtrl)->GetValue();
01586             if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), p))
01587             {
01588                 wxBell();
01589                 wxMessageBox(_("Pitch value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01590                 return;
01591             }
01592             text = XRCCTRL(*this,"input_roll",wxTextCtrl)->GetValue();
01593             if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), r))
01594             {
01595                 wxBell();
01596                 wxMessageBox(_("Roll value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01597                 return;
01598             }
01599             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01600                     new PanoCommand::RotatePanoCmd(m_pano, y, p, r)
01601                 );
01602             break;
01603         case 2: //mosaic
01604         case 3: //mosaic, individual
01605             //@TODO limit numeric transform to selected images
01606             text = XRCCTRL(*this,"input_x",wxTextCtrl)->GetValue();
01607             if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), x))
01608             {
01609                 wxBell();
01610                 wxMessageBox(_("X value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01611                 return;
01612             }
01613             text = XRCCTRL(*this,"input_y",wxTextCtrl)->GetValue();
01614             if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
01615             {
01616                 wxBell();
01617                 wxMessageBox(_("Y value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01618                 return;
01619             }
01620             text = XRCCTRL(*this,"input_z",wxTextCtrl)->GetValue();
01621             if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), z))
01622             {
01623                 wxBell();
01624                 wxMessageBox(_("Z value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01625                 return;
01626             }
01627             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01628                     new PanoCommand::TranslatePanoCmd(m_pano, x, y, z)
01629                 );
01630             break;
01631     }
01632 }
01633 
01634 void GLPreviewFrame::OnExposureChanged(wxCommandEvent & e)
01635 {
01636     HuginBase::PanoramaOptions opts = m_pano.getOptions();
01637     // exposure
01638     wxString text = m_exposureTextCtrl->GetValue();
01639     DEBUG_INFO ("target exposure = " << text.mb_str(wxConvLocal) );
01640     double p = 0;
01641     if (text != wxT("")) {
01642         if (!hugin_utils::str2double(text, p)) {
01643             wxLogError(_("Value must be numeric."));
01644             return;
01645         }
01646     }
01647     opts.outputExposureValue = p;
01648     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01649             new PanoCommand::SetPanoOptionsCmd( m_pano, opts )
01650                                            );
01651 }
01652 
01653 void GLPreviewFrame::OnProjParameterChanged(wxCommandEvent & e)
01654 {
01655     HuginBase::PanoramaOptions opts = m_pano.getOptions();
01656     int nParam = opts.m_projFeatures.numberOfParameters;
01657     std::vector<double> para = opts.getProjectionParameters();
01658     for (int i = 0; i < nParam; i++) {
01659         if (e.GetEventObject() == m_projParamTextCtrl[i]) {
01660             wxString text = m_projParamTextCtrl[i]->GetValue();
01661             DEBUG_INFO ("param " << i << ":  = " << text.mb_str(wxConvLocal) );
01662             double p = 0;
01663             if (text != wxT("")) {
01664                 if (!hugin_utils::str2double(text, p)) {
01665                     wxLogError(_("Value must be numeric."));
01666                     return;
01667                 }
01668             }
01669             para[i] = p;
01670         }
01671     }
01672     opts.setProjectionParameters(para);
01673     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01674             new PanoCommand::SetPanoOptionsCmd( m_pano, opts )
01675                                            );
01676 }
01677 
01678 void GLPreviewFrame::OnProjParameterReset(wxCommandEvent &e)
01679 {
01680     HuginBase::PanoramaOptions opts = m_pano.getOptions();
01681     opts.resetProjectionParameters();
01682     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01683         new PanoCommand::SetPanoOptionsCmd(m_pano, opts)
01684         );
01685 };
01686 
01687 void GLPreviewFrame::OnChangeFOV(wxScrollEvent & e)
01688 {
01689     DEBUG_TRACE("");
01690 
01691     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01692 
01693     if (e.GetEventObject() == m_HFOVSlider) {
01694         DEBUG_DEBUG("HFOV changed (slider): " << e.GetInt() << " == " << m_HFOVSlider->GetValue());
01695         opt.setHFOV(e.GetInt());
01696     } else if (e.GetEventObject() == m_VFOVSlider) {
01697         DEBUG_DEBUG("VFOV changed (slider): " << e.GetInt());
01698         opt.setVFOV(e.GetInt());
01699     } else if (e.GetEventObject() == XRCCTRL(*this,"layout_scale_slider",wxSlider)) {
01700         DEBUG_DEBUG("Layout scale changed (slider): " << e.GetInt());
01701         GLPreviewFrame::OnLayoutScaleChange(e);
01702     } else {
01703         int nParam = opt.m_projFeatures.numberOfParameters;
01704         std::vector<double> para = opt.getProjectionParameters();
01705         for (int i = 0; i < nParam; i++) {
01706             if (e.GetEventObject() == m_projParamSlider[i]) {
01707                 // update
01708                 para[i] = e.GetInt();
01709             }
01710         }
01711         opt.setProjectionParameters(para);
01712                 opt.setHFOV(m_HFOVSlider->GetValue());
01713                 opt.setVFOV(m_VFOVSlider->GetValue());
01714     }
01715 
01716     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01717         new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01718         );    
01719 }
01720 
01721 void GLPreviewFrame::OnTrackChangeFOV(wxScrollEvent & e)
01722 {
01723     DEBUG_TRACE("");
01724     DEBUG_TRACE("fov change " << e.GetInt());
01725     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01726 
01727     if (e.GetEventObject() == m_HFOVSlider) {
01728         opt.setHFOV(e.GetInt());
01729     } else if (e.GetEventObject() == m_VFOVSlider) {
01730         opt.setVFOV(e.GetInt());
01731     } else {
01732         int nParam = opt.m_projFeatures.numberOfParameters;
01733         std::vector<double> para = opt.getProjectionParameters();
01734         for (int i = 0; i < nParam; i++) {
01735             if (e.GetEventObject() == m_projParamSlider[i]) {
01736                 // update
01737                 para[i] = e.GetInt();
01738             }
01739         }
01740         opt.setProjectionParameters(para);
01741     }
01742     // we only actually update the panorama fully when the mouse is released.
01743     // As we are dragging it we don't want to create undo events, but we would
01744     // like to update the display, so we change the GLViewer's ViewState and
01745     // request a redraw.
01746     m_GLPreview->m_view_state->SetOptions(&opt);
01747     m_GLPreview->Refresh();
01748 }
01749 
01750 void GLPreviewFrame::OnBlendChoice(wxCommandEvent & e)
01751 {
01752     if (e.GetEventObject() == m_BlendModeChoice)
01753     {
01754         updateBlendMode();
01755     }
01756     else
01757     {
01758         // FIXME DEBUG_WARN("wxChoice event from unknown object received");
01759     }
01760 }
01761 
01762 void GLPreviewFrame::OnDragChoice(wxCommandEvent & e)
01763 {
01764     if (drag_tool)
01765     {
01766         DragTool::DragMode newDragMode=DragTool::drag_mode_normal;
01767         int index = m_DragModeChoice->GetSelection();
01768         switch (index) {
01769             case 0: //normal
01770             case 1:
01771                 newDragMode=DragTool::drag_mode_normal;
01772                 break;
01773             case 2: //mosaic
01774             case 3:
01775                 newDragMode=DragTool::drag_mode_mosaic;
01776                 break;
01777         }
01778         if(newDragMode==DragTool::drag_mode_mosaic)
01779         {
01780             if(HasNonZeroTranslationPlaneParameters())
01781             {
01782                 if(wxMessageBox(_("The mosaic/plane mode works only correct for a remapping plane of yaw=0 and pitch=0.\nBut your project has non-zero Tpy and Tpp parameters.\nShould the Tpy and Tpp parameters reset to zero?"),
01783 #ifdef __WXMSW__
01784                     _("Hugin"),
01785 #else
01786                     wxEmptyString,
01787 #endif
01788                     wxYES_NO | wxICON_QUESTION, this) == wxYES)
01789                 {
01790                     ResetTranslationPlaneParameters();
01791                 }
01792                 else
01793                 {
01794                     m_DragModeChoice->SetSelection(index-2);
01795                     return;
01796                 };
01797             };
01798             //switch overview mode to plane
01799             UpdateOverviewMode(1);
01800             m_OverviewModeChoice->SetSelection(1);
01801         }
01802         else
01803         {
01804             //new mode is normal
01805             //set overview back to panosphere mode
01806             UpdateOverviewMode(0);
01807             m_OverviewModeChoice->SetSelection(0);
01808             m_GLOverview->m_visualization_state->ForceRequireRedraw();
01809             m_GLOverview->m_visualization_state->SetDirtyViewport();
01810         };
01811         //update drag mode
01812         drag_tool->setDragMode(newDragMode);
01813         EnableGroupCheckboxes(individualDragging());
01814         // adjust the layout
01815         DragChoiceLayout(index);
01816     };
01817 };
01818 
01819 bool GLPreviewFrame::HasNonZeroTranslationPlaneParameters()
01820 {
01821     size_t nr = m_pano.getNrOfImages();
01822     for (size_t i = 0 ; i < nr; i++)
01823     {
01824         if (m_pano.getSrcImage(i).getTranslationPlaneYaw() != 0 ||
01825             m_pano.getSrcImage(i).getTranslationPlanePitch() != 0)
01826         {
01827             return true;
01828         };
01829     }
01830     return false;
01831 };
01832 
01833 void GLPreviewFrame::ResetTranslationPlaneParameters()
01834 {
01835     HuginBase::UIntSet imgs;
01836     HuginBase::Panorama newPan = m_pano.duplicate();
01837     size_t nr = newPan.getNrOfImages();
01838     for (size_t i = 0 ; i < nr ; i++)
01839     {
01840         HuginBase::SrcPanoImage img = newPan.getSrcImage(i);
01841         img.setTranslationPlaneYaw(0);
01842         img.setTranslationPlanePitch(0);
01843         newPan.setSrcImage(i,img);
01844         imgs.insert(i);
01845     }
01846     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01847         new PanoCommand::UpdateImagesVariablesCmd(m_pano, imgs, newPan.getVariables())
01848     );
01849 };
01850 
01851 bool GLPreviewFrame::UpdateOverviewMode(int newMode)
01852 {
01853     GLOverview::OverviewMode newOverviewMode=GLOverview::PANOSPHERE;
01854     if(newMode==1)
01855     {
01856         newOverviewMode=GLOverview::PLANE;
01857     };
01858     if(m_GLOverview->GetMode()==newOverviewMode)
01859     {
01860         return true;
01861     };
01862     if (m_GLOverview->GetMode() == GLOverview::PANOSPHERE)
01863     {
01864         if (!HasNonZeroTranslationPlaneParameters())
01865         {
01866             m_GLOverview->SetMode(GLOverview::PLANE);
01867             return true;
01868         }
01869         else
01870         {
01871             if(wxMessageBox(_("The mosaic/plane mode works only correct for a remapping plane of yaw=0 and pitch=0.\nBut your project has non-zero Tpy and Tpp parameters.\nShould the Tpy and Tpp parameters reset to zero?"),
01872 #ifdef __WXMSW__
01873                 _("Hugin"),
01874 #else
01875                 wxEmptyString,
01876 #endif
01877                 wxYES_NO | wxICON_QUESTION, this) == wxYES)
01878             {
01879                 ResetTranslationPlaneParameters();
01880                 m_GLOverview->SetMode(GLOverview::PLANE);
01881                 return true;
01882             }
01883             else
01884             {
01885                 return false;
01886             };
01887         };
01888     }
01889     else
01890     {
01891         m_GLOverview->SetMode(GLOverview::PANOSPHERE);
01892         return true;
01893     }
01894 };
01895 
01896 void GLPreviewFrame::OnOverviewModeChoice( wxCommandEvent & e)
01897 {
01898     if(UpdateOverviewMode(m_OverviewModeChoice->GetSelection()))
01899     {
01900         m_GLOverview->m_visualization_state->ForceRequireRedraw();
01901         m_GLOverview->m_visualization_state->SetDirtyViewport();
01902         //set drag mode to normal if new mode is panosphere mode
01903         if(m_GLOverview->GetMode()==GLOverview::PANOSPHERE && m_DragModeChoice->GetSelection()>1)
01904         {
01905             m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
01906             OnDragChoice(e);
01907         };
01908     }
01909     else
01910     {
01911         //change mode was not successful or canceled by user, set mode choice back
01912         if(m_GLOverview->GetMode()==GLOverview::PANOSPHERE)
01913         {
01914             m_OverviewModeChoice->SetSelection(0);
01915         }
01916         else
01917         {
01918             m_OverviewModeChoice->SetSelection(1);
01919         };
01920     };
01921 };
01922 
01923 void GLPreviewFrame::DragChoiceLayout( int index )
01924 {
01925     // visibility of controls based on selected drag mode
01926     bool normalMode=index==0 || index==1;
01927     XRCCTRL(*this,"label_yaw",wxStaticText)->Show(normalMode);
01928     XRCCTRL(*this,"input_yaw",wxTextCtrl)->Show(normalMode);
01929     XRCCTRL(*this,"label_pitch",wxStaticText)->Show(normalMode);
01930     XRCCTRL(*this,"input_pitch",wxTextCtrl)->Show(normalMode);
01931     XRCCTRL(*this,"label_roll",wxStaticText)->Show(normalMode);
01932     XRCCTRL(*this,"input_roll",wxTextCtrl)->Show(normalMode);
01933     XRCCTRL(*this,"label_x",wxStaticText)->Show(!normalMode);
01934     XRCCTRL(*this,"input_x",wxTextCtrl)->Show(!normalMode);
01935     XRCCTRL(*this,"label_y",wxStaticText)->Show(!normalMode);
01936     XRCCTRL(*this,"input_y",wxTextCtrl)->Show(!normalMode);
01937     XRCCTRL(*this,"label_z",wxStaticText)->Show(!normalMode);
01938     XRCCTRL(*this,"input_z",wxTextCtrl)->Show(!normalMode);
01939     // redraw layout to compress empty space
01940     XRCCTRL(*this,"apply_num_transform",wxButton)->GetParent()->Layout();
01941 }
01942 
01943 void GLPreviewFrame::OnDefaultExposure( wxCommandEvent & e )
01944 {
01945     if (m_pano.getNrOfImages() > 0) {
01946         HuginBase::PanoramaOptions opt = m_pano.getOptions();
01947         opt.outputExposureValue = HuginBase::CalculateMeanExposure::calcMeanExposure(m_pano);
01948         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01949                 new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01950                                                );
01951     }
01952 }
01953 
01954 void GLPreviewFrame::OnIncreaseExposure( wxSpinEvent & e )
01955 {
01956     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01957     opt.outputExposureValue = opt.outputExposureValue + 1.0/3;
01958     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01959             new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01960                                             );
01961 }
01962 
01963 void GLPreviewFrame::OnDecreaseExposure( wxSpinEvent & e )
01964 {
01965     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01966     opt.outputExposureValue = opt.outputExposureValue - 1.0/3;
01967     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01968             new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01969                                            );
01970 }
01971 
01972 void GLPreviewFrame::OnProjectionChoice( wxCommandEvent & e )
01973 {
01974     if (e.GetEventObject() == m_ProjectionChoice) {
01975         HuginBase::PanoramaOptions opt = m_pano.getOptions();
01976         int lt = m_ProjectionChoice->GetSelection();
01977         wxString Ip;
01978         opt.setProjection((HuginBase::PanoramaOptions::ProjectionFormat) lt);
01979         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01980                 new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01981                                             );
01982         DEBUG_DEBUG ("Projection changed: "  << lt);
01983         m_projection_panel->Layout();
01984         Refresh();
01985     } else {
01986         // FIXME DEBUG_WARN("wxChoice event from unknown object received");
01987     }
01988 }
01989 
01990 /* We don't have an OpenGL hdr display yet
01991 void GLPreviewFrame::OnOutputChoice( wxCommandEvent & e)
01992 {
01993     if (e.GetEventObject() == m_outputModeChoice) {
01994         PanoramaOptions opt = m_pano.getOptions();
01995         int lt = m_outputModeChoice->GetSelection();
01996         wxString Ip;
01997         opt.outputMode = ( (PanoramaOptions::OutputMode) lt );
01998         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01999                 new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
02000                                                );
02001 
02002     } else {
02003         // FIXME DEBUG_WARN("wxChoice event from unknown object received");
02004     }
02005 }
02006 */
02007 
02008 void GLPreviewFrame::SetStatusMessage(wxString message)
02009 {
02010     SetStatusText(message, 0);
02011 }
02012 
02013 void GLPreviewFrame::OnPhotometric(wxCommandEvent & e)
02014 {
02015     m_GLPreview->SetPhotometricCorrect(e.IsChecked());
02016 }
02017 
02018 void GLPreviewFrame::MakePreviewTools(PreviewToolHelper *preview_helper_in)
02019 {
02020     // create the tool objects.
02021     // we delay this until we have an OpenGL context so that they are free to
02022     // create texture objects and display lists before they are used.
02023     preview_helper = preview_helper_in;
02024     crop_tool = new PreviewCropTool(preview_helper);
02025     drag_tool = new PreviewDragTool(preview_helper);
02026     color_picker_tool = new PreviewColorPickerTool(preview_helper);
02027     edit_cp_tool = new PreviewEditCPTool(preview_helper);
02028     identify_tool = new PreviewIdentifyTool(preview_helper, this, true);
02029     preview_helper->ActivateTool(identify_tool);
02030     difference_tool = new PreviewDifferenceTool(preview_helper);
02031     pano_mask_tool = new PreviewPanoMaskTool(preview_helper);
02032     preview_control_point_tool = new PreviewControlPointTool(preview_helper);
02033     m_preview_layoutLinesTool = new PreviewLayoutLinesTool(preview_helper);
02034 
02035     preview_projection_grid = new PreviewProjectionGridTool(preview_helper);
02036     if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
02037     {
02038         preview_helper->ActivateTool(preview_projection_grid);
02039     };
02040     preview_guide_tool = new PreviewGuideTool(preview_helper);
02041     preview_guide_tool->SetGuideStyle((PreviewGuideTool::Guides)m_GuideChoiceProj->GetSelection());
02042 
02043     // activate tools that are always active.
02044     preview_helper->ActivateTool(pano_mask_tool);
02045     // update the blend mode which activates some tools
02046     updateBlendMode();
02047     m_GLPreview->SetPhotometricCorrect(true);
02048     // update toolbar
02049     SetMode(mode_assistant);
02050 }
02051 
02052 void GLPreviewFrame::MakePanosphereOverviewTools(PanosphereOverviewToolHelper *panosphere_overview_helper_in)
02053 {
02054     panosphere_overview_helper = panosphere_overview_helper_in;
02055     overview_drag_tool = new OverviewDragTool(panosphere_overview_helper);
02056     panosphere_overview_camera_tool = new PanosphereOverviewCameraTool(panosphere_overview_helper);
02057     panosphere_overview_helper->ActivateTool(panosphere_overview_camera_tool);
02058     panosphere_overview_identify_tool = new PreviewIdentifyTool(panosphere_overview_helper, this, false);
02059     panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool);
02060 
02061     panosphere_sphere_tool = new PanosphereSphereTool(panosphere_overview_helper, GetPreviewBackgroundColor());
02062     panosphere_overview_helper->ActivateTool(panosphere_sphere_tool);
02063     
02064     overview_projection_grid = new PanosphereOverviewProjectionGridTool(panosphere_overview_helper);
02065     if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
02066     {
02067         panosphere_overview_helper->ActivateTool(overview_projection_grid);
02068     }
02069     
02070     
02071     overview_outlines_tool = new PanosphereOverviewOutlinesTool(panosphere_overview_helper, m_GLPreview);
02072     panosphere_overview_helper->ActivateTool(overview_outlines_tool);
02073     panosphere_difference_tool = new PreviewDifferenceTool(panosphere_overview_helper);
02074 
02075     m_panosphere_layoutLinesTool = new PreviewLayoutLinesTool(panosphere_overview_helper);
02076     panosphere_control_point_tool = new PreviewControlPointTool(panosphere_overview_helper);
02077 
02078 
02079 
02080 }
02081 
02082 void GLPreviewFrame::MakePlaneOverviewTools(PlaneOverviewToolHelper *plane_overview_helper_in)
02083 {
02084     plane_overview_helper = plane_overview_helper_in;
02085     plane_overview_identify_tool = new PreviewIdentifyTool(plane_overview_helper, this, false);
02086     plane_overview_helper->ActivateTool(plane_overview_identify_tool);
02087     
02088     plane_overview_camera_tool = new PlaneOverviewCameraTool(plane_overview_helper);
02089     plane_overview_helper->ActivateTool(plane_overview_camera_tool);
02090     plane_difference_tool = new PreviewDifferenceTool(plane_overview_helper);
02091 
02092     plane_overview_outlines_tool = new PlaneOverviewOutlinesTool(plane_overview_helper, m_GLPreview);
02093     plane_overview_helper->ActivateTool(plane_overview_outlines_tool);
02094 
02095     m_plane_layoutLinesTool = new PreviewLayoutLinesTool(plane_overview_helper);
02096     plane_control_point_tool = new PreviewControlPointTool(plane_overview_helper);
02097 
02098 }
02099 
02100 void GLPreviewFrame::OnIdentify(wxCommandEvent & e)
02101 {
02102     SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
02103     if (e.IsChecked())
02104     {
02105         m_BlendModeChoice->SetSelection(0);
02106         preview_helper->DeactivateTool(difference_tool);
02107         panosphere_overview_helper->DeactivateTool(panosphere_difference_tool);
02108         plane_overview_helper->DeactivateTool(plane_difference_tool);
02109         identify_tool->setConstantOn(true);
02110         panosphere_overview_identify_tool->setConstantOn(true);
02111         plane_overview_identify_tool->setConstantOn(true);
02112 //        TurnOffTools(preview_helper->ActivateTool(identify_tool));
02113 //        TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool));
02114 //        TurnOffTools(plane_overview_helper->ActivateTool(plane_overview_identify_tool));
02115     } else {
02116         identify_tool->setConstantOn(false);
02117         panosphere_overview_identify_tool->setConstantOn(false);
02118         plane_overview_identify_tool->setConstantOn(false);
02119 //        preview_helper->DeactivateTool(identify_tool);
02120 //        panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
02121 //        plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
02122         CleanButtonColours();
02123     }
02124     m_GLPreview->Refresh();
02125     m_GLOverview->Refresh();
02126 }
02127 
02128 void GLPreviewFrame::OnControlPoint(wxCommandEvent & e)
02129 {
02130     if (!m_editCP_togglebutton->GetValue())
02131     {
02132         //process event only if edit cp tool is disabled
02133         SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
02134         if (e.IsChecked())
02135         {
02136             TurnOffTools(preview_helper->ActivateTool(preview_control_point_tool));
02137             TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_control_point_tool));
02138             TurnOffTools(plane_overview_helper->ActivateTool(plane_control_point_tool));
02139         }
02140         else {
02141             preview_helper->DeactivateTool(preview_control_point_tool);
02142             panosphere_overview_helper->DeactivateTool(panosphere_control_point_tool);
02143             plane_overview_helper->DeactivateTool(plane_control_point_tool);
02144         }
02145         m_GLPreview->Refresh();
02146         m_GLOverview->Refresh();
02147     };
02148 }
02149 
02150 void GLPreviewFrame::TurnOffTools(std::set<Tool*> tools)
02151 {
02152     std::set<Tool*>::iterator i;
02153     for (i = tools.begin(); i != tools.end(); ++i)
02154     {
02155         if (*i == crop_tool)
02156         {
02157             // cover up the guidelines
02158             m_GLPreview->Refresh();
02159         } else if (*i == drag_tool)
02160         {
02161             // cover up its boxes
02162             m_GLPreview->Refresh();
02163         } else if (*i == identify_tool)
02164         {
02165             // disabled the identify tool, toggle its button off.
02166             m_identify_togglebutton->SetValue(false);
02167             // cover up its indicators and restore normal button colours.
02168             m_GLPreview->Refresh();
02169             m_GLOverview->Refresh();
02170             CleanButtonColours();
02171         } else if (*i == preview_control_point_tool)
02172         {
02173             // disabled the control point tool.
02174             XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
02175             // cover up the control point lines.
02176             m_GLPreview->Refresh();
02177             m_GLOverview->Refresh();
02178         }
02179     }
02180 }
02181 
02182 void GLPreviewFrame::SetImageButtonColour(unsigned int image_nr,
02183                                           unsigned char red,
02184                                           unsigned char green,
02185                                           unsigned char blue)
02186 {
02187     // 0, 0, 0 indicates we want to go back to the system colour.
02188     // TODO: Maybe we should test this better on different themes.
02189 #if defined __WXMSW__ || defined __WXMAC__
02190     if (red || green || blue)
02191     {
02192         // the identify tool wants us to highlight an image button in the given
02193         // colour, to match up with the display in the preview.
02194         // on windows change the color of the surhugin_utils::rounding wxPanel
02195         m_ToggleButtonPanel[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
02196     }
02197     else
02198     {
02199         // return to the normal colour
02200         m_ToggleButtonPanel[image_nr]->SetBackgroundColour(m_ToggleButtonPanel[image_nr]->GetParent()->GetBackgroundColour());
02201     }
02202     m_ToggleButtonPanel[image_nr]->Refresh();
02203 #else
02204     if (red || green || blue)
02205     {
02206         // change the color of the wxToggleButton 
02207         m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_COLOUR);
02208         m_ToggleButtons[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
02209         // black should be visible on the button's vibrant colours.
02210         m_ToggleButtons[image_nr]->SetForegroundColour(wxColour(0, 0, 0));
02211     }
02212     else
02213     {
02214         // return to the normal colour
02215         m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
02216         m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour);
02217         m_ToggleButtons[image_nr]->SetForegroundColour(wxNullColour);
02218     };
02219     m_ToggleButtons[image_nr]->Refresh();
02220 #endif
02221 }
02222 
02223 void GLPreviewFrame::CleanButtonColours()
02224 {
02225     // when we turn off the identification tool, any buttons that were coloured
02226     // to match the image in the preview should be given back the system themed
02227     // colours.
02228     unsigned int nr_images = m_pano.getNrOfImages();
02229     for (unsigned image = 0; image < nr_images; image++)
02230     {
02231 #if defined __WXMSW__ || defined __WXMAC__
02232         m_ToggleButtonPanel[image]->SetBackgroundColour(m_ToggleButtonPanel[image]->GetParent()->GetBackgroundColour());
02233         m_ToggleButtonPanel[image]->Refresh();
02234 #else
02235         m_ToggleButtons[image]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
02236         m_ToggleButtons[image]->SetBackgroundColour(wxNullColour);
02237         m_ToggleButtons[image]->SetForegroundColour(wxNullColour);
02238         m_ToggleButtons[image]->Refresh();
02239 #endif
02240     }
02241 }
02242 
02243 void GLPreviewFrame::OnColorPicker(wxCommandEvent &e)
02244 {
02245     // blank status text as it refers to an old tool.
02246     SetStatusText(wxT(""), 0); 
02247     if (e.IsChecked())
02248     {
02249         // deactivate delete cp tool if active
02250         preview_helper->DeactivateTool(edit_cp_tool);
02251         m_editCP_togglebutton->SetValue(false);
02252         preview_helper->ActivateTool(color_picker_tool);
02253     }
02254     else
02255     {
02256         preview_helper->DeactivateTool(color_picker_tool);
02257     };
02258     m_GLPreview->Refresh();
02259 };
02260 
02261 void GLPreviewFrame::UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
02262 {
02263     PanoCommand::GlobalCmdHist::getInstance().addCommand(
02264         new PanoCommand::UpdateWhiteBalance(m_pano, redFactor, blueFactor)
02265         );
02266     //now toggle button and deactivate tool
02267     m_colorpicker_togglebutton->SetValue(false);
02268     //direct deactivation of tool does not work because this function is called by the tool itself
02269     //so we are send an event to deactivate the tool
02270     wxCommandEvent e(wxEVT_COMMAND_TOOL_CLICKED, XRCID("preview_color_picker_tool"));
02271     e.SetInt(0);
02272     GetEventHandler()->AddPendingEvent(e);
02273 };
02274 
02275 void GLPreviewFrame::OnEditCPTool(wxCommandEvent &e)
02276 {
02277     // blank status text as it refers to an old tool.
02278     SetStatusText(wxT(""), 0);
02279     if (e.IsChecked())
02280     {
02281         // deactivate color picker tool
02282         preview_helper->DeactivateTool(color_picker_tool);
02283         m_colorpicker_togglebutton->SetValue(false);
02284         // show automatically all cp
02285         preview_helper->ActivateTool(preview_control_point_tool);
02286         preview_helper->ActivateTool(edit_cp_tool);
02287     }
02288     else
02289     {
02290         if (!XRCCTRL(*this, "preview_control_point_tool", wxCheckBox)->GetValue())
02291         {
02292             preview_helper->DeactivateTool(preview_control_point_tool);
02293         };
02294         preview_helper->DeactivateTool(edit_cp_tool);
02295     };
02296     m_GLPreview->Refresh();
02297 };
02298 
02299 ImageToogleButtonEventHandler::ImageToogleButtonEventHandler(
02300                                   unsigned int image_number_in,
02301                                   wxToggleButton* identify_button_in,
02302                                   HuginBase::Panorama * m_pano_in)
02303 {
02304     image_number = image_number_in;
02305     m_identify_button = identify_button_in;
02306     m_pano = m_pano_in;
02307 }
02308 
02309 void ImageToogleButtonEventHandler::OnEnter(wxMouseEvent & e)
02310 {
02311     // When using the identify tool, we want to identify image locations when
02312     // the user moves the mouse over the image buttons, but only if the image
02313     // is being shown.
02314     if ( 
02315         m_identify_button->GetValue() && 
02316         m_pano->getActiveImages().count(image_number))
02317     {
02318         std::vector<PreviewIdentifyTool**>::iterator it;
02319         for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
02320             (*(*it))->ShowImageNumber(image_number);
02321         }
02322     }
02323     e.Skip();
02324 }
02325 
02326 void ImageToogleButtonEventHandler::OnLeave(wxMouseEvent & e)
02327 {
02328     // if the mouse left one of the image toggle buttons with the identification
02329     // tool active, we should stop showing the image indicator for that button.
02330     if ( 
02331         m_identify_button->GetValue() && 
02332         m_pano->getActiveImages().count(image_number))
02333     {
02334         std::vector<PreviewIdentifyTool**>::iterator it;
02335         for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
02336             (*(*it))->StopShowingImages();
02337         }
02338     }
02339     e.Skip();
02340 }
02341 
02342 void ImageToogleButtonEventHandler::OnChange(wxCommandEvent & e)
02343 {
02344     // the user is turning on or off an image using its button. We want to turn
02345     // the indicators on and off if appropriate correctly to. We use OnEnter
02346     // and OnLeave for the indicators, but these only work when the image is
02347     // showing, so we are carefull of the order:
02348     HuginBase::UIntSet activeImages = m_pano->getActiveImages();
02349     wxMouseEvent null_event;
02350     if (e.IsChecked()) {
02351         activeImages.insert(image_number);
02352         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02353             new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
02354         );
02355         OnEnter(null_event);
02356     } else {
02357         OnLeave(null_event);
02358         activeImages.erase(image_number);
02359         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02360             new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
02361         );
02362     }
02363 }
02364 
02365 void ImageToogleButtonEventHandler::AddIdentifyTool(PreviewIdentifyTool** identify_tool_in) {
02366     identify_tools.push_back(identify_tool_in);
02367 }
02368 
02369 ImageGroupButtonEventHandler::ImageGroupButtonEventHandler(unsigned int image_number, GLPreviewFrame* frame_in, HuginBase::Panorama* m_pano)
02370     : image_number(image_number), frame(frame_in), m_pano(m_pano) {}
02371 
02372 void ImageGroupButtonEventHandler::AddIdentifyTool(PreviewIdentifyTool** identify_tool_in) {
02373     identify_tools.push_back(identify_tool_in);
02374 }
02375 
02376 
02377 void ImageGroupButtonEventHandler::OnEnter(wxMouseEvent & e)
02378 {
02379     //mark the image
02380     if (m_pano->getActiveImages().count(image_number))
02381     {
02382         std::vector<PreviewIdentifyTool**>::iterator it;
02383         for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
02384             (*(*it))->ShowImageNumber(image_number);
02385         }
02386     }
02387     e.Skip();
02388 }
02389 
02390 void ImageGroupButtonEventHandler::OnLeave(wxMouseEvent & e)
02391 {
02392     //unmark the image
02393     if (m_pano->getActiveImages().count(image_number))
02394     {
02395         std::vector<PreviewIdentifyTool**>::iterator it;
02396         for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
02397             (*(*it))->StopShowingImages();
02398         }
02399     }
02400     e.Skip();
02401 }
02402 
02403 void ImageGroupButtonEventHandler::OnChange(wxCommandEvent & e)
02404 {
02405     wxMouseEvent null_event;
02406     if (e.IsChecked()) {
02407         frame->AddImageToDragGroup(image_number,false);
02408         OnEnter(null_event);
02409     } else {
02410         OnLeave(null_event);
02411         frame->RemoveImageFromDragGroup(image_number,false);
02412     }
02413 }
02414 
02415 void ImageGroupButtonEventHandler::AddDragTool(DragTool** drag_tool_in) {
02416     drag_tools.push_back(drag_tool_in);
02417 }
02418 
02419 bool GLPreviewFrame::individualDragging()
02420 {
02421     return m_DragModeChoice->GetSelection()==1 || 
02422            m_DragModeChoice->GetSelection()==3;
02423 }
02424 
02425 void GLPreviewFrame::ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box) {
02426     if (imageDragGroup.count(image_nr) == 0) {
02427         this->AddImageToDragGroup(image_nr, update_check_box);
02428     } else {
02429         this->RemoveImageFromDragGroup(image_nr, update_check_box);
02430     }
02431 }
02432 void GLPreviewFrame::RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box) {
02433     imageDragGroup.erase(image_nr);
02434     if (update_check_box) {
02435         m_GroupToggleButtons[image_nr]->SetValue(false);
02436     }
02437 }
02438 void GLPreviewFrame::AddImageToDragGroup(unsigned int image_nr, bool update_check_box) {
02439     imageDragGroup.insert(image_nr);
02440     if (update_check_box) {
02441         m_GroupToggleButtons[image_nr]->SetValue(true);
02442     }
02443 }
02444 void GLPreviewFrame::SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box) {
02445     imageDragGroup.swap(imageDragGroup_in);
02446     std::vector<wxCheckBox*>::iterator it;
02447     unsigned int nr = 0;
02448     for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
02449         (*it)->SetValue(imageDragGroup.count(nr++)>0);
02450     }
02451 }
02452 HuginBase::UIntSet GLPreviewFrame::GetDragGroupImages() {
02453     return imageDragGroup;
02454 }
02455 void GLPreviewFrame::ClearDragGroupImages(bool update_check_box) {
02456     imageDragGroup.clear();
02457     std::vector<wxCheckBox*>::iterator it;
02458     for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
02459         (*it)->SetValue(false);
02460     }
02461 }
02462 
02463 void GLPreviewFrame::EnableGroupCheckboxes(bool isShown)
02464 {
02465     std::vector<wxCheckBox*>::iterator it;
02466     for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it)
02467     {
02468         (*it)->Show(isShown);
02469     }
02470     Layout();
02471 };
02472 
02474 void GLPreviewFrame::FillBlendChoice()
02475 {
02476     if(PreviewDifferenceTool::CheckOpenGLCanDifference())
02477         m_differenceIndex=m_BlendModeChoice->Append(_("difference"));
02478     // update size
02479     m_BlendModeChoice->InvalidateBestSize();
02480     m_BlendModeChoice->GetParent()->Layout();
02481     Refresh();
02482     // get blend mode last state
02483     unsigned int oldMode = wxConfigBase::Get()->Read(wxT("/GLPreviewFrame/blendMode"), 0l);
02484     // limit old state to max available states
02485     if (oldMode >= m_BlendModeChoice->GetCount())
02486     {
02487         oldMode = 0;
02488     }
02489     m_BlendModeChoice->SetSelection(oldMode);
02490     updateBlendMode();
02491 };
02492 
02493 void GLPreviewFrame::OnAutocrop(wxCommandEvent &e)
02494 {
02495     DEBUG_INFO("Dirty ROI Calc\n");
02496     if (m_pano.getActiveImages().size() == 0)
02497     {
02498         return;
02499     };
02500 
02501     vigra::Rect2D newROI;
02502     {
02503         ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
02504         HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
02505         cropPano.run();
02506         if (cropPano.hasRunSuccessfully())
02507         {
02508             newROI = cropPano.getResultOptimalROI();
02509         };
02510     };
02511 
02512     //set the ROI - fail if the right/bottom is zero, meaning all zero
02513     if(!newROI.isEmpty())
02514     {
02515         HuginBase::PanoramaOptions opt = m_pano.getOptions();
02516         opt.setROI(newROI);
02517         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02518             new PanoCommand::SetPanoOptionsCmd(m_pano, opt )
02519             );
02520     }
02521 }
02522 
02523 void GLPreviewFrame::OnStackAutocrop(wxCommandEvent &e)
02524 {
02525     DEBUG_INFO("Dirty ROI Calc\n");
02526     if (m_pano.getActiveImages().size() == 0)
02527     {
02528         return;
02529     };
02530 
02531     vigra::Rect2D newROI;
02532     {
02533         ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
02534         HuginBase::UIntSet activeImages = m_pano.getActiveImages();
02535         std::vector<HuginBase::UIntSet> stackImgs = getHDRStacks(m_pano, activeImages, m_pano.getOptions());
02536         HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
02537         //only use hdr autocrop for projects with stacks
02538         //otherwise fall back to "normal" autocrop
02539         if (stackImgs.size()<activeImages.size())
02540         {
02541             cropPano.setStacks(stackImgs);
02542         }
02543         cropPano.run();
02544         if (cropPano.hasRunSuccessfully())
02545         {
02546             newROI = cropPano.getResultOptimalROI();
02547         };
02548     };
02549 
02550     //set the ROI - fail if the right/bottom is zero, meaning all zero
02551     if(!newROI.isEmpty())
02552     {
02553         HuginBase::PanoramaOptions opt = m_pano.getOptions();
02554         opt.setROI(newROI);
02555         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02556             new PanoCommand::SetPanoOptionsCmd(m_pano, opt )
02557             );
02558     }
02559 }
02560 
02561 void GLPreviewFrame::OnFullScreen(wxCommandEvent & e)
02562 {
02563     ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
02564 };
02565 
02566 void GLPreviewFrame::SetMode(int newMode)
02567 {
02568     if(m_mode==newMode)
02569         return;
02570     SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
02571     switch(m_mode)
02572     {
02573         case mode_assistant:
02574         case mode_preview:
02575             // switch off identify and show cp tool
02576             identify_tool->setConstantOn(false);
02577             panosphere_overview_identify_tool->setConstantOn(false);
02578             plane_overview_identify_tool->setConstantOn(false);
02579             preview_helper->DeactivateTool(color_picker_tool);
02580             m_colorpicker_togglebutton->SetValue(false);
02581 //            preview_helper->DeactivateTool(identify_tool);
02582 //            panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
02583 //            plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
02584             preview_helper->DeactivateTool(edit_cp_tool);
02585             m_editCP_togglebutton->SetValue(false);
02586 
02587             CleanButtonColours();
02588             m_identify_togglebutton->SetValue(false);
02589             preview_helper->DeactivateTool(preview_control_point_tool);
02590             panosphere_overview_helper->DeactivateTool(panosphere_control_point_tool);
02591             plane_overview_helper->DeactivateTool(plane_control_point_tool);
02592             XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
02593             break;
02594         case mode_layout:
02595             // disable layout mode.
02596             preview_helper->DeactivateTool(m_preview_layoutLinesTool);
02597             panosphere_overview_helper->DeactivateTool(m_panosphere_layoutLinesTool);
02598             plane_overview_helper->DeactivateTool(m_plane_layoutLinesTool);
02599             // reactivate identify tool when leaving layout mode
02600             preview_helper->ActivateTool(identify_tool);
02601             panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool);
02602             plane_overview_helper->ActivateTool(plane_overview_identify_tool);
02603             m_GLPreview->SetLayoutMode(false);
02604             m_GLOverview->SetLayoutMode(false);
02605             // Switch the panorama mask back on.
02606             preview_helper->ActivateTool(pano_mask_tool);
02607             //restore blend mode
02608             m_BlendModeChoice->SetSelection(non_layout_blend_mode);
02609             updateBlendMode();
02610             break;
02611         case mode_projection:
02612             preview_helper->DeactivateTool(preview_guide_tool);
02613             break;
02614         case mode_drag:
02615             preview_helper->DeactivateTool(preview_guide_tool);
02616             preview_helper->DeactivateTool(drag_tool);
02617             panosphere_overview_helper->DeactivateTool(overview_drag_tool);
02618             if (individualDragging()) {
02619                 std::vector<wxCheckBox*>::iterator it;
02620                 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
02621                     (*it)->Show(false);
02622                 }
02623             }
02624             break;
02625         case mode_crop:
02626             preview_helper->DeactivateTool(preview_guide_tool);
02627             preview_helper->DeactivateTool(crop_tool);
02628             break;
02629     };
02630     m_mode=newMode;
02631     wxScrollEvent dummy;
02632     switch(m_mode)
02633     {
02634         case mode_assistant:
02635         case mode_preview:
02636             break;
02637         case mode_layout:
02638             //save blend mode setting, set to normal for layout mode
02639             non_layout_blend_mode=m_BlendModeChoice->GetSelection();
02640             m_BlendModeChoice->SetSelection(0);
02641             updateBlendMode();
02642             // turn off things not used in layout mode.
02643             preview_helper->DeactivateTool(pano_mask_tool);
02644             // deactivate identify tool in layout mode
02645             preview_helper->DeactivateTool(identify_tool);
02646             panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
02647             plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
02648             m_GLPreview->SetLayoutMode(true);
02649             m_GLOverview->SetLayoutMode(true);
02650             preview_helper->ActivateTool(m_preview_layoutLinesTool);
02651             panosphere_overview_helper->ActivateTool(m_panosphere_layoutLinesTool);
02652             plane_overview_helper->ActivateTool(m_plane_layoutLinesTool);
02653             // we need to update the meshes after switch to layout mode
02654             // otherwise the following update of scale has no meshes to scale
02655             m_GLPreview->Update();
02656             m_GLOverview->Update();
02657             OnLayoutScaleChange(dummy);
02658             break;
02659         case mode_projection:
02660             preview_helper->ActivateTool(preview_guide_tool);
02661             break;
02662         case mode_drag:
02663             preview_helper->ActivateTool(preview_guide_tool);
02664             TurnOffTools(preview_helper->ActivateTool(drag_tool));
02665             TurnOffTools(panosphere_overview_helper->ActivateTool(overview_drag_tool));
02666             if (individualDragging()) {
02667                 std::vector<wxCheckBox*>::iterator it;
02668                 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
02669                     (*it)->Show(true);
02670                 }
02671             }
02672             break;
02673         case mode_crop:
02674             TurnOffTools(preview_helper->ActivateTool(crop_tool));
02675             preview_helper->ActivateTool(preview_guide_tool);
02676             break;
02677     };
02678     //enable group checkboxes only for drag mode tab
02679     EnableGroupCheckboxes(m_mode==mode_drag && individualDragging());
02680     m_GLPreview->Refresh();
02681 };
02682 
02683 void GLPreviewFrame::OnSelectMode(wxNotebookEvent &e)
02684 {
02685     if(m_mode!=-1)
02686         SetMode(e.GetSelection());
02687 };
02688 
02689 void GLPreviewFrame::OnToolModeChanging(wxNotebookEvent &e)
02690 {
02691     if(m_pano.getNrOfImages()==0 && e.GetOldSelection()==0)
02692     {
02693         wxBell();
02694         e.Veto();
02695     };
02696 };
02697 
02698 void GLPreviewFrame::OnROIChanged ( wxCommandEvent & e )
02699 {
02700     HuginBase::PanoramaOptions opt = m_pano.getOptions();
02701     long left, right, top, bottom;
02702     if (!m_ROITopTxt->GetValue().ToLong(&top)) {
02703         wxLogError(_("Top needs to be an integer bigger than 0"));
02704         return;
02705     }
02706     if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
02707         wxLogError(_("left needs to be an integer bigger than 0"));
02708         return;
02709     }
02710     if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
02711         wxLogError(_("right needs to be an integer bigger than 0"));
02712         return;
02713     }
02714     if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
02715         wxLogError(_("bottom needs to be an integer bigger than 0"));
02716         return;
02717     }
02718     opt.setROI(vigra::Rect2D(left, top, right, bottom));
02719     // make sure that left is really to the left of right
02720     if(opt.getROI().width()<1) {
02721         wxLogError(_("left boundary must be smaller than right"));
02722         UpdateRoiDisplay(m_pano.getOptions());
02723         return;
02724     }
02725     // make sure that top is really higher than bottom
02726     if(opt.getROI().height()<1) {
02727         wxLogError(_("top boundary must be smaller than bottom"));
02728         UpdateRoiDisplay(m_pano.getOptions());
02729         return;
02730     }
02731 
02732     PanoCommand::GlobalCmdHist::getInstance().addCommand(
02733             new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
02734                                            );
02735 };
02736 
02737 void GLPreviewFrame::OnResetCrop(wxCommandEvent &e)
02738 {
02739     HuginBase::PanoramaOptions opt = m_pano.getOptions();
02740     opt.setROI(vigra::Rect2D(0,0,opt.getWidth(),opt.getHeight()));
02741     PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::SetPanoOptionsCmd(m_pano, opt));
02742 };
02743 
02744 void GLPreviewFrame::OnHFOVChanged ( wxCommandEvent & e )
02745 {
02746     HuginBase::PanoramaOptions opt = m_pano.getOptions();
02747 
02748 
02749     wxString text = m_HFOVText->GetValue();
02750     DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
02751     if (text == wxT("")) {
02752         return;
02753     }
02754 
02755     double hfov;
02756     if (!hugin_utils::str2double(text, hfov)) {
02757         wxLogError(_("Value must be numeric."));
02758         return;
02759     }
02760 
02761     if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
02762         wxLogError(wxString::Format(
02763             _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
02764             opt.getMaxHFOV()));
02765         hfov=opt.getMaxHFOV();
02766     }
02767     opt.setHFOV(hfov);
02768     // recalculate panorama height...
02769     PanoCommand::GlobalCmdHist::getInstance().addCommand(
02770         new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
02771         );
02772 
02773     DEBUG_INFO ( "new hfov: " << hfov )
02774 };
02775 
02776 void GLPreviewFrame::OnVFOVChanged ( wxCommandEvent & e )
02777 {
02778     HuginBase::PanoramaOptions opt = m_pano.getOptions();
02779 
02780     wxString text = m_VFOVText->GetValue();
02781     DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
02782     if (text == wxT("")) {
02783         return;
02784     }
02785 
02786     double vfov;
02787     if (!hugin_utils::str2double(text, vfov)) {
02788         wxLogError(_("Value must be numeric."));
02789         return;
02790     }
02791 
02792     if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
02793         wxLogError(wxString::Format(
02794             _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
02795             opt.getMaxVFOV()));
02796         vfov = opt.getMaxVFOV();
02797     }
02798     opt.setVFOV(vfov);
02799     // recalculate panorama height...
02800     PanoCommand::GlobalCmdHist::getInstance().addCommand(
02801         new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
02802         );
02803 
02804     DEBUG_INFO ( "new vfov: " << vfov )
02805 };
02806 
02807 void GLPreviewFrame::OnLayoutScaleChange(wxScrollEvent &e)
02808 {
02809     if(m_mode==mode_layout)
02810     {
02811         double scale_factor=XRCCTRL(*this,"layout_scale_slider",wxSlider)->GetValue();
02812         m_GLPreview->SetLayoutScale(10.0 - sqrt(scale_factor));
02813         m_GLOverview->SetLayoutScale(10.0 - sqrt(scale_factor));
02814         m_GLPreview->Refresh();
02815         m_GLOverview->Refresh();
02816     };
02817 };
02818 
02819 void GLPreviewFrame::ShowProjectionWarnings()
02820 {
02821     HuginBase::PanoramaOptions opts = m_pano.getOptions();
02822     double hfov = opts.getHFOV();
02823     double vfov = opts.getVFOV();
02824     double maxfov = hfov > vfov ? hfov : vfov;
02825     wxString message;
02826     // If this is set to true, offer rectilinear as an alternative if it fits.
02827     bool rectilinear_option = false;
02828     switch (opts.getProjection()) {
02829         case HuginBase::PanoramaOptions::RECTILINEAR:
02830             if (maxfov > 120.0) {
02831                             // wide rectilinear image
02832                 message = _("With a wide field of view, panoramas with rectilinear projection get very stretched towards the edges.\n");
02833                 if (vfov < 110) {
02834                     message += _("Since the field of view is only very wide in the horizontal direction, try a cylindrical projection instead.");
02835                 } else {
02836                     message += _("For a very wide panorama, try equirectangular projection instead.");
02837                 }
02838                 message += _(" You could also try Panini projection.");
02839             }
02840             break;
02841         case HuginBase::PanoramaOptions::CYLINDRICAL:
02842             if (vfov > 120.0) {
02843                 message = _("With a wide vertical field of view, panoramas with cylindrical projection get very stretched at the top and bottom.\nAn equirectangular projection would fit the same content in less vertical space.");
02844             } else rectilinear_option = true;
02845             break;
02846         case HuginBase::PanoramaOptions::EQUIRECTANGULAR:
02847             if (vfov < 110.0 && hfov > 120.0)
02848             {
02849                 message = _("Since the vertical field of view is not too wide, you could try setting the panorama projection to cylindrical.\nCylindrical projection preserves vertical lines, unlike equirectangular.");
02850             } else rectilinear_option = true;
02851             break;
02852         case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE:
02853             if (maxfov < 280.0) {
02854                 rectilinear_option = true;
02855                 message = _("Stereographic projection is conformal, unlike this Fisheye panorama projection.\nA conformal projection preserves angles around a point, which often makes it easier on the eye.");
02856             }
02857             break;
02858         case HuginBase::PanoramaOptions::STEREOGRAPHIC:
02859             if (maxfov > 300.0) {
02860                 message = _("Panoramas with stereographic projection and a very wide field of view stretch the image around the edges a lot.\nThe Fisheye panorama projection compresses it, so you can fit in a wide field of view and still have a reasonable coverage of the middle.");
02861             } else rectilinear_option = true;
02862             break;
02863         default:
02864             rectilinear_option = true;
02865     }
02866     if (rectilinear_option && maxfov < 110.0) {
02867         message = _("Setting the panorama to rectilinear projection would keep the straight lines straight.");
02868     }
02869     if (message.IsEmpty()) {
02870         // no message needed.
02871         m_infoBar->Dismiss();
02872     } else {
02873         m_infoBar->ShowMessage(message, wxICON_INFORMATION);
02874     }
02875 };
02876 
02877 void GLPreviewFrame::SetShowProjectionHints(bool new_value)
02878 {
02879     m_showProjectionHints=new_value;
02880     if(!m_showProjectionHints)
02881     {
02882         m_infoBar->Dismiss();
02883     };
02884 };
02885 
02886 void GLPreviewFrame::OnHideProjectionHints(wxCommandEvent &e)
02887 {
02888     wxMessageBox(_("You have hidden the infobar, which shows hints about selection of projection.\nIf you want to see the bar again, activate the bar in the preferences again."),
02889 #ifdef __WXMSW__
02890         _("Hugin"),
02891 #else
02892         wxT(""),
02893 #endif
02894         wxOK | wxICON_INFORMATION, this);
02895 
02896     wxConfigBase* cfg=wxConfigBase::Get();
02897     cfg->Write(wxT("/GLPreviewFrame/ShowProjectionHints"), false);
02898     m_showProjectionHints=false;
02899     cfg->Flush();
02900     e.Skip();
02901 };
02902 
02903 void GLPreviewFrame::UpdateIdentifyTools(std::set<unsigned int> new_image_set)
02904 {
02905     if(identify_tool)
02906     {
02907         identify_tool->UpdateWithNewImageSet(new_image_set);
02908     };
02909     if(panosphere_overview_identify_tool)
02910     {
02911         panosphere_overview_identify_tool->UpdateWithNewImageSet(new_image_set);
02912     };
02913     if(plane_overview_identify_tool)
02914     {
02915         plane_overview_identify_tool->UpdateWithNewImageSet(new_image_set);
02916     };
02917 }
02918 
02919 void GLPreviewFrame::OnPreviewBackgroundColorChanged(wxColourPickerEvent & e) {
02920     m_preview_background_color = XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->GetColour();
02921     wxString c = m_preview_background_color.GetAsString(wxC2S_HTML_SYNTAX);
02922     wxConfigBase* cfg=wxConfigBase::Get();
02923     cfg->Write(wxT("/GLPreviewFrame/PreviewBackground"), c);
02924     cfg->Flush();
02925     panosphere_sphere_tool->SetPreviewBackgroundColor(m_preview_background_color);
02926     m_GLPreview->SetViewerBackground(m_preview_background_color);
02927     m_GLOverview->SetViewerBackground(m_preview_background_color);
02928     redrawPreview();
02929 }
02930 
02931 wxColor GLPreviewFrame::GetPreviewBackgroundColor() {
02932   return m_preview_background_color;
02933 }
02934 
02935 void GLPreviewFrame::OnGuideChanged(wxCommandEvent &e)
02936 {
02937     if(preview_guide_tool)
02938     {
02939         int selection=e.GetSelection();
02940         preview_guide_tool->SetGuideStyle((PreviewGuideTool::Guides)selection);
02941         //synchronize wxChoice in projection and crop tab
02942         m_GuideChoiceCrop->SetSelection(selection);
02943         m_GuideChoiceProj->SetSelection(selection);
02944         m_GuideChoiceDrag->SetSelection(selection);
02945         redrawPreview();
02946     };
02947 };
02948 
02949 void GLPreviewFrame::SetGuiLevel(GuiLevel newLevel)
02950 {
02951     int old_selection=m_DragModeChoice->GetSelection();
02952     if(old_selection==wxNOT_FOUND)
02953     {
02954         old_selection=0;
02955     };
02956     m_DragModeChoice->Clear();
02957     m_DragModeChoice->Append(_("normal"));
02958     m_DragModeChoice->Append(_("normal, individual"));
02959     if(newLevel==GUI_EXPERT)
02960     {
02961         m_DragModeChoice->Append(_("mosaic"));
02962         m_DragModeChoice->Append(_("mosaic, individual"));
02963         m_DragModeChoice->SetSelection(old_selection);
02964     }
02965     else
02966     {
02967         if(old_selection>1)
02968         {
02969             m_DragModeChoice->SetSelection(old_selection-2);
02970         }
02971         else
02972         {
02973             m_DragModeChoice->SetSelection(old_selection);
02974         };
02975     };
02976     DragChoiceLayout(m_DragModeChoice->GetSelection());
02977     wxCommandEvent dummy;
02978     OnDragChoice(dummy);
02979 
02980     old_selection=m_OverviewModeChoice->GetSelection();
02981     m_OverviewModeChoice->Clear();
02982     m_OverviewModeChoice->Append(_("Panosphere"));
02983     if(newLevel==GUI_EXPERT)
02984     {
02985         m_OverviewModeChoice->Append(_("Mosaic plane"));
02986     };
02987     if(newLevel==GUI_EXPERT && old_selection==1)
02988     {
02989         m_OverviewModeChoice->SetSelection(1);
02990     }
02991     else
02992     {
02993         m_GLOverview->SetMode(GLOverview::PANOSPHERE);
02994         m_OverviewModeChoice->SetSelection(0);
02995     };
02996     wxPanel* panel=XRCCTRL(*this, "overview_command_panel", wxPanel);
02997     panel->Show(newLevel==GUI_EXPERT);
02998     panel->GetParent()->Layout();
02999     if(newLevel==GUI_SIMPLE)
03000     {
03001 #ifdef __WXMAC__
03002         wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
03003 #endif
03004         if(m_guiLevel!=GUI_SIMPLE)
03005         {
03006             GetMenuBar()->Remove(0);
03007             GetMenuBar()->Insert(0, m_filemenuSimple, _("&File"));
03008         };
03009         SetTitle(MainFrame::Get()->GetTitle());
03010     }
03011     else
03012     {
03013 #ifdef __WXMAC__
03014         wxApp::s_macExitMenuItemId = XRCID("action_exit_hugin");
03015 #endif
03016         if(m_guiLevel==GUI_SIMPLE)
03017         {
03018             GetMenuBar()->Remove(0);
03019             GetMenuBar()->Insert(0, m_filemenuAdvanced, _("&File"));
03020         };
03021         SetTitle(_("Fast Panorama preview"));
03022     };
03023     m_guiLevel=newLevel;
03024     // update menu items
03025     switch(m_guiLevel)
03026     {
03027         case GUI_SIMPLE:
03028             GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
03029             break;
03030         case GUI_ADVANCED:
03031             GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
03032             break;
03033         case GUI_EXPERT:
03034             GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
03035             break;
03036     };
03037 };
03038 
03039 void GLPreviewFrame::OnShowMainFrame(wxCommandEvent &e)
03040 {
03041     MainFrame::Get()->Show();
03042     MainFrame::Get()->Raise();
03043 };
03044 
03045 void GLPreviewFrame::OnUserExit(wxCommandEvent &e)
03046 {
03047     Close();
03048 };
03049 
03050 void GLPreviewFrame::OnLoadImages( wxCommandEvent & e )
03051 {
03052     // load the images.
03053     PanoOperation::AddImageOperation addImage;
03054     HuginBase::UIntSet images;
03055     PanoCommand::PanoCommand* cmd=addImage.GetCommand(wxGetActiveWindow(), m_pano, images, m_guiLevel);
03056     if(cmd==NULL)
03057     {
03058         return;
03059     }
03060     //distribute images only if the existing images are not connected
03061     //otherwise it would destruct the existing image pattern
03062     bool distributeImages=m_pano.getNrOfCtrlPoints()==0;
03063 
03064     long autoAlign = wxConfigBase::Get()->Read(wxT("/Assistant/autoAlign"), HUGIN_ASS_AUTO_ALIGN); 
03065     if (autoAlign)
03066     {
03067         PanoCommand::GlobalCmdHist::getInstance().addCommand(cmd);
03068         wxCommandEvent dummy;
03069         OnAlign(dummy);
03070     }
03071     else
03072     {
03073         std::vector<PanoCommand::PanoCommand*> cmds;
03074         cmds.push_back(cmd);
03075         if(distributeImages)
03076         {
03077             cmds.push_back(new PanoCommand::DistributeImagesCmd(m_pano));
03078             cmds.push_back(new PanoCommand::CenterPanoCmd(m_pano));
03079         };
03080         PanoCommand::CombinedPanoCommand* combinedCmd = new PanoCommand::CombinedPanoCommand(m_pano, cmds);
03081         combinedCmd->setName("add and distribute images");
03082         PanoCommand::GlobalCmdHist::getInstance().addCommand(combinedCmd);
03083     };
03084 }
03085 
03086 void GLPreviewFrame::OnAlign( wxCommandEvent & e )
03087 {
03088     MainFrame::Get()->RunAssistant(this);
03089 }
03090 
03091 void GLPreviewFrame::OnCreate( wxCommandEvent & e )
03092 {
03093     PanoOutputDialog dlg(this, m_pano, m_guiLevel);
03094     if(dlg.ShowModal()==wxID_OK)
03095     {
03096         PanoCommand::GlobalCmdHist::getInstance().addCommand(
03097             new PanoCommand::SetPanoOptionsCmd(m_pano, dlg.GetNewPanoramaOptions())
03098             );
03099         wxCommandEvent dummy;
03100         MainFrame::Get()->OnDoStitch(dummy);
03101     };
03102 }
03103 
03104 void GLPreviewFrame::OnLensTypeChanged (wxCommandEvent & e)
03105 {
03106     // uses enum Lens::LensProjectionFormat from PanoramaMemento.h
03107     size_t var = GetSelectedValue(m_lensTypeChoice);
03108     const HuginBase::SrcPanoImage& img=m_pano.getImage(0);
03109     if (img.getProjection() != (HuginBase::Lens::LensProjectionFormat) var)
03110     {
03111         double fl = HuginBase::SrcPanoImage::calcFocalLength(img.getProjection(), img.getHFOV(), img.getCropFactor(), img.getSize());
03112         HuginBase::UIntSet imgs;
03113         imgs.insert(0);
03114         std::vector<PanoCommand::PanoCommand*> commands;
03115         commands.push_back(
03116                 new PanoCommand::ChangeImageProjectionCmd(
03117                                     m_pano,
03118                                     imgs,
03119                                     (HuginBase::SrcPanoImage::Projection) var
03120                                 )
03121             );
03122         
03123         commands.push_back(new PanoCommand::UpdateFocalLengthCmd(m_pano, imgs, fl));
03124         PanoCommand::GlobalCmdHist::getInstance().addCommand(
03125                 new PanoCommand::CombinedPanoCommand(m_pano, commands));
03126     }
03127 }
03128 
03129 void GLPreviewFrame::OnFocalLengthChanged(wxCommandEvent & e)
03130 {
03131     if (m_pano.getNrOfImages() == 0)
03132     {
03133         return;
03134     };
03135 
03136     // always change first lens
03137     wxString text = m_focalLengthText->GetValue();
03138     DEBUG_INFO("focal length: " << text.mb_str(wxConvLocal));
03139     double val;
03140     if (!hugin_utils::str2double(text, val))
03141     {
03142         return;
03143     }
03144     //no negative values, no zero input please
03145     if (val<0.1)
03146     {
03147         wxBell();
03148         return;
03149     };    
03150 
03151     // always change first lens...
03152     HuginBase::UIntSet images0;
03153     images0.insert(0);
03154     PanoCommand::GlobalCmdHist::getInstance().addCommand(
03155         new PanoCommand::UpdateFocalLengthCmd(m_pano, images0, val)
03156     );
03157 }
03158 
03159 void GLPreviewFrame::OnCropFactorChanged(wxCommandEvent & e)
03160 {
03161     if (m_pano.getNrOfImages() == 0)
03162     {
03163         return;
03164     };
03165 
03166     wxString text = m_cropFactorText->GetValue();
03167     DEBUG_INFO("crop factor: " << text.mb_str(wxConvLocal));
03168     double val;
03169     if (!hugin_utils::str2double(text, val))
03170     {
03171         return;
03172     }
03173     //no negative values, no zero input please
03174     if (val<0.1)
03175     {
03176         wxBell();
03177         return;
03178     };    
03179 
03180     HuginBase::UIntSet images;
03181     images.insert(0);
03182     PanoCommand::GlobalCmdHist::getInstance().addCommand(
03183         new PanoCommand::UpdateCropFactorCmd(m_pano,images,val)
03184     );
03185 }
03186 
03187 // remove cp, relatively easy, we get the selected cp from the edit cp tool
03188 void GLPreviewFrame::OnRemoveCP(wxCommandEvent & e)
03189 {
03190     edit_cp_tool->SetMenuProcessed();
03191     PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::RemoveCtrlPointsCmd(m_pano, edit_cp_tool->GetFoundCPs()));
03192     // ask user, if pano should be optimized
03193     long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
03194     bool optimize = false;
03195     if (afterEditCPAction == 0)
03196     {
03197         wxDialog dlg;
03198         wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("edit_cp_optimize_dialog"));
03199         XRCCTRL(dlg, "edit_cp_text1", wxStaticText)->SetLabel(wxString::Format(_("%lu control points were removed from the panorama.\n\nShould the panorama now be re-optimized?"), static_cast<unsigned long int>(edit_cp_tool->GetFoundCPs().size())));
03200         XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
03201         dlg.Fit();
03202         optimize = (dlg.ShowModal() == wxID_OK);
03203         if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
03204         {
03205             if (optimize)
03206             {
03207                 wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
03208             }
03209             else
03210             {
03211                 wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
03212             };
03213         };
03214     }
03215     else
03216     {
03217         optimize = (afterEditCPAction == 1);
03218     }
03219     if (optimize)
03220     {
03221         // invoke optimization routine
03222         wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
03223         MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
03224     };
03225 };
03226 
03227 // some helper for cp generation
03228 // maximal width for remapping for cp generating
03229 #define MAX_DIMENSION 1600
03230 struct FindStruct
03231 {
03232     size_t imgNr;
03233     vigra::BRGBImage image;
03234     vigra::BImage mask;
03235 };
03236 
03237 typedef std::vector<FindStruct> FindVector;
03238 typedef std::multimap<double, vigra::Diff2D> MapPoints;
03239 
03240 static hugin_omp::Lock cpLock;
03241 
03242 void GLPreviewFrame::OnCreateCP(wxCommandEvent & e)
03243 {
03244     edit_cp_tool->SetMenuProcessed();
03245     vigra::Rect2D roi = edit_cp_tool->GetSelectedROI();
03246     HuginBase::UIntSet imgs = HuginBase::getImagesinROI(m_pano, m_pano.getActiveImages(), roi);
03247     // some checking of conditions
03248     if (imgs.empty())
03249     {
03250         wxMessageBox(_("The selected region contains no active image.\nPlease select a region which is covered by at least 2 images."),
03251 #ifdef __WXMSW__
03252             _("Hugin"),
03253 #else
03254             wxT(""),
03255 #endif
03256             wxOK | wxICON_INFORMATION, this);
03257         return;
03258     };
03259     if (imgs.size() < 2)
03260     {
03261         wxMessageBox(_("The selected region is only covered by a single image.\nCan't create control points for a single image."),
03262 #ifdef __WXMSW__
03263             _("Hugin"),
03264 #else
03265             wxT(""),
03266 #endif
03267             wxOK | wxICON_INFORMATION, this);
03268         return;
03269     };
03270     if (roi.width() > 0.25 * m_pano.getOptions().getWidth())
03271     {
03272         if(wxMessageBox(_("The selected rectangle is very big.\nThis function is only intended for smaller areas. Otherwise unwanted side effect can appear.\n\nProceed anyway?"),
03273 #ifdef __WXMSW__
03274             _("Hugin"),
03275 #else
03276             wxT(""),
03277 #endif
03278             wxYES_NO | wxICON_INFORMATION, this) == wxNO)
03279         {
03280             return;
03281         };
03282     }
03283     HuginBase::PanoramaOptions opts = m_pano.getOptions();
03284     opts.setROI(roi);
03285     // don't correct exposure
03286     opts.outputExposureValue = 0;
03287     // don't use GPU for remapping, this interfere with the fast preview window
03288     opts.remapUsingGPU = false;
03289     // rescale if size is too big
03290     if (roi.width() > MAX_DIMENSION)
03291     {
03292         opts.setWidth(opts.getWidth() * MAX_DIMENSION / roi.width(), true);
03293         roi = opts.getROI();
03294     };
03295     HuginBase::CPVector cps;
03296     {
03297         ProgressReporterDialog progress(2*imgs.size()+1, _("Searching control points"), _("Processing"), this);
03298         // remap all images to panorama projection
03299         FindVector cpInfos;
03300         HuginBase::CPVector tempCps;
03301         for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
03302         {
03303             const size_t imgNr = *it;
03304             if (!progress.updateDisplayValue(_("Remap image to panorama projection...")))
03305             {
03306                 return;
03307             };
03308             FindStruct findStruct;
03309             findStruct.imgNr = imgNr;
03310             // remap image to panorama projection
03311             ImageCache::ImageCacheRGB8Ptr CachedImg = ImageCache::getInstance().getImage(m_pano.getImage(imgNr).getFilename())->get8BitImage();
03312 
03313             HuginBase::Nona::RemappedPanoImage<vigra::BRGBImage, vigra::BImage>* remapped = new HuginBase::Nona::RemappedPanoImage<vigra::BRGBImage, vigra::BImage>;
03314             HuginBase::SrcPanoImage srcImg = m_pano.getSrcImage(imgNr);
03315             // don't correct exposure
03316             srcImg.setExposureValue(0);
03317             remapped->setPanoImage(srcImg, opts, roi);
03318             remapped->remapImage(vigra::srcImageRange(*CachedImg), vigra_ext::INTERP_CUBIC, &progress);
03319             if (!progress.updateDisplay())
03320             {
03321                 delete remapped;
03322                 return;
03323             };
03324             findStruct.image = remapped->m_image;
03325             findStruct.mask = remapped->m_mask;
03326             delete remapped;
03327             cpInfos.push_back(findStruct);
03328         };
03329         if (cpInfos.size() > 1)
03330         {
03331             // match keypoints in all image pairs
03332             // select a sensible grid size depending on ratio of selected region, maximal should it be 25 regions
03333             unsigned gridx = hugin_utils::roundi(sqrt((double)roi.width() / (double)roi.height() * 25));
03334             if (gridx < 1)
03335             {
03336                 gridx = 1;
03337             }
03338             unsigned gridy = hugin_utils::roundi(25 / gridx);
03339             if (gridy < 1)
03340             {
03341                 gridy = 1;
03342             }
03343             // template width
03344             const long templWidth = 20;
03345             // search width
03346             const long sWidth = 100;
03347             // match all images with all
03348             for (size_t img1 = 0; img1 < cpInfos.size() - 1; ++img1)
03349             {
03350                 if (!progress.updateDisplayValue(_("Matching interest points...")))
03351                 {
03352                     return;
03353                 };
03354                 vigra::Size2D size(cpInfos[img1].image.width(), cpInfos[img1].image.height());
03355                 // create a number of sub-regions
03356                 std::vector<vigra::Rect2D> rects;
03357                 for (unsigned party = 0; party < gridy; party++)
03358                 {
03359                     for (unsigned partx = 0; partx < gridx; partx++)
03360                     {
03361                         vigra::Rect2D rect(partx*size.x / gridx, party*size.y / gridy,
03362                             (partx + 1)*size.x / gridx, (party + 1)*size.y / gridy);
03363                         rect &= vigra::Rect2D(size);
03364                         if (rect.width()>0 && rect.height()>0)
03365                         {
03366                             rects.push_back(rect);
03367                         };
03368                     };
03369                 };
03370 
03371                 if (!progress.updateDisplay())
03372                 {
03373                     return;
03374                 };
03375 
03376 #pragma omp parallel for schedule(dynamic)
03377                 for (int i = 0; i < rects.size(); ++i)
03378                 {
03379                     MapPoints points;
03380                     vigra::Rect2D rect(rects[i]);
03381                     // run interest point detection in sub-region
03382                     vigra_ext::findInterestPointsPartial(srcImageRange(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >()), rect, 2, 5 * 8, points);
03383                     //check if all points are inside the given image
03384                     MapPoints validPoints;
03385                     for (MapPoints::const_iterator it = points.begin(); it != points.end(); ++it)
03386                     {
03387                         if (cpInfos[img1].mask(it->second.x, it->second.y)>0)
03388                         {
03389                             validPoints.insert(*it);
03390                         };
03391                     };
03392 
03393                     if (!validPoints.empty())
03394                     {
03395                         // now fine-tune the interest points with all other images
03396                         for (size_t img2 = img1 + 1; img2 < cpInfos.size(); ++img2)
03397                         {
03398                             unsigned nGood = 0;
03399                             // loop over all points, starting with the highest corner score
03400                             for (MapPoints::const_reverse_iterator it = validPoints.rbegin(); it != validPoints.rend(); ++it)
03401                             {
03402                                 if (nGood >= 2)
03403                                 {
03404                                     // we have enough points, stop
03405                                     break;
03406                                 }
03407                                 //check if point is covered by second image
03408                                 if (cpInfos[img2].mask(it->second.x, it->second.y) == 0)
03409                                 {
03410                                     continue;
03411                                 };
03412                                 // finally fine-tune point
03413                                 vigra_ext::CorrelationResult res = vigra_ext::PointFineTune(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, templWidth,
03414                                     cpInfos[img2].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, sWidth);
03415                                 if (res.maxi < 0.9)
03416                                 {
03417                                     continue;
03418                                 }
03419                                 nGood++;
03420                                 // add control point
03421                                 {
03422                                     hugin_omp::ScopedLock sl(cpLock);
03423                                     tempCps.push_back(HuginBase::ControlPoint(cpInfos[img1].imgNr, it->second.x, it->second.y,
03424                                         cpInfos[img2].imgNr, res.maxpos.x, res.maxpos.y, HuginBase::ControlPoint::X_Y));
03425                                 };
03426                             };
03427                         };
03428                     };
03429                 };
03430                 // free memory
03431                 cpInfos[img1].image.resize(0, 0);
03432                 cpInfos[img1].mask.resize(0, 0);
03433             };
03434 
03435             // transform coordinates back to image space
03436             for (size_t i = 0; i < tempCps.size(); ++i)
03437             {
03438                 HuginBase::ControlPoint cp = tempCps[i];
03439                 hugin_utils::FDiff2D p1(cp.x1 + roi.left(), cp.y1 + roi.top());
03440                 hugin_utils::FDiff2D p1Img;
03441                 HuginBase::PTools::Transform transform;
03442                 transform.createTransform(m_pano.getImage(cp.image1Nr), opts);
03443                 if (transform.transformImgCoord(p1Img, p1))
03444                 {
03445                     hugin_utils::FDiff2D p2(cp.x2 + roi.left(), cp.y2 + roi.top());
03446                     hugin_utils::FDiff2D p2Img;
03447                     transform.createTransform(m_pano.getImage(cp.image2Nr), opts);
03448                     if (transform.transformImgCoord(p2Img, p2))
03449                     {
03450                         cp.x1 = p1Img.x;
03451                         cp.y1 = p1Img.y;
03452                         cp.x2 = p2Img.x;
03453                         cp.y2 = p2Img.y;
03454                         cps.push_back(cp);
03455                     };
03456                 };
03457             };
03458 
03459             if (!cps.empty())
03460             {
03461                 // check newly found control points
03462                 // create copy
03463                 HuginBase::Panorama copyPano=m_pano.duplicate();
03464                 // remove all cps and set only the new found cp
03465                 copyPano.setCtrlPoints(cps);
03466                 // now create a subpano with only the selected images
03467                 HuginBase::Panorama subPano = copyPano.getSubset(imgs);
03468                 // clean control points
03469                 if (!progress.updateDisplayValue(_("Checking results...")))
03470                 {
03471                     return;
03472                 };
03473                 deregisterPTWXDlgFcn();
03474                 HuginBase::UIntSet invalidCP = HuginBase::getCPoutsideLimit(subPano);
03475                 registerPTWXDlgFcn();
03476                 if (!invalidCP.empty())
03477                 {
03478                     for (HuginBase::UIntSet::const_reverse_iterator it = invalidCP.rbegin(); it != invalidCP.rend(); ++it)
03479                     {
03480                         cps.erase(cps.begin() + *it);
03481                     };
03482                 }
03483                 // force closing progress dialog
03484                 if (!progress.updateDisplayValue())
03485                 {
03486                     return;
03487                 };
03488                 PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::AddCtrlPointsCmd(m_pano, cps));
03489                 // ask user, if pano should be optimized
03490                 long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
03491                 bool optimize = false;
03492                 if (afterEditCPAction == 0)
03493                 {
03494                     wxDialog dlg;
03495                     wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("edit_cp_optimize_dialog"));
03496                     XRCCTRL(dlg, "edit_cp_text1", wxStaticText)->SetLabel(wxString::Format(_("%lu control points were added to the panorama.\n\nShould the panorama now be re-optimized?"), static_cast<unsigned long int>(cps.size())));
03497                     XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
03498                     dlg.Fit();
03499                     optimize = (dlg.ShowModal() == wxID_OK);
03500                     if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
03501                     {
03502                         if (optimize)
03503                         {
03504                             wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
03505                         }
03506                         else
03507                         {
03508                             wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
03509                         };
03510                     };
03511                 }
03512                 else
03513                 {
03514                     optimize = (afterEditCPAction == 1);
03515                 }
03516                 if (optimize)
03517                 {
03518                     // invoke optimization routine
03519                     wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
03520                     MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
03521                 };
03522             };
03523         };
03524     };
03525     // finally redraw
03526     m_GLPreview->Update();
03527     m_GLPreview->Refresh();
03528 };
03529 
03530 // handle menu close event to redraw preview, so that selection rectangle is hidden
03531 void GLPreviewFrame::OnMenuClose(wxMenuEvent & e)
03532 {
03533     m_GLPreview->Refresh();
03534     e.Skip();
03535 };
03536 
03537 void GLPreviewFrame::OnSelectContextMenu(wxContextMenuEvent& e)
03538 {
03539     wxPoint point = e.GetPosition();
03540     // If from keyboard
03541     if (point.x == -1 && point.y == -1)
03542     {
03543         point = m_selectAllButton->GetPosition();
03544     }
03545     else
03546     {
03547         point = ScreenToClient(point);
03548     }
03549     PopupMenu(m_selectAllMenu, point);
03550 };
03551 
03552 void GLPreviewFrame::OnSelectAllMenu(wxCommandEvent& e)
03553 {
03554     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
03555     m_selectAllMode = SELECT_ALL_IMAGES;
03556 };
03557 
03558 void GLPreviewFrame::OnSelectMedianMenu(wxCommandEvent& e)
03559 {
03560     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 1l);
03561     m_selectAllMode = SELECT_MEDIAN_IMAGES;
03562 };
03563 
03564 void GLPreviewFrame::OnSelectBrightestMenu(wxCommandEvent& e)
03565 {
03566     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 2l);
03567     m_selectAllMode = SELECT_BRIGHTEST_IMAGES;
03568 };
03569 
03570 void GLPreviewFrame::OnSelectDarkestMenu(wxCommandEvent& e)
03571 {
03572     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 3l);
03573     m_selectAllMode = SELECT_DARKEST_IMAGES;
03574 };
03575 
03576 void GLPreviewFrame::OnSelectKeepSelection(wxCommandEvent& e)
03577 {
03578     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), true);
03579     m_selectKeepSelection = true;
03580 };
03581 
03582 void GLPreviewFrame::OnSelectResetSelection(wxCommandEvent& e)
03583 {
03584     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), false);
03585     m_selectKeepSelection = false;
03586 };

Generated on 19 Aug 2017 for Hugintrunk by  doxygen 1.4.7