GLPreviewFrame.cpp

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

Generated on 26 Jul 2016 for Hugintrunk by  doxygen 1.4.7