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 "hugin_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->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().left() ));
00953     m_ROIRightTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().right() ));
00954     m_ROITopTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().top() ));
00955     m_ROIBottomTxt->ChangeValue(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()>0);
00964 
00965     if(pano.getNrOfImages()==0)
00966     {
00967         m_createButton->Disable();
00968         m_imagesText->SetLabel(_("No images loaded."));
00969     }
00970     else
00971     {
00972         bool enableCreate = false;
00973         // check if images are at position 0
00974         for (size_t i = 0; i < pano.getNrOfImages(); ++i)
00975         {
00976             const HuginBase::SrcPanoImage& img = pano.getImage(i);
00977             if (img.getYaw() != 0.0 || img.getPitch() != 0.0 || img.getRoll() != 0.0)
00978             {
00979                 enableCreate = true;
00980                 break;
00981             };
00982         };
00983         if (!enableCreate && pano.getNrOfImages() == 1)
00984         {
00985             // some more checks for single image projects
00986             if (pano.getOptions().getProjection() != HuginBase::PanoramaOptions::EQUIRECTANGULAR)
00987             {
00988                 enableCreate = true;
00989             };
00990             if (pano.getOptions().getROI() != vigra::Rect2D(pano.getOptions().getSize()))
00991             {
00992                 enableCreate = true;
00993             };
00994         };
00995         // disable create button after loading images
00996         const std::string lastCmd=PanoCommand::GlobalCmdHist::getInstance().getLastCommandName();
00997         if (lastCmd == "add images" || lastCmd== "add and distribute images")
00998         {
00999             enableCreate = false;
01000         }
01001         m_createButton->Enable(enableCreate);
01002 
01003         // in wxWidgets 2.9, format must have types that exactly match.
01004         // However std::size_t could be any unsiged integer, so we cast it to
01005         // unsigned long.int to be on the safe side.
01006         wxString imgMsg = wxString::Format(_("%lu images loaded."), (unsigned long int) pano.getNrOfImages());
01007         m_imagesText->SetLabel(imgMsg);
01008 
01009         // update data in lens display
01010         const HuginBase::SrcPanoImage& img = pano.getImage(0);
01011         SelectListValue(m_lensTypeChoice, img.getProjection());
01012         double focal_length = HuginBase::SrcPanoImage::calcFocalLength(img.getProjection(), img.getHFOV(), img.getCropFactor(), img.getSize());
01013         // use ChangeValue explicit, SetValue would create EVT_TEXT event which collides with our TextKillFocusHandler
01014         m_focalLengthText->ChangeValue(hugin_utils::doubleTowxString(focal_length,m_degDigits));
01015         m_cropFactorText->ChangeValue(hugin_utils::doubleTowxString(img.getCropFactor(),m_degDigits));
01016     }
01017 
01018     if (pano.getNrOfImages() > 1)
01019     {
01020         // in wxWidgets 2.9, format must have types that exactly match.
01021         // However std::size_t could be any unsiged integer, so we cast it to
01022         // unsigned long.int to be on the safe side.
01023         wxString alignMsg = wxString::Format(_("Images are connected by %lu control points.\n"), (unsigned long int) pano.getCtrlPoints().size());
01024 
01025         if (m_pano.getNrOfCtrlPoints() > 0)
01026         {
01027             // find components..
01028             HuginGraph::ImageGraph graph(m_pano);
01029             const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
01030             if (comps.size() > 1)
01031             {
01032                 alignMsg += wxString::Format(_("%lu unconnected image groups found: %s\n"), static_cast<unsigned long int>(comps.size()), Components2Str(comps).c_str());
01033             }
01034             else
01035             {
01036                 if (m_pano.needsOptimization())
01037                 {
01038                     alignMsg += _("Images or control points have changed, new alignment is needed.");
01039                 }
01040                 else
01041                 {
01042                     HuginBase::CalculateCPStatisticsError calcStats(m_pano, MainFrame::Get()->GetOptimizeOnlyActiveImages());
01043                     calcStats.run();
01044                     const double max = calcStats.getResultMax();
01045                     const double mean = calcStats.getResultMean();
01046 
01047                     if (max != 0.0)
01048                     {
01049                         alignMsg = alignMsg + wxString::Format(_("Mean error after optimization: %.1f pixel, max: %.1f"), mean, max); 
01050                     }
01051                 }
01052             }
01053         }
01054         XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(alignMsg);
01055         m_tool_notebook->GetPage(0)->Layout();
01056         Refresh();
01057     }
01058     else
01059     {
01060         XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(wxT(""));
01061     };
01062 
01063     GetMenuBar()->Enable(XRCID("ID_EDITUNDO"), PanoCommand::GlobalCmdHist::getInstance().canUndo());
01064     GetMenuBar()->Enable(XRCID("ID_EDITREDO"), PanoCommand::GlobalCmdHist::getInstance().canRedo());
01065 
01066     // TODO: update meaningful help text and dynamic links to relevant tabs
01067 
01068     const HuginBase::PanoramaOptions & opts = pano.getOptions();
01069 
01070     wxString projection;
01071     m_ProjectionChoice->SetSelection(opts.getProjection());
01072     m_VFOVSlider->Enable( opts.fovCalcSupported(opts.getProjection()) );
01073     
01074     // No HDR display yet.
01075     /*
01076     m_outputModeChoice->SetSelection(opts.outputMode);
01077     if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) {
01078         m_exposureTextCtrl->Hide();
01079         m_defaultExposureBut->Hide();
01080         m_decExposureBut->Hide();
01081         m_incExposureBut->Hide();
01082     } else {
01083         m_exposureTextCtrl->Show();
01084         m_defaultExposureBut->Show();
01085         m_decExposureBut->Show();
01086         m_incExposureBut->Show();
01087     }*/
01088     m_exposureTextCtrl->ChangeValue(wxString(hugin_utils::doubleToString(opts.outputExposureValue,2).c_str(), wxConvLocal));
01089 
01090     bool activeImgs = pano.getActiveImages().size() > 0;
01091 
01092     // TODO: enable display of parameters and set their limits, if projection has some.
01093 
01094     int nParam = opts.m_projFeatures.numberOfParameters;
01095     bool relayout = false;
01096     // if the projection format has changed
01097     if (opts.getProjection() != m_oldProjFormat) {
01098         DEBUG_DEBUG("Projection format changed");
01099         if (nParam) {
01100             // show parameters and update labels.
01101             m_projection_panel->GetSizer()->Show(m_projParamSizer, true, true);
01102             int i;
01103             for (i=0; i < nParam; i++) {
01104                 const pano_projection_parameter * pp = & (opts.m_projFeatures.parm[i]);
01105                 wxString str2(pp->name, wxConvLocal);
01106                 str2 = wxGetTranslation(str2);
01107                 m_projParamNamesLabel[i]->SetLabel(str2);
01108                 m_projParamSlider[i]->SetRange(hugin_utils::roundi(pp->minValue), hugin_utils::roundi(pp->maxValue));
01109             }
01110             for(;i < PANO_PROJECTION_MAX_PARMS; i++) {
01111                 m_projParamNamesLabel[i]->Hide();
01112                 m_projParamSlider[i]->Hide();
01113                 m_projParamTextCtrl[i]->Hide();
01114             }
01115             relayout = true;
01116         } else {
01117             m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
01118             relayout = true;
01119         }
01120     }
01121     if (nParam) {
01122         // display new values
01123         std::vector<double> params = opts.getProjectionParameters();
01124         assert((int) params.size() == nParam);
01125         for (int i=0; i < nParam; i++) {
01126             wxString val = wxString(hugin_utils::doubleToString(params[i],1).c_str(), wxConvLocal);
01127             m_projParamTextCtrl[i]->ChangeValue(wxString(val.wc_str(), wxConvLocal));
01128             m_projParamSlider[i]->SetValue(hugin_utils::roundi(params[i]));
01129         }
01130     }
01131     if (relayout) {
01132         m_projection_panel->Layout();
01133         Refresh();
01134     }
01135     SetStatusText(wxString::Format(wxT("%.1f x %.1f"), opts.getHFOV(), opts.getVFOV()),2);
01136     m_HFOVSlider->SetValue(hugin_utils::roundi(opts.getHFOV()));
01137     m_VFOVSlider->SetValue(hugin_utils::roundi(opts.getVFOV()));
01138     std::string val;
01139     val = hugin_utils::doubleToString(opts.getHFOV(),1);
01140     m_HFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
01141     val = hugin_utils::doubleToString(opts.getVFOV(),1);
01142     m_VFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
01143     m_VFOVText->Enable(opts.fovCalcSupported(opts.getProjection()));
01144 
01145     m_oldProjFormat = opts.getProjection();
01146 
01147     XRCCTRL(*this,"preview_autocrop_tool",wxButton)->Enable(activeImgs);
01148     XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->Enable(activeImgs);
01149     UpdateRoiDisplay(opts);
01150     
01151     if(m_showProjectionHints)
01152     {
01153         ShowProjectionWarnings();
01154     };
01155     redrawPreview();
01156 }
01157 
01158 void GLPreviewFrame::panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
01159 {
01160     DEBUG_TRACE("");
01161 
01162     bool dirty = false;
01163 
01164     unsigned int nrImages = pano.getNrOfImages();
01165     unsigned int nrButtons = m_ToggleButtons.size();
01166     
01167     GetMenuBar()->Enable(XRCID("action_optimize"), nrImages > 0);
01168 
01169 //    m_displayedImgs.clear();
01170 
01171     // remove items for nonexisting images
01172     for (int i=nrButtons-1; i>=(int)nrImages; i--)
01173     {
01174         m_ButtonSizer->Detach(m_ToggleButtonPanel[i]);
01175         // Image toggle buttons have a event handler on the stack which
01176         // must be removed before the buttons get destroyed.
01177         m_ToggleButtons[i]->PopEventHandler();
01178         m_GroupToggleButtons[i]->PopEventHandler();
01179         delete m_ToggleButtons[i];
01180         delete m_GroupToggleButtons[i];
01181         delete m_ToggleButtonPanel[i];
01182         m_ToggleButtons.pop_back();
01183         m_GroupToggleButtons.pop_back();
01184         m_ToggleButtonPanel.pop_back();
01185         delete toogle_button_event_handlers[i];
01186         toogle_button_event_handlers.pop_back();
01187         delete toggle_group_button_event_handlers[i];
01188         toggle_group_button_event_handlers.pop_back();
01189         dirty = true;
01190     }
01191 
01192     //change overview mode to panosphere if the translation plane parameter are non zero
01193     if (m_GLOverview->GetMode() == GLOverview::PLANE)
01194     {
01195         if (HasNonZeroTranslationPlaneParameters())
01196         {
01197             m_GLOverview->SetMode(GLOverview::PANOSPHERE);
01198             m_OverviewModeChoice->SetSelection(0);
01199             //check if drag mode is mosaic, if so reset to normal
01200             if(drag_tool)
01201             {
01202                 if(drag_tool->getDragMode()==DragTool::drag_mode_mosaic)
01203                 {
01204                     m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
01205                     drag_tool->setDragMode(DragTool::drag_mode_normal);
01206                     EnableGroupCheckboxes(individualDragging());
01207                     // adjust the layout
01208                     DragChoiceLayout(m_DragModeChoice->GetSelection());
01209                 };
01210             };
01211         }
01212     }
01213 
01214     // add buttons
01215     if ( nrImages >= nrButtons ) {
01216         for(HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it){
01217             if (*it >= nrButtons) {
01218                 // create new item.
01219 //                wxImage * bmp = new wxImage(sz.GetWidth(), sz.GetHeight());
01220                 //put wxToggleButton in a wxPanel because 
01221                 //on Windows the background colour of wxToggleButton can't be changed
01222                 wxPanel *pan = new wxPanel(m_ButtonPanel);
01223                 wxBoxSizer * siz = new wxBoxSizer(wxVERTICAL);
01224                 pan->SetSizer(siz);
01225 #ifdef USE_TOGGLE_BUTTON
01226                 wxToggleButton * but = new wxToggleButton(pan,
01227                                                           ID_TOGGLE_BUT + *it,
01228                                                           wxString::Format(wxT("%d"),*it),
01229                                                           wxDefaultPosition, wxDefaultSize,
01230                                                           wxBU_EXACTFIT);
01231 #else
01232                 wxCheckBox * but = new wxCheckBox(pan,
01233                                                   ID_TOGGLE_BUT + *it,
01234                                                   wxString::Format(wxT("%d"),*it));
01235 #endif
01236                 
01237                 wxCheckBox *butcheck = new wxCheckBox(pan, wxID_ANY, wxT(""));
01238 
01239 #ifdef __WXMSW__
01240                 //we need a border around the button to see the colored panel
01241                 //because changing backgroundcolor of wxToggleButton does not work in wxMSW
01242                 siz->AddSpacer(5);
01243                 siz->Add(butcheck, 0, wxALIGN_CENTRE_HORIZONTAL | wxFIXED_MINSIZE, 0);
01244                 siz->Add(but,0,wxLEFT | wxRIGHT | wxBOTTOM , 5);
01245 #else
01246                 siz->Add(but,0,wxALL ,0);
01247                 siz->Add(butcheck, 0, wxALL | wxFIXED_MINSIZE, 0);
01248 #endif
01249                 // for the identification tool to work, we need to find when the
01250                 // mouse enters and exits the button. We use a custom event
01251                 // handler, which will also toggle the images:
01252                 ImageToogleButtonEventHandler * event_handler = new
01253                     ImageToogleButtonEventHandler(*it,
01254                         m_ToolBar_Identify->FindById(XRCID("preview_identify_tool")),
01255                         &m_pano);
01256                 event_handler->AddIdentifyTool(&identify_tool);
01257                 event_handler->AddIdentifyTool(&panosphere_overview_identify_tool);
01258                 event_handler->AddIdentifyTool(&plane_overview_identify_tool);
01259                 toogle_button_event_handlers.push_back(event_handler);
01260                 but->PushEventHandler(event_handler);
01261 
01262                 ImageGroupButtonEventHandler * group_event_handler = new 
01263                     ImageGroupButtonEventHandler(*it, this, &m_pano);
01264                 group_event_handler->AddDragTool((DragTool**) &drag_tool);
01265                 group_event_handler->AddDragTool((DragTool**) &overview_drag_tool);
01266                 group_event_handler->AddIdentifyTool(&identify_tool);
01267                 group_event_handler->AddIdentifyTool(&panosphere_overview_identify_tool);
01268                 group_event_handler->AddIdentifyTool(&plane_overview_identify_tool);
01269                 toggle_group_button_event_handlers.push_back(group_event_handler);
01270                 butcheck->PushEventHandler(group_event_handler);
01271                 butcheck->Show(individualDragging() && m_mode==mode_drag);
01272 
01273                 but->SetValue(true);
01274                 m_ButtonSizer->Add(pan,
01275                                    0,
01276                                    wxLEFT | wxTOP,
01277                                    0);
01278                 m_ToggleButtons.push_back(but);
01279                 m_GroupToggleButtons.push_back(butcheck);
01280                 m_ToggleButtonPanel.push_back(pan);
01281                 dirty = true;
01282             }
01283         }
01284     }
01285 
01286     // update existing items
01287     HuginBase::UIntSet displayedImages = m_pano.getActiveImages();
01288     for (unsigned i=0; i < nrImages; i++) {
01289         m_ToggleButtons[i]->SetValue(set_contains(displayedImages, i));
01290         wxFileName tFilename(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
01291         m_ToggleButtons[i]->SetToolTip(tFilename.GetFullName());
01292     }
01293 
01294     if (dirty) {
01295         m_ButtonSizer->FitInside(m_ButtonPanel);
01296                 Layout();
01297                 DEBUG_INFO("New m_ButtonPanel width: " << (m_ButtonPanel->GetSize()).GetWidth());
01298                 DEBUG_INFO("New m_ButtonPanel Height: " << (m_ButtonPanel->GetSize()).GetHeight());
01299     }
01300     if(nrImages==0)
01301     {
01302         SetMode(mode_assistant);
01303         m_tool_notebook->ChangeSelection(mode_assistant);
01304     };
01305     for(size_t i=2; i<m_tool_notebook->GetPageCount();i++)
01306     {
01307         m_tool_notebook->GetPage(i)->Enable(nrImages!=0);
01308     };
01309     redrawPreview();
01310 }
01311 
01312 void GLPreviewFrame::redrawPreview()
01313 {
01314     m_GLPreview->Refresh();
01315     m_GLOverview->Refresh();
01316 }
01317 
01318 void GLPreviewFrame::OnShowEvent(wxShowEvent& e)
01319 {
01320 
01321     DEBUG_TRACE("OnShow");
01322     bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
01323     wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
01324     if (inf.IsOk()) {
01325         if (e.IsShown()) {
01326             if (!inf.IsShown() && toggle_on ) {
01327                 inf.Show();
01328                 m_mgr->Update();
01329             }
01330         } else {
01331             if (inf.IsFloating() && inf.IsShown()) {
01332                 DEBUG_DEBUG("hiding overview float");
01333                 inf.Hide();
01334                 m_mgr->Update();
01335             }
01336         }
01337     }
01338 
01339 }
01340 
01341 //the following methods are to substitude the GLViewer KeyUp and KeyDown methods
01342 //so that tools use key events that happen globally to the preview frame
01343 //however only key up event is sent, and not key down
01344 //so until this is resolved they will remain to be handled by GLViewer
01345 void GLPreviewFrame::KeyDown(wxKeyEvent& e)
01346 {
01347     if (preview_helper) {
01348         preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
01349     }
01350     if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
01351         if(m_GLOverview->GetMode() == GLOverview::PLANE) {
01352             if (plane_overview_helper) {
01353                 plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
01354             }
01355         } else if (m_GLOverview->GetMode() == GLOverview::PANOSPHERE) {
01356             if (panosphere_overview_helper) {
01357                 panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
01358             }
01359         }
01360     
01361     }
01362     e.Skip();
01363 }
01364 
01365 void GLPreviewFrame::KeyUp(wxKeyEvent& e)
01366 {
01367     if (preview_helper) {
01368         preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
01369     }
01370     if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
01371         if(m_GLOverview->GetMode() == GLOverview::PLANE) {
01372             if (plane_overview_helper) {
01373                 plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
01374             }
01375         } else if (m_GLOverview->GetMode() == GLOverview::PANOSPHERE) {
01376             if (panosphere_overview_helper) {
01377                 panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
01378             }
01379         }
01380     
01381     }
01382     e.Skip();
01383 }
01384 
01385 
01386 
01387 void GLPreviewFrame::OnOverviewToggle(wxCommandEvent& e)
01388 {
01389     DEBUG_TRACE("overview toggle");
01390     bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
01391     wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
01392     if (inf.IsOk()) {
01393         if (inf.IsShown() && !toggle_on) {
01394             inf.Hide();
01395             m_GLOverview->SetActive(false);
01396             m_mgr->Update();
01397         } else if (!(inf.IsShown() && toggle_on)) {
01398             inf.Show();
01399 #if defined __WXMSW__ || defined __WXMAC__
01400             m_GLOverview->SetActive(true);
01401             m_mgr->Update();
01402 #else
01403             m_mgr->Update();
01404             m_GLOverview->SetActive(true);
01405 #endif
01406         }
01407     }
01408 }
01409 
01410 void GLPreviewFrame::OnSwitchPreviewGrid(wxCommandEvent & e)
01411 {
01412     if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
01413     {
01414         preview_helper->ActivateTool(preview_projection_grid);
01415         panosphere_overview_helper->ActivateTool(overview_projection_grid);
01416     }
01417     else
01418     {
01419         preview_helper->DeactivateTool(preview_projection_grid);
01420         panosphere_overview_helper->DeactivateTool(overview_projection_grid);
01421     }
01422     m_GLPreview->Refresh();
01423     m_GLOverview->Refresh();
01424 }
01425 
01426 void GLPreviewFrame::OnClose(wxCloseEvent& event)
01427 {
01428     DEBUG_TRACE("OnClose")
01429     // do not close, just hide if we're not forced
01430     if(m_guiLevel==GUI_SIMPLE)
01431     {
01432         if(!MainFrame::Get()->CloseProject(event.CanVeto(), MainFrame::CLOSE_PROGRAM))
01433         {
01434            if (event.CanVeto())
01435            {
01436                event.Veto();
01437                return;
01438            };
01439         };
01440         MainFrame::Get()->Close(true);
01441     }
01442     else
01443     {
01444         if (event.CanVeto())
01445         {
01446             event.Veto();
01447             Hide();
01448             DEBUG_DEBUG("hiding");
01449         }
01450         else
01451         {
01452             DEBUG_DEBUG("closing");
01453             this->Destroy();
01454         }
01455     };
01456 }
01457 
01458 #if 0
01459 // need to add the wxChoice somewhere
01460 void PreviewFrame::OnProjectionChanged()
01461 {
01462     PanoramaOptions opt = m_pano.getOptions();
01463     int lt = m_ProjectionChoice->GetSelection();
01464     wxString Ip;
01465     switch ( lt ) {
01466     case PanoramaOptions::RECTILINEAR:       Ip = _("Rectilinear"); break;
01467     case PanoramaOptions::CYLINDRICAL:       Ip = _("Cylindrical"); break;
01468     case PanoramaOptions::EQUIRECTANGULAR:   Ip = _("Equirectangular"); break;
01469     }
01470     opt.projectionFormat = (PanoramaOptions::ProjectionFormat) lt;
01471     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01472         new PanoCommand::SetPanoOptionsCmd( pano, opt )
01473         );
01474     DEBUG_DEBUG ("Projection changed: "  << lt << ":" << Ip )
01475 
01476 
01477 }
01478 #endif
01479 
01480 void GLPreviewFrame::OnCenterHorizontally(wxCommandEvent & e)
01481 {
01482     if (m_pano.getActiveImages().size() == 0) return;
01483 
01484     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01485         new PanoCommand::CenterPanoCmd(m_pano)
01486         );
01487 }
01488 
01489 void GLPreviewFrame::OnStraighten(wxCommandEvent & e)
01490 {
01491     if (m_pano.getNrOfImages() == 0) return;
01492 
01493     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01494         new PanoCommand::StraightenPanoCmd(m_pano)
01495         );
01496 }
01497 
01498 void GLPreviewFrame::OnFitPano(wxCommandEvent & e)
01499 {
01500     if (m_pano.getActiveImages().size() == 0) return;
01501 
01502     DEBUG_TRACE("");
01503     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01504     HuginBase::CalculateFitPanorama fitPano(m_pano);
01505     fitPano.run();
01506     opt.setHFOV(fitPano.getResultHorizontalFOV());
01507     opt.setHeight(hugin_utils::roundi(fitPano.getResultHeight()));
01508 
01509     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01510         new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01511         );
01512 
01513     DEBUG_INFO ( "new fov: [" << opt.getHFOV() << " "<< opt.getVFOV() << "] => height: " << opt.getHeight() );
01514 }
01515 
01516 void GLPreviewFrame::OnShowAll(wxCommandEvent & e)
01517 {
01518     if (m_pano.getNrOfImages() == 0) return;
01519 
01520     HuginBase::UIntSet displayedImgs;
01521     if (m_selectAllMode == SELECT_ALL_IMAGES)
01522     {
01523         fill_set(displayedImgs, 0, m_pano.getNrOfImages() - 1);
01524     }
01525     else
01526     {
01527         if (m_selectKeepSelection)
01528         {
01529             displayedImgs = m_pano.getActiveImages();
01530         };
01531         std::vector<HuginBase::UIntVector> stackedImg = HuginBase::getSortedStacks(&m_pano);
01532         for (size_t i = 0; i < stackedImg.size(); ++i)
01533         {
01534             switch (m_selectAllMode)
01535             {
01536                 case SELECT_BRIGHTEST_IMAGES:
01537                     displayedImgs.insert(*(stackedImg[i].rbegin()));
01538                     break;
01539                 case SELECT_DARKEST_IMAGES:
01540                     displayedImgs.insert(*(stackedImg[i].begin()));
01541                     break;
01542                 case SELECT_MEDIAN_IMAGES:
01543                 default:
01544                     displayedImgs.insert(stackedImg[i][stackedImg[i].size() / 2]);
01545                     break;
01546             };
01547         };
01548     };
01549     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01550         new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
01551         );
01552 }
01553 
01554 void GLPreviewFrame::OnShowNone(wxCommandEvent & e)
01555 {
01556     if (m_pano.getNrOfImages() == 0) return;
01557 
01558     DEBUG_ASSERT(m_pano.getNrOfImages() == m_ToggleButtons.size());
01559     for (unsigned int i=0; i < m_pano.getNrOfImages(); i++) {
01560         m_ToggleButtons[i]->SetValue(false);
01561     }
01562     HuginBase::UIntSet displayedImgs;
01563     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01564         new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
01565         );
01566 }
01567 
01568 void GLPreviewFrame::OnNumTransform(wxCommandEvent & e)
01569 {
01570     if (m_pano.getNrOfImages() == 0) return;
01571 
01572     wxString text;
01573     double y;
01574     double p;
01575     double r;
01576     double x;
01577     double z;
01578 
01579     int index = m_DragModeChoice->GetSelection();
01580     switch (index) {
01581         case 0: //normal
01582         case 1: //normal, individual
01583             //@TODO limit numeric transform to selected images
01584             text = XRCCTRL(*this,"input_yaw",wxTextCtrl)->GetValue();
01585             if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
01586             {
01587                 wxBell();
01588                 wxMessageBox(_("Yaw value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01589                 return;
01590             }
01591             text = XRCCTRL(*this,"input_pitch",wxTextCtrl)->GetValue();
01592             if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), p))
01593             {
01594                 wxBell();
01595                 wxMessageBox(_("Pitch value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01596                 return;
01597             }
01598             text = XRCCTRL(*this,"input_roll",wxTextCtrl)->GetValue();
01599             if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), r))
01600             {
01601                 wxBell();
01602                 wxMessageBox(_("Roll value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01603                 return;
01604             }
01605             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01606                     new PanoCommand::RotatePanoCmd(m_pano, y, p, r)
01607                 );
01608             break;
01609         case 2: //mosaic
01610         case 3: //mosaic, individual
01611             //@TODO limit numeric transform to selected images
01612             text = XRCCTRL(*this,"input_x",wxTextCtrl)->GetValue();
01613             if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), x))
01614             {
01615                 wxBell();
01616                 wxMessageBox(_("X value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01617                 return;
01618             }
01619             text = XRCCTRL(*this,"input_y",wxTextCtrl)->GetValue();
01620             if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
01621             {
01622                 wxBell();
01623                 wxMessageBox(_("Y value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01624                 return;
01625             }
01626             text = XRCCTRL(*this,"input_z",wxTextCtrl)->GetValue();
01627             if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), z))
01628             {
01629                 wxBell();
01630                 wxMessageBox(_("Z value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
01631                 return;
01632             }
01633             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01634                     new PanoCommand::TranslatePanoCmd(m_pano, x, y, z)
01635                 );
01636             break;
01637     }
01638 }
01639 
01640 void GLPreviewFrame::OnExposureChanged(wxCommandEvent & e)
01641 {
01642     HuginBase::PanoramaOptions opts = m_pano.getOptions();
01643     // exposure
01644     wxString text = m_exposureTextCtrl->GetValue();
01645     DEBUG_INFO ("target exposure = " << text.mb_str(wxConvLocal) );
01646     double p = 0;
01647     if (text != wxT("")) {
01648         if (!hugin_utils::str2double(text, p)) {
01649             wxLogError(_("Value must be numeric."));
01650             return;
01651         }
01652     }
01653     opts.outputExposureValue = p;
01654     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01655             new PanoCommand::SetPanoOptionsCmd( m_pano, opts )
01656                                            );
01657 }
01658 
01659 void GLPreviewFrame::OnProjParameterChanged(wxCommandEvent & e)
01660 {
01661     HuginBase::PanoramaOptions opts = m_pano.getOptions();
01662     int nParam = opts.m_projFeatures.numberOfParameters;
01663     std::vector<double> para = opts.getProjectionParameters();
01664     for (int i = 0; i < nParam; i++) {
01665         if (e.GetEventObject() == m_projParamTextCtrl[i]) {
01666             wxString text = m_projParamTextCtrl[i]->GetValue();
01667             DEBUG_INFO ("param " << i << ":  = " << text.mb_str(wxConvLocal) );
01668             double p = 0;
01669             if (text != wxT("")) {
01670                 if (!hugin_utils::str2double(text, p)) {
01671                     wxLogError(_("Value must be numeric."));
01672                     return;
01673                 }
01674             }
01675             para[i] = p;
01676         }
01677     }
01678     opts.setProjectionParameters(para);
01679     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01680             new PanoCommand::SetPanoOptionsCmd( m_pano, opts )
01681                                            );
01682 }
01683 
01684 void GLPreviewFrame::OnProjParameterReset(wxCommandEvent &e)
01685 {
01686     HuginBase::PanoramaOptions opts = m_pano.getOptions();
01687     opts.resetProjectionParameters();
01688     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01689         new PanoCommand::SetPanoOptionsCmd(m_pano, opts)
01690         );
01691 };
01692 
01693 void GLPreviewFrame::OnChangeFOV(wxScrollEvent & e)
01694 {
01695     DEBUG_TRACE("");
01696 
01697     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01698 
01699     if (e.GetEventObject() == m_HFOVSlider) {
01700         DEBUG_DEBUG("HFOV changed (slider): " << e.GetInt() << " == " << m_HFOVSlider->GetValue());
01701         opt.setHFOV(e.GetInt());
01702     } else if (e.GetEventObject() == m_VFOVSlider) {
01703         DEBUG_DEBUG("VFOV changed (slider): " << e.GetInt());
01704         opt.setVFOV(e.GetInt());
01705     } else if (e.GetEventObject() == XRCCTRL(*this,"layout_scale_slider",wxSlider)) {
01706         DEBUG_DEBUG("Layout scale changed (slider): " << e.GetInt());
01707         GLPreviewFrame::OnLayoutScaleChange(e);
01708     } else {
01709         int nParam = opt.m_projFeatures.numberOfParameters;
01710         std::vector<double> para = opt.getProjectionParameters();
01711         for (int i = 0; i < nParam; i++) {
01712             if (e.GetEventObject() == m_projParamSlider[i]) {
01713                 // update
01714                 para[i] = e.GetInt();
01715             }
01716         }
01717         opt.setProjectionParameters(para);
01718                 opt.setHFOV(m_HFOVSlider->GetValue());
01719                 opt.setVFOV(m_VFOVSlider->GetValue());
01720     }
01721 
01722     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01723         new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01724         );    
01725 }
01726 
01727 void GLPreviewFrame::OnTrackChangeFOV(wxScrollEvent & e)
01728 {
01729     DEBUG_TRACE("");
01730     DEBUG_TRACE("fov change " << e.GetInt());
01731     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01732 
01733     if (e.GetEventObject() == m_HFOVSlider) {
01734         opt.setHFOV(e.GetInt());
01735     } else if (e.GetEventObject() == m_VFOVSlider) {
01736         opt.setVFOV(e.GetInt());
01737     } else {
01738         int nParam = opt.m_projFeatures.numberOfParameters;
01739         std::vector<double> para = opt.getProjectionParameters();
01740         for (int i = 0; i < nParam; i++) {
01741             if (e.GetEventObject() == m_projParamSlider[i]) {
01742                 // update
01743                 para[i] = e.GetInt();
01744             }
01745         }
01746         opt.setProjectionParameters(para);
01747     }
01748     // we only actually update the panorama fully when the mouse is released.
01749     // As we are dragging it we don't want to create undo events, but we would
01750     // like to update the display, so we change the GLViewer's ViewState and
01751     // request a redraw.
01752     m_GLPreview->m_view_state->SetOptions(&opt);
01753     m_GLPreview->Refresh();
01754 }
01755 
01756 void GLPreviewFrame::OnBlendChoice(wxCommandEvent & e)
01757 {
01758     if (e.GetEventObject() == m_BlendModeChoice)
01759     {
01760         updateBlendMode();
01761     }
01762     else
01763     {
01764         // FIXME DEBUG_WARN("wxChoice event from unknown object received");
01765     }
01766 }
01767 
01768 void GLPreviewFrame::OnDragChoice(wxCommandEvent & e)
01769 {
01770     if (drag_tool)
01771     {
01772         DragTool::DragMode newDragMode=DragTool::drag_mode_normal;
01773         int index = m_DragModeChoice->GetSelection();
01774         switch (index) {
01775             case 0: //normal
01776             case 1:
01777                 newDragMode=DragTool::drag_mode_normal;
01778                 break;
01779             case 2: //mosaic
01780             case 3:
01781                 newDragMode=DragTool::drag_mode_mosaic;
01782                 break;
01783         }
01784         if(newDragMode==DragTool::drag_mode_mosaic)
01785         {
01786             if(HasNonZeroTranslationPlaneParameters())
01787             {
01788                 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?"),
01789 #ifdef __WXMSW__
01790                     _("Hugin"),
01791 #else
01792                     wxEmptyString,
01793 #endif
01794                     wxYES_NO | wxICON_QUESTION, this) == wxYES)
01795                 {
01796                     ResetTranslationPlaneParameters();
01797                 }
01798                 else
01799                 {
01800                     m_DragModeChoice->SetSelection(index-2);
01801                     return;
01802                 };
01803             };
01804             //switch overview mode to plane
01805             UpdateOverviewMode(1);
01806             m_OverviewModeChoice->SetSelection(1);
01807         }
01808         else
01809         {
01810             //new mode is normal
01811             //set overview back to panosphere mode
01812             UpdateOverviewMode(0);
01813             m_OverviewModeChoice->SetSelection(0);
01814             m_GLOverview->m_visualization_state->ForceRequireRedraw();
01815             m_GLOverview->m_visualization_state->SetDirtyViewport();
01816         };
01817         //update drag mode
01818         drag_tool->setDragMode(newDragMode);
01819         EnableGroupCheckboxes(individualDragging());
01820         // adjust the layout
01821         DragChoiceLayout(index);
01822     };
01823 };
01824 
01825 bool GLPreviewFrame::HasNonZeroTranslationPlaneParameters()
01826 {
01827     size_t nr = m_pano.getNrOfImages();
01828     for (size_t i = 0 ; i < nr; i++)
01829     {
01830         if (m_pano.getSrcImage(i).getTranslationPlaneYaw() != 0 ||
01831             m_pano.getSrcImage(i).getTranslationPlanePitch() != 0)
01832         {
01833             return true;
01834         };
01835     }
01836     return false;
01837 };
01838 
01839 void GLPreviewFrame::ResetTranslationPlaneParameters()
01840 {
01841     HuginBase::UIntSet imgs;
01842     HuginBase::Panorama newPan = m_pano.duplicate();
01843     size_t nr = newPan.getNrOfImages();
01844     for (size_t i = 0 ; i < nr ; i++)
01845     {
01846         HuginBase::SrcPanoImage img = newPan.getSrcImage(i);
01847         img.setTranslationPlaneYaw(0);
01848         img.setTranslationPlanePitch(0);
01849         newPan.setSrcImage(i,img);
01850         imgs.insert(i);
01851     }
01852     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01853         new PanoCommand::UpdateImagesVariablesCmd(m_pano, imgs, newPan.getVariables())
01854     );
01855 };
01856 
01857 bool GLPreviewFrame::UpdateOverviewMode(int newMode)
01858 {
01859     GLOverview::OverviewMode newOverviewMode=GLOverview::PANOSPHERE;
01860     if(newMode==1)
01861     {
01862         newOverviewMode=GLOverview::PLANE;
01863     };
01864     if(m_GLOverview->GetMode()==newOverviewMode)
01865     {
01866         return true;
01867     };
01868     if (m_GLOverview->GetMode() == GLOverview::PANOSPHERE)
01869     {
01870         if (!HasNonZeroTranslationPlaneParameters())
01871         {
01872             m_GLOverview->SetMode(GLOverview::PLANE);
01873             return true;
01874         }
01875         else
01876         {
01877             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?"),
01878 #ifdef __WXMSW__
01879                 _("Hugin"),
01880 #else
01881                 wxEmptyString,
01882 #endif
01883                 wxYES_NO | wxICON_QUESTION, this) == wxYES)
01884             {
01885                 ResetTranslationPlaneParameters();
01886                 m_GLOverview->SetMode(GLOverview::PLANE);
01887                 return true;
01888             }
01889             else
01890             {
01891                 return false;
01892             };
01893         };
01894     }
01895     else
01896     {
01897         m_GLOverview->SetMode(GLOverview::PANOSPHERE);
01898         return true;
01899     }
01900 };
01901 
01902 void GLPreviewFrame::OnOverviewModeChoice( wxCommandEvent & e)
01903 {
01904     if(UpdateOverviewMode(m_OverviewModeChoice->GetSelection()))
01905     {
01906         m_GLOverview->m_visualization_state->ForceRequireRedraw();
01907         m_GLOverview->m_visualization_state->SetDirtyViewport();
01908         //set drag mode to normal if new mode is panosphere mode
01909         if(m_GLOverview->GetMode()==GLOverview::PANOSPHERE && m_DragModeChoice->GetSelection()>1)
01910         {
01911             m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
01912             OnDragChoice(e);
01913         };
01914     }
01915     else
01916     {
01917         //change mode was not successful or canceled by user, set mode choice back
01918         if(m_GLOverview->GetMode()==GLOverview::PANOSPHERE)
01919         {
01920             m_OverviewModeChoice->SetSelection(0);
01921         }
01922         else
01923         {
01924             m_OverviewModeChoice->SetSelection(1);
01925         };
01926     };
01927 };
01928 
01929 void GLPreviewFrame::DragChoiceLayout( int index )
01930 {
01931     // visibility of controls based on selected drag mode
01932     bool normalMode=index==0 || index==1;
01933     XRCCTRL(*this,"label_yaw",wxStaticText)->Show(normalMode);
01934     XRCCTRL(*this,"input_yaw",wxTextCtrl)->Show(normalMode);
01935     XRCCTRL(*this,"label_pitch",wxStaticText)->Show(normalMode);
01936     XRCCTRL(*this,"input_pitch",wxTextCtrl)->Show(normalMode);
01937     XRCCTRL(*this,"label_roll",wxStaticText)->Show(normalMode);
01938     XRCCTRL(*this,"input_roll",wxTextCtrl)->Show(normalMode);
01939     XRCCTRL(*this,"label_x",wxStaticText)->Show(!normalMode);
01940     XRCCTRL(*this,"input_x",wxTextCtrl)->Show(!normalMode);
01941     XRCCTRL(*this,"label_y",wxStaticText)->Show(!normalMode);
01942     XRCCTRL(*this,"input_y",wxTextCtrl)->Show(!normalMode);
01943     XRCCTRL(*this,"label_z",wxStaticText)->Show(!normalMode);
01944     XRCCTRL(*this,"input_z",wxTextCtrl)->Show(!normalMode);
01945     // redraw layout to compress empty space
01946     XRCCTRL(*this,"apply_num_transform",wxButton)->GetParent()->Layout();
01947 }
01948 
01949 void GLPreviewFrame::OnDefaultExposure( wxCommandEvent & e )
01950 {
01951     if (m_pano.getNrOfImages() > 0) {
01952         HuginBase::PanoramaOptions opt = m_pano.getOptions();
01953         opt.outputExposureValue = HuginBase::CalculateMeanExposure::calcMeanExposure(m_pano);
01954         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01955                 new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01956                                                );
01957     }
01958 }
01959 
01960 void GLPreviewFrame::OnIncreaseExposure( wxSpinEvent & e )
01961 {
01962     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01963     opt.outputExposureValue = opt.outputExposureValue + 1.0/3;
01964     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01965             new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01966                                             );
01967 }
01968 
01969 void GLPreviewFrame::OnDecreaseExposure( wxSpinEvent & e )
01970 {
01971     HuginBase::PanoramaOptions opt = m_pano.getOptions();
01972     opt.outputExposureValue = opt.outputExposureValue - 1.0/3;
01973     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01974             new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01975                                            );
01976 }
01977 
01978 void GLPreviewFrame::OnProjectionChoice( wxCommandEvent & e )
01979 {
01980     if (e.GetEventObject() == m_ProjectionChoice) {
01981         HuginBase::PanoramaOptions opt = m_pano.getOptions();
01982         int lt = m_ProjectionChoice->GetSelection();
01983         wxString Ip;
01984         opt.setProjection((HuginBase::PanoramaOptions::ProjectionFormat) lt);
01985         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01986                 new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
01987                                             );
01988         DEBUG_DEBUG ("Projection changed: "  << lt);
01989         m_projection_panel->Layout();
01990         Refresh();
01991     } else {
01992         // FIXME DEBUG_WARN("wxChoice event from unknown object received");
01993     }
01994 }
01995 
01996 /* We don't have an OpenGL hdr display yet
01997 void GLPreviewFrame::OnOutputChoice( wxCommandEvent & e)
01998 {
01999     if (e.GetEventObject() == m_outputModeChoice) {
02000         PanoramaOptions opt = m_pano.getOptions();
02001         int lt = m_outputModeChoice->GetSelection();
02002         wxString Ip;
02003         opt.outputMode = ( (PanoramaOptions::OutputMode) lt );
02004         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02005                 new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
02006                                                );
02007 
02008     } else {
02009         // FIXME DEBUG_WARN("wxChoice event from unknown object received");
02010     }
02011 }
02012 */
02013 
02014 void GLPreviewFrame::SetStatusMessage(wxString message)
02015 {
02016     SetStatusText(message, 0);
02017 }
02018 
02019 void GLPreviewFrame::OnPhotometric(wxCommandEvent & e)
02020 {
02021     m_GLPreview->SetPhotometricCorrect(e.IsChecked());
02022 }
02023 
02024 void GLPreviewFrame::MakePreviewTools(PreviewToolHelper *preview_helper_in)
02025 {
02026     // create the tool objects.
02027     // we delay this until we have an OpenGL context so that they are free to
02028     // create texture objects and display lists before they are used.
02029     preview_helper = preview_helper_in;
02030     crop_tool = new PreviewCropTool(preview_helper);
02031     drag_tool = new PreviewDragTool(preview_helper);
02032     color_picker_tool = new PreviewColorPickerTool(preview_helper);
02033     edit_cp_tool = new PreviewEditCPTool(preview_helper);
02034     identify_tool = new PreviewIdentifyTool(preview_helper, this, true);
02035     preview_helper->ActivateTool(identify_tool);
02036     difference_tool = new PreviewDifferenceTool(preview_helper);
02037     pano_mask_tool = new PreviewPanoMaskTool(preview_helper);
02038     preview_control_point_tool = new PreviewControlPointTool(preview_helper);
02039     m_preview_layoutLinesTool = new PreviewLayoutLinesTool(preview_helper);
02040 
02041     preview_projection_grid = new PreviewProjectionGridTool(preview_helper);
02042     if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
02043     {
02044         preview_helper->ActivateTool(preview_projection_grid);
02045     };
02046     preview_guide_tool = new PreviewGuideTool(preview_helper);
02047     preview_guide_tool->SetGuideStyle((PreviewGuideTool::Guides)m_GuideChoiceProj->GetSelection());
02048 
02049     // activate tools that are always active.
02050     preview_helper->ActivateTool(pano_mask_tool);
02051     // update the blend mode which activates some tools
02052     updateBlendMode();
02053     m_GLPreview->SetPhotometricCorrect(true);
02054     // update toolbar
02055     SetMode(mode_assistant);
02056 }
02057 
02058 void GLPreviewFrame::MakePanosphereOverviewTools(PanosphereOverviewToolHelper *panosphere_overview_helper_in)
02059 {
02060     panosphere_overview_helper = panosphere_overview_helper_in;
02061     overview_drag_tool = new OverviewDragTool(panosphere_overview_helper);
02062     panosphere_overview_camera_tool = new PanosphereOverviewCameraTool(panosphere_overview_helper);
02063     panosphere_overview_helper->ActivateTool(panosphere_overview_camera_tool);
02064     panosphere_overview_identify_tool = new PreviewIdentifyTool(panosphere_overview_helper, this, false);
02065     panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool);
02066 
02067     panosphere_sphere_tool = new PanosphereSphereTool(panosphere_overview_helper, GetPreviewBackgroundColor());
02068     panosphere_overview_helper->ActivateTool(panosphere_sphere_tool);
02069     
02070     overview_projection_grid = new PanosphereOverviewProjectionGridTool(panosphere_overview_helper);
02071     if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
02072     {
02073         panosphere_overview_helper->ActivateTool(overview_projection_grid);
02074     }
02075     
02076     
02077     overview_outlines_tool = new PanosphereOverviewOutlinesTool(panosphere_overview_helper, m_GLPreview);
02078     panosphere_overview_helper->ActivateTool(overview_outlines_tool);
02079     panosphere_difference_tool = new PreviewDifferenceTool(panosphere_overview_helper);
02080 
02081     m_panosphere_layoutLinesTool = new PreviewLayoutLinesTool(panosphere_overview_helper);
02082     panosphere_control_point_tool = new PreviewControlPointTool(panosphere_overview_helper);
02083 
02084 
02085 
02086 }
02087 
02088 void GLPreviewFrame::MakePlaneOverviewTools(PlaneOverviewToolHelper *plane_overview_helper_in)
02089 {
02090     plane_overview_helper = plane_overview_helper_in;
02091     plane_overview_identify_tool = new PreviewIdentifyTool(plane_overview_helper, this, false);
02092     plane_overview_helper->ActivateTool(plane_overview_identify_tool);
02093     
02094     plane_overview_camera_tool = new PlaneOverviewCameraTool(plane_overview_helper);
02095     plane_overview_helper->ActivateTool(plane_overview_camera_tool);
02096     plane_difference_tool = new PreviewDifferenceTool(plane_overview_helper);
02097 
02098     plane_overview_outlines_tool = new PlaneOverviewOutlinesTool(plane_overview_helper, m_GLPreview);
02099     plane_overview_helper->ActivateTool(plane_overview_outlines_tool);
02100 
02101     m_plane_layoutLinesTool = new PreviewLayoutLinesTool(plane_overview_helper);
02102     plane_control_point_tool = new PreviewControlPointTool(plane_overview_helper);
02103 
02104 }
02105 
02106 void GLPreviewFrame::OnIdentify(wxCommandEvent & e)
02107 {
02108     SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
02109     if (e.IsChecked())
02110     {
02111         m_BlendModeChoice->SetSelection(0);
02112         preview_helper->DeactivateTool(difference_tool);
02113         panosphere_overview_helper->DeactivateTool(panosphere_difference_tool);
02114         plane_overview_helper->DeactivateTool(plane_difference_tool);
02115         identify_tool->setConstantOn(true);
02116         panosphere_overview_identify_tool->setConstantOn(true);
02117         plane_overview_identify_tool->setConstantOn(true);
02118 //        TurnOffTools(preview_helper->ActivateTool(identify_tool));
02119 //        TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool));
02120 //        TurnOffTools(plane_overview_helper->ActivateTool(plane_overview_identify_tool));
02121     } else {
02122         identify_tool->setConstantOn(false);
02123         panosphere_overview_identify_tool->setConstantOn(false);
02124         plane_overview_identify_tool->setConstantOn(false);
02125 //        preview_helper->DeactivateTool(identify_tool);
02126 //        panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
02127 //        plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
02128         CleanButtonColours();
02129     }
02130     m_GLPreview->Refresh();
02131     m_GLOverview->Refresh();
02132 }
02133 
02134 void GLPreviewFrame::OnControlPoint(wxCommandEvent & e)
02135 {
02136     if (!m_ToolBar_editCP->GetToolState(XRCID("preview_edit_cp_tool")))
02137     {
02138         //process event only if edit cp tool is disabled
02139         SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
02140         if (e.IsChecked())
02141         {
02142             TurnOffTools(preview_helper->ActivateTool(preview_control_point_tool));
02143             TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_control_point_tool));
02144             TurnOffTools(plane_overview_helper->ActivateTool(plane_control_point_tool));
02145         }
02146         else {
02147             preview_helper->DeactivateTool(preview_control_point_tool);
02148             panosphere_overview_helper->DeactivateTool(panosphere_control_point_tool);
02149             plane_overview_helper->DeactivateTool(plane_control_point_tool);
02150         }
02151         m_GLPreview->Refresh();
02152         m_GLOverview->Refresh();
02153     };
02154 }
02155 
02156 void GLPreviewFrame::TurnOffTools(std::set<Tool*> tools)
02157 {
02158     std::set<Tool*>::iterator i;
02159     for (i = tools.begin(); i != tools.end(); ++i)
02160     {
02161         if (*i == crop_tool)
02162         {
02163             // cover up the guidelines
02164             m_GLPreview->Refresh();
02165         } else if (*i == drag_tool)
02166         {
02167             // cover up its boxes
02168             m_GLPreview->Refresh();
02169         } else if (*i == identify_tool)
02170         {
02171             // disabled the identify tool, toggle its button off.
02172             m_ToolBar_Identify->ToggleTool(XRCID("preview_identify_tool"), false);
02173             // cover up its indicators and restore normal button colours.
02174             m_GLPreview->Refresh();
02175             m_GLOverview->Refresh();
02176             CleanButtonColours();
02177         } else if (*i == preview_control_point_tool)
02178         {
02179             // disabled the control point tool.
02180             XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
02181             // cover up the control point lines.
02182             m_GLPreview->Refresh();
02183             m_GLOverview->Refresh();
02184         }
02185     }
02186 }
02187 
02188 void GLPreviewFrame::SetImageButtonColour(unsigned int image_nr,
02189                                           unsigned char red,
02190                                           unsigned char green,
02191                                           unsigned char blue)
02192 {
02193     // 0, 0, 0 indicates we want to go back to the system colour.
02194     // TODO: Maybe we should test this better on different themes.
02195     // On OS X, the background colour is ignored on toggle buttons, but not
02196     // checkboxes.
02197     if (red || green || blue)
02198     {
02199         // the identify tool wants us to highlight an image button in the given
02200         // colour, to match up with the display in the preview.
02201 #if defined __WXMSW__
02202         // on windows change the color of the surhugin_utils::rounding wxPanel
02203         m_ToggleButtonPanel[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
02204 #else
02205         // change the color of the wxToggleButton 
02206         m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_COLOUR);
02207         m_ToggleButtons[image_nr]->SetBackgroundColour(
02208                                                     wxColour(red, green, blue));
02209         // black should be visible on the button's vibrant colours.
02210         m_ToggleButtons[image_nr]->SetForegroundColour(wxColour(0, 0, 0));
02211 #endif
02212     } else {
02213         // return to the normal colour
02214 #if defined __WXMSW__
02215         m_ToggleButtonPanel[image_nr]->SetBackgroundColour(this->GetBackgroundColour());
02216 #else
02217         m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
02218         m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour);
02219         m_ToggleButtons[image_nr]->SetForegroundColour(wxNullColour);
02220 #endif
02221     }
02222 #if defined __WXMSW__
02223     m_ToggleButtonPanel[image_nr]->Refresh();
02224 #else
02225     m_ToggleButtons[image_nr]->Refresh();
02226 #endif
02227 }
02228 
02229 void GLPreviewFrame::CleanButtonColours()
02230 {
02231     // when we turn off the identification tool, any buttons that were coloured
02232     // to match the image in the preview should be given back the system themed
02233     // colours.
02234     unsigned int nr_images = m_pano.getNrOfImages();
02235     for (unsigned image = 0; image < nr_images; image++)
02236     {
02237 #if defined __WXMSW__
02238         m_ToggleButtonPanel[image]->SetBackgroundColour(this->GetBackgroundColour());
02239         m_ToggleButtonPanel[image]->Refresh();
02240 #else
02241         m_ToggleButtons[image]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
02242         m_ToggleButtons[image]->SetBackgroundColour(wxNullColour);
02243         m_ToggleButtons[image]->SetForegroundColour(wxNullColour);
02244         m_ToggleButtons[image]->Refresh();
02245 #endif
02246     }
02247 }
02248 
02249 void GLPreviewFrame::OnColorPicker(wxCommandEvent &e)
02250 {
02251     // blank status text as it refers to an old tool.
02252     SetStatusText(wxT(""), 0); 
02253     if (e.IsChecked())
02254     {
02255         // deactivate delete cp tool if active
02256         preview_helper->DeactivateTool(edit_cp_tool);
02257         m_ToolBar_editCP->ToggleTool(XRCID("preview_edit_cp_tool"), false);
02258         preview_helper->ActivateTool(color_picker_tool);
02259     }
02260     else
02261     {
02262         preview_helper->DeactivateTool(color_picker_tool);
02263     };
02264     m_GLPreview->Refresh();
02265 };
02266 
02267 void GLPreviewFrame::UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
02268 {
02269     PanoCommand::GlobalCmdHist::getInstance().addCommand(
02270         new PanoCommand::UpdateWhiteBalance(m_pano, redFactor, blueFactor)
02271         );
02272     //now toggle button and deactivate tool
02273     m_ToolBar_ColorPicker->ToggleTool(XRCID("preview_color_picker_tool"),false);
02274     //direct deactivation of tool does not work because this function is called by the tool itself
02275     //so we are send an event to deactivate the tool
02276     wxCommandEvent e(wxEVT_COMMAND_TOOL_CLICKED, XRCID("preview_color_picker_tool"));
02277     e.SetInt(0);
02278     GetEventHandler()->AddPendingEvent(e);
02279 };
02280 
02281 void GLPreviewFrame::OnEditCPTool(wxCommandEvent &e)
02282 {
02283     // blank status text as it refers to an old tool.
02284     SetStatusText(wxT(""), 0);
02285     if (e.IsChecked())
02286     {
02287         // deactivate color picker tool
02288         preview_helper->DeactivateTool(color_picker_tool);
02289         m_ToolBar_ColorPicker->ToggleTool(XRCID("preview_color_picker_tool"), false);
02290         // show automatically all cp
02291         preview_helper->ActivateTool(preview_control_point_tool);
02292         preview_helper->ActivateTool(edit_cp_tool);
02293     }
02294     else
02295     {
02296         if (!XRCCTRL(*this, "preview_control_point_tool", wxCheckBox)->GetValue())
02297         {
02298             preview_helper->DeactivateTool(preview_control_point_tool);
02299         };
02300         preview_helper->DeactivateTool(edit_cp_tool);
02301     };
02302     m_GLPreview->Refresh();
02303 };
02304 
02305 ImageToogleButtonEventHandler::ImageToogleButtonEventHandler(
02306                                   unsigned int image_number_in,
02307                                   wxToolBarToolBase* identify_toolbutton_in,
02308                                   HuginBase::Panorama * m_pano_in)
02309 {
02310     image_number = image_number_in;
02311     identify_toolbutton = identify_toolbutton_in;
02312     m_pano = m_pano_in;
02313 }
02314 
02315 void ImageToogleButtonEventHandler::OnEnter(wxMouseEvent & e)
02316 {
02317     // When using the identify tool, we want to identify image locations when
02318     // the user moves the mouse over the image buttons, but only if the image
02319     // is being shown.
02320     if ( 
02321         identify_toolbutton->IsToggled() && 
02322         m_pano->getActiveImages().count(image_number))
02323     {
02324         std::vector<PreviewIdentifyTool**>::iterator it;
02325         for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
02326             (*(*it))->ShowImageNumber(image_number);
02327         }
02328     }
02329     e.Skip();
02330 }
02331 
02332 void ImageToogleButtonEventHandler::OnLeave(wxMouseEvent & e)
02333 {
02334     // if the mouse left one of the image toggle buttons with the identification
02335     // tool active, we should stop showing the image indicator for that button.
02336     if ( 
02337         identify_toolbutton->IsToggled() && 
02338         m_pano->getActiveImages().count(image_number))
02339     {
02340         std::vector<PreviewIdentifyTool**>::iterator it;
02341         for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
02342             (*(*it))->StopShowingImages();
02343         }
02344     }
02345     e.Skip();
02346 }
02347 
02348 void ImageToogleButtonEventHandler::OnChange(wxCommandEvent & e)
02349 {
02350     // the user is turning on or off an image using its button. We want to turn
02351     // the indicators on and off if appropriate correctly to. We use OnEnter
02352     // and OnLeave for the indicators, but these only work when the image is
02353     // showing, so we are carefull of the order:
02354     HuginBase::UIntSet activeImages = m_pano->getActiveImages();
02355     wxMouseEvent null_event;
02356     if (e.IsChecked()) {
02357         activeImages.insert(image_number);
02358         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02359             new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
02360         );
02361         OnEnter(null_event);
02362     } else {
02363         OnLeave(null_event);
02364         activeImages.erase(image_number);
02365         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02366             new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
02367         );
02368     }
02369 }
02370 
02371 void ImageToogleButtonEventHandler::AddIdentifyTool(PreviewIdentifyTool** identify_tool_in) {
02372     identify_tools.push_back(identify_tool_in);
02373 }
02374 
02375 ImageGroupButtonEventHandler::ImageGroupButtonEventHandler(unsigned int image_number, GLPreviewFrame* frame_in, HuginBase::Panorama* m_pano)
02376     : image_number(image_number), frame(frame_in), m_pano(m_pano) {}
02377 
02378 void ImageGroupButtonEventHandler::AddIdentifyTool(PreviewIdentifyTool** identify_tool_in) {
02379     identify_tools.push_back(identify_tool_in);
02380 }
02381 
02382 
02383 void ImageGroupButtonEventHandler::OnEnter(wxMouseEvent & e)
02384 {
02385     //mark the image
02386     if (m_pano->getActiveImages().count(image_number))
02387     {
02388         std::vector<PreviewIdentifyTool**>::iterator it;
02389         for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
02390             (*(*it))->ShowImageNumber(image_number);
02391         }
02392     }
02393     e.Skip();
02394 }
02395 
02396 void ImageGroupButtonEventHandler::OnLeave(wxMouseEvent & e)
02397 {
02398     //unmark the image
02399     if (m_pano->getActiveImages().count(image_number))
02400     {
02401         std::vector<PreviewIdentifyTool**>::iterator it;
02402         for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
02403             (*(*it))->StopShowingImages();
02404         }
02405     }
02406     e.Skip();
02407 }
02408 
02409 void ImageGroupButtonEventHandler::OnChange(wxCommandEvent & e)
02410 {
02411     wxMouseEvent null_event;
02412     if (e.IsChecked()) {
02413         frame->AddImageToDragGroup(image_number,false);
02414         OnEnter(null_event);
02415     } else {
02416         OnLeave(null_event);
02417         frame->RemoveImageFromDragGroup(image_number,false);
02418     }
02419 }
02420 
02421 void ImageGroupButtonEventHandler::AddDragTool(DragTool** drag_tool_in) {
02422     drag_tools.push_back(drag_tool_in);
02423 }
02424 
02425 bool GLPreviewFrame::individualDragging()
02426 {
02427     return m_DragModeChoice->GetSelection()==1 || 
02428            m_DragModeChoice->GetSelection()==3;
02429 }
02430 
02431 void GLPreviewFrame::ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box) {
02432     if (imageDragGroup.count(image_nr) == 0) {
02433         this->AddImageToDragGroup(image_nr, update_check_box);
02434     } else {
02435         this->RemoveImageFromDragGroup(image_nr, update_check_box);
02436     }
02437 }
02438 void GLPreviewFrame::RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box) {
02439     imageDragGroup.erase(image_nr);
02440     if (update_check_box) {
02441         m_GroupToggleButtons[image_nr]->SetValue(false);
02442     }
02443 }
02444 void GLPreviewFrame::AddImageToDragGroup(unsigned int image_nr, bool update_check_box) {
02445     imageDragGroup.insert(image_nr);
02446     if (update_check_box) {
02447         m_GroupToggleButtons[image_nr]->SetValue(true);
02448     }
02449 }
02450 void GLPreviewFrame::SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box) {
02451     imageDragGroup.swap(imageDragGroup_in);
02452     std::vector<wxCheckBox*>::iterator it;
02453     unsigned int nr = 0;
02454     for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
02455         (*it)->SetValue(imageDragGroup.count(nr++)>0);
02456     }
02457 }
02458 HuginBase::UIntSet GLPreviewFrame::GetDragGroupImages() {
02459     return imageDragGroup;
02460 }
02461 void GLPreviewFrame::ClearDragGroupImages(bool update_check_box) {
02462     imageDragGroup.clear();
02463     std::vector<wxCheckBox*>::iterator it;
02464     for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
02465         (*it)->SetValue(false);
02466     }
02467 }
02468 
02469 void GLPreviewFrame::EnableGroupCheckboxes(bool isShown)
02470 {
02471     std::vector<wxCheckBox*>::iterator it;
02472     for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it)
02473     {
02474         (*it)->Show(isShown);
02475     }
02476     Layout();
02477 };
02478 
02480 void GLPreviewFrame::FillBlendChoice()
02481 {
02482     if(PreviewDifferenceTool::CheckOpenGLCanDifference())
02483         m_differenceIndex=m_BlendModeChoice->Append(_("difference"));
02484     // update size
02485     m_BlendModeChoice->InvalidateBestSize();
02486     m_BlendModeChoice->GetParent()->Layout();
02487     Refresh();
02488     // get blend mode last state
02489     unsigned int oldMode = wxConfigBase::Get()->Read(wxT("/GLPreviewFrame/blendMode"), 0l);
02490     // limit old state to max available states
02491     if (oldMode >= m_BlendModeChoice->GetCount())
02492     {
02493         oldMode = 0;
02494     }
02495     m_BlendModeChoice->SetSelection(oldMode);
02496     updateBlendMode();
02497 };
02498 
02499 void GLPreviewFrame::OnAutocrop(wxCommandEvent &e)
02500 {
02501     DEBUG_INFO("Dirty ROI Calc\n");
02502     if (m_pano.getActiveImages().size() == 0)
02503     {
02504         return;
02505     };
02506 
02507     vigra::Rect2D newROI;
02508     {
02509         ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
02510         HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
02511         cropPano.run();
02512         if (cropPano.hasRunSuccessfully())
02513         {
02514             newROI = cropPano.getResultOptimalROI();
02515         };
02516     };
02517 
02518     //set the ROI - fail if the right/bottom is zero, meaning all zero
02519     if(!newROI.isEmpty())
02520     {
02521         HuginBase::PanoramaOptions opt = m_pano.getOptions();
02522         opt.setROI(newROI);
02523         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02524             new PanoCommand::SetPanoOptionsCmd(m_pano, opt )
02525             );
02526     }
02527 }
02528 
02529 void GLPreviewFrame::OnStackAutocrop(wxCommandEvent &e)
02530 {
02531     DEBUG_INFO("Dirty ROI Calc\n");
02532     if (m_pano.getActiveImages().size() == 0)
02533     {
02534         return;
02535     };
02536 
02537     vigra::Rect2D newROI;
02538     {
02539         ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
02540         HuginBase::UIntSet activeImages = m_pano.getActiveImages();
02541         std::vector<HuginBase::UIntSet> stackImgs = getHDRStacks(m_pano, activeImages, m_pano.getOptions());
02542         HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
02543         //only use hdr autocrop for projects with stacks
02544         //otherwise fall back to "normal" autocrop
02545         if (stackImgs.size()<activeImages.size())
02546         {
02547             cropPano.setStacks(stackImgs);
02548         }
02549         cropPano.run();
02550         if (cropPano.hasRunSuccessfully())
02551         {
02552             newROI = cropPano.getResultOptimalROI();
02553         };
02554     };
02555 
02556     //set the ROI - fail if the right/bottom is zero, meaning all zero
02557     if(!newROI.isEmpty())
02558     {
02559         HuginBase::PanoramaOptions opt = m_pano.getOptions();
02560         opt.setROI(newROI);
02561         PanoCommand::GlobalCmdHist::getInstance().addCommand(
02562             new PanoCommand::SetPanoOptionsCmd(m_pano, opt )
02563             );
02564     }
02565 }
02566 
02567 void GLPreviewFrame::OnFullScreen(wxCommandEvent & e)
02568 {
02569     ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
02570 };
02571 
02572 void GLPreviewFrame::SetMode(int newMode)
02573 {
02574     if(m_mode==newMode)
02575         return;
02576     SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
02577     switch(m_mode)
02578     {
02579         case mode_assistant:
02580         case mode_preview:
02581             // switch off identify and show cp tool
02582             identify_tool->setConstantOn(false);
02583             panosphere_overview_identify_tool->setConstantOn(false);
02584             plane_overview_identify_tool->setConstantOn(false);
02585             preview_helper->DeactivateTool(color_picker_tool);
02586             m_ToolBar_ColorPicker->ToggleTool(XRCID("preview_color_picker_tool"),false);
02587 //            preview_helper->DeactivateTool(identify_tool);
02588 //            panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
02589 //            plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
02590             preview_helper->DeactivateTool(edit_cp_tool);
02591             m_ToolBar_editCP->ToggleTool(XRCID("preview_edit_cp_tool"), false);
02592 
02593             CleanButtonColours();
02594             m_ToolBar_Identify->ToggleTool(XRCID("preview_identify_tool"),false);
02595             preview_helper->DeactivateTool(preview_control_point_tool);
02596             panosphere_overview_helper->DeactivateTool(panosphere_control_point_tool);
02597             plane_overview_helper->DeactivateTool(plane_control_point_tool);
02598             XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
02599             break;
02600         case mode_layout:
02601             // disable layout mode.
02602             preview_helper->DeactivateTool(m_preview_layoutLinesTool);
02603             panosphere_overview_helper->DeactivateTool(m_panosphere_layoutLinesTool);
02604             plane_overview_helper->DeactivateTool(m_plane_layoutLinesTool);
02605             // reactivate identify tool when leaving layout mode
02606             preview_helper->ActivateTool(identify_tool);
02607             panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool);
02608             plane_overview_helper->ActivateTool(plane_overview_identify_tool);
02609             m_GLPreview->SetLayoutMode(false);
02610             m_GLOverview->SetLayoutMode(false);
02611             // Switch the panorama mask back on.
02612             preview_helper->ActivateTool(pano_mask_tool);
02613             //restore blend mode
02614             m_BlendModeChoice->SetSelection(non_layout_blend_mode);
02615             updateBlendMode();
02616             break;
02617         case mode_projection:
02618             preview_helper->DeactivateTool(preview_guide_tool);
02619             break;
02620         case mode_drag:
02621             preview_helper->DeactivateTool(preview_guide_tool);
02622             preview_helper->DeactivateTool(drag_tool);
02623             panosphere_overview_helper->DeactivateTool(overview_drag_tool);
02624             if (individualDragging()) {
02625                 std::vector<wxCheckBox*>::iterator it;
02626                 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
02627                     (*it)->Show(false);
02628                 }
02629             }
02630             break;
02631         case mode_crop:
02632             preview_helper->DeactivateTool(preview_guide_tool);
02633             preview_helper->DeactivateTool(crop_tool);
02634             break;
02635     };
02636     m_mode=newMode;
02637     wxScrollEvent dummy;
02638     switch(m_mode)
02639     {
02640         case mode_assistant:
02641         case mode_preview:
02642             break;
02643         case mode_layout:
02644             //save blend mode setting, set to normal for layout mode
02645             non_layout_blend_mode=m_BlendModeChoice->GetSelection();
02646             m_BlendModeChoice->SetSelection(0);
02647             updateBlendMode();
02648             // turn off things not used in layout mode.
02649             preview_helper->DeactivateTool(pano_mask_tool);
02650             // deactivate identify tool in layout mode
02651             preview_helper->DeactivateTool(identify_tool);
02652             panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
02653             plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
02654             m_GLPreview->SetLayoutMode(true);
02655             m_GLOverview->SetLayoutMode(true);
02656             preview_helper->ActivateTool(m_preview_layoutLinesTool);
02657             panosphere_overview_helper->ActivateTool(m_panosphere_layoutLinesTool);
02658             plane_overview_helper->ActivateTool(m_plane_layoutLinesTool);
02659             // we need to update the meshes after switch to layout mode
02660             // otherwise the following update of scale has no meshes to scale
02661             m_GLPreview->Update();
02662             m_GLOverview->Update();
02663             OnLayoutScaleChange(dummy);
02664             break;
02665         case mode_projection:
02666             preview_helper->ActivateTool(preview_guide_tool);
02667             break;
02668         case mode_drag:
02669             preview_helper->ActivateTool(preview_guide_tool);
02670             TurnOffTools(preview_helper->ActivateTool(drag_tool));
02671             TurnOffTools(panosphere_overview_helper->ActivateTool(overview_drag_tool));
02672             if (individualDragging()) {
02673                 std::vector<wxCheckBox*>::iterator it;
02674                 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
02675                     (*it)->Show(true);
02676                 }
02677             }
02678             break;
02679         case mode_crop:
02680             TurnOffTools(preview_helper->ActivateTool(crop_tool));
02681             preview_helper->ActivateTool(preview_guide_tool);
02682             break;
02683     };
02684     //enable group checkboxes only for drag mode tab
02685     EnableGroupCheckboxes(m_mode==mode_drag && individualDragging());
02686     m_GLPreview->Refresh();
02687 };
02688 
02689 void GLPreviewFrame::OnSelectMode(wxNotebookEvent &e)
02690 {
02691     if(m_mode!=-1)
02692         SetMode(e.GetSelection());
02693 };
02694 
02695 void GLPreviewFrame::OnToolModeChanging(wxNotebookEvent &e)
02696 {
02697     if(m_pano.getNrOfImages()==0 && e.GetOldSelection()==0)
02698     {
02699         wxBell();
02700         e.Veto();
02701     };
02702 };
02703 
02704 void GLPreviewFrame::OnROIChanged ( wxCommandEvent & e )
02705 {
02706     HuginBase::PanoramaOptions opt = m_pano.getOptions();
02707     long left, right, top, bottom;
02708     if (!m_ROITopTxt->GetValue().ToLong(&top)) {
02709         wxLogError(_("Top needs to be an integer bigger than 0"));
02710         return;
02711     }
02712     if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
02713         wxLogError(_("left needs to be an integer bigger than 0"));
02714         return;
02715     }
02716     if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
02717         wxLogError(_("right needs to be an integer bigger than 0"));
02718         return;
02719     }
02720     if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
02721         wxLogError(_("bottom needs to be an integer bigger than 0"));
02722         return;
02723     }
02724     opt.setROI(vigra::Rect2D(left, top, right, bottom));
02725     // make sure that left is really to the left of right
02726     if(opt.getROI().width()<1) {
02727         wxLogError(_("left boundary must be smaller than right"));
02728         UpdateRoiDisplay(m_pano.getOptions());
02729         return;
02730     }
02731     // make sure that top is really higher than bottom
02732     if(opt.getROI().height()<1) {
02733         wxLogError(_("top boundary must be smaller than bottom"));
02734         UpdateRoiDisplay(m_pano.getOptions());
02735         return;
02736     }
02737 
02738     PanoCommand::GlobalCmdHist::getInstance().addCommand(
02739             new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
02740                                            );
02741 };
02742 
02743 void GLPreviewFrame::OnResetCrop(wxCommandEvent &e)
02744 {
02745     HuginBase::PanoramaOptions opt = m_pano.getOptions();
02746     opt.setROI(vigra::Rect2D(0,0,opt.getWidth(),opt.getHeight()));
02747     PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::SetPanoOptionsCmd(m_pano, opt));
02748 };
02749 
02750 void GLPreviewFrame::OnHFOVChanged ( wxCommandEvent & e )
02751 {
02752     HuginBase::PanoramaOptions opt = m_pano.getOptions();
02753 
02754 
02755     wxString text = m_HFOVText->GetValue();
02756     DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
02757     if (text == wxT("")) {
02758         return;
02759     }
02760 
02761     double hfov;
02762     if (!hugin_utils::str2double(text, hfov)) {
02763         wxLogError(_("Value must be numeric."));
02764         return;
02765     }
02766 
02767     if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
02768         wxLogError(wxString::Format(
02769             _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
02770             opt.getMaxHFOV()));
02771         hfov=opt.getMaxHFOV();
02772     }
02773     opt.setHFOV(hfov);
02774     // recalculate panorama height...
02775     PanoCommand::GlobalCmdHist::getInstance().addCommand(
02776         new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
02777         );
02778 
02779     DEBUG_INFO ( "new hfov: " << hfov )
02780 };
02781 
02782 void GLPreviewFrame::OnVFOVChanged ( wxCommandEvent & e )
02783 {
02784     HuginBase::PanoramaOptions opt = m_pano.getOptions();
02785 
02786     wxString text = m_VFOVText->GetValue();
02787     DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
02788     if (text == wxT("")) {
02789         return;
02790     }
02791 
02792     double vfov;
02793     if (!hugin_utils::str2double(text, vfov)) {
02794         wxLogError(_("Value must be numeric."));
02795         return;
02796     }
02797 
02798     if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
02799         wxLogError(wxString::Format(
02800             _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
02801             opt.getMaxVFOV()));
02802         vfov = opt.getMaxVFOV();
02803     }
02804     opt.setVFOV(vfov);
02805     // recalculate panorama height...
02806     PanoCommand::GlobalCmdHist::getInstance().addCommand(
02807         new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
02808         );
02809 
02810     DEBUG_INFO ( "new vfov: " << vfov )
02811 };
02812 
02813 void GLPreviewFrame::OnLayoutScaleChange(wxScrollEvent &e)
02814 {
02815     if(m_mode==mode_layout)
02816     {
02817         double scale_factor=XRCCTRL(*this,"layout_scale_slider",wxSlider)->GetValue();
02818         m_GLPreview->SetLayoutScale(10.0 - sqrt(scale_factor));
02819         m_GLOverview->SetLayoutScale(10.0 - sqrt(scale_factor));
02820         m_GLPreview->Refresh();
02821         m_GLOverview->Refresh();
02822     };
02823 };
02824 
02825 void GLPreviewFrame::ShowProjectionWarnings()
02826 {
02827     HuginBase::PanoramaOptions opts = m_pano.getOptions();
02828     double hfov = opts.getHFOV();
02829     double vfov = opts.getVFOV();
02830     double maxfov = hfov > vfov ? hfov : vfov;
02831     wxString message;
02832     // If this is set to true, offer rectilinear as an alternative if it fits.
02833     bool rectilinear_option = false;
02834     switch (opts.getProjection()) {
02835         case HuginBase::PanoramaOptions::RECTILINEAR:
02836             if (maxfov > 120.0) {
02837                             // wide rectilinear image
02838                 message = _("With a wide field of view, panoramas with rectilinear projection get very stretched towards the edges.\n");
02839                 if (vfov < 110) {
02840                     message += _("Since the field of view is only very wide in the horizontal direction, try a cylindrical projection instead.");
02841                 } else {
02842                     message += _("For a very wide panorama, try equirectangular projection instead.");
02843                 }
02844                 message += _(" You could also try Panini projection.");
02845             }
02846             break;
02847         case HuginBase::PanoramaOptions::CYLINDRICAL:
02848             if (vfov > 120.0) {
02849                 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.");
02850             } else rectilinear_option = true;
02851             break;
02852         case HuginBase::PanoramaOptions::EQUIRECTANGULAR:
02853             if (vfov < 110.0 && hfov > 120.0)
02854             {
02855                 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.");
02856             } else rectilinear_option = true;
02857             break;
02858         case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE:
02859             if (maxfov < 280.0) {
02860                 rectilinear_option = true;
02861                 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.");
02862             }
02863             break;
02864         case HuginBase::PanoramaOptions::STEREOGRAPHIC:
02865             if (maxfov > 300.0) {
02866                 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.");
02867             } else rectilinear_option = true;
02868             break;
02869         default:
02870             rectilinear_option = true;
02871     }
02872     if (rectilinear_option && maxfov < 110.0) {
02873         message = _("Setting the panorama to rectilinear projection would keep the straight lines straight.");
02874     }
02875     if (message.IsEmpty()) {
02876         // no message needed.
02877         m_infoBar->Dismiss();
02878     } else {
02879         m_infoBar->ShowMessage(message, wxICON_INFORMATION);
02880     }
02881 };
02882 
02883 void GLPreviewFrame::SetShowProjectionHints(bool new_value)
02884 {
02885     m_showProjectionHints=new_value;
02886     if(!m_showProjectionHints)
02887     {
02888         m_infoBar->Dismiss();
02889     };
02890 };
02891 
02892 void GLPreviewFrame::OnHideProjectionHints(wxCommandEvent &e)
02893 {
02894     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."),
02895 #ifdef __WXMSW__
02896         _("Hugin"),
02897 #else
02898         wxT(""),
02899 #endif
02900         wxOK | wxICON_INFORMATION, this);
02901 
02902     wxConfigBase* cfg=wxConfigBase::Get();
02903     cfg->Write(wxT("/GLPreviewFrame/ShowProjectionHints"), false);
02904     m_showProjectionHints=false;
02905     cfg->Flush();
02906     e.Skip();
02907 };
02908 
02909 void GLPreviewFrame::UpdateIdentifyTools(std::set<unsigned int> new_image_set)
02910 {
02911     if(identify_tool)
02912     {
02913         identify_tool->UpdateWithNewImageSet(new_image_set);
02914     };
02915     if(panosphere_overview_identify_tool)
02916     {
02917         panosphere_overview_identify_tool->UpdateWithNewImageSet(new_image_set);
02918     };
02919     if(plane_overview_identify_tool)
02920     {
02921         plane_overview_identify_tool->UpdateWithNewImageSet(new_image_set);
02922     };
02923 }
02924 
02925 void GLPreviewFrame::OnPreviewBackgroundColorChanged(wxColourPickerEvent & e) {
02926     m_preview_background_color = XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->GetColour();
02927     wxString c = m_preview_background_color.GetAsString(wxC2S_HTML_SYNTAX);
02928     wxConfigBase* cfg=wxConfigBase::Get();
02929     cfg->Write(wxT("/GLPreviewFrame/PreviewBackground"), c);
02930     cfg->Flush();
02931     panosphere_sphere_tool->SetPreviewBackgroundColor(m_preview_background_color);
02932     m_GLPreview->SetViewerBackground(m_preview_background_color);
02933     m_GLOverview->SetViewerBackground(m_preview_background_color);
02934     redrawPreview();
02935 }
02936 
02937 wxColor GLPreviewFrame::GetPreviewBackgroundColor() {
02938   return m_preview_background_color;
02939 }
02940 
02941 void GLPreviewFrame::OnGuideChanged(wxCommandEvent &e)
02942 {
02943     if(preview_guide_tool)
02944     {
02945         int selection=e.GetSelection();
02946         preview_guide_tool->SetGuideStyle((PreviewGuideTool::Guides)selection);
02947         //synchronize wxChoice in projection and crop tab
02948         m_GuideChoiceCrop->SetSelection(selection);
02949         m_GuideChoiceProj->SetSelection(selection);
02950         m_GuideChoiceDrag->SetSelection(selection);
02951         redrawPreview();
02952     };
02953 };
02954 
02955 void GLPreviewFrame::SetGuiLevel(GuiLevel newLevel)
02956 {
02957     int old_selection=m_DragModeChoice->GetSelection();
02958     if(old_selection==wxNOT_FOUND)
02959     {
02960         old_selection=0;
02961     };
02962     m_DragModeChoice->Clear();
02963     m_DragModeChoice->Append(_("normal"));
02964     m_DragModeChoice->Append(_("normal, individual"));
02965     if(newLevel==GUI_EXPERT)
02966     {
02967         m_DragModeChoice->Append(_("mosaic"));
02968         m_DragModeChoice->Append(_("mosaic, individual"));
02969         m_DragModeChoice->SetSelection(old_selection);
02970     }
02971     else
02972     {
02973         if(old_selection>1)
02974         {
02975             m_DragModeChoice->SetSelection(old_selection-2);
02976         }
02977         else
02978         {
02979             m_DragModeChoice->SetSelection(old_selection);
02980         };
02981     };
02982     DragChoiceLayout(m_DragModeChoice->GetSelection());
02983     wxCommandEvent dummy;
02984     OnDragChoice(dummy);
02985 
02986     old_selection=m_OverviewModeChoice->GetSelection();
02987     m_OverviewModeChoice->Clear();
02988     m_OverviewModeChoice->Append(_("Panosphere"));
02989     if(newLevel==GUI_EXPERT)
02990     {
02991         m_OverviewModeChoice->Append(_("Mosaic plane"));
02992     };
02993     if(newLevel==GUI_EXPERT && old_selection==1)
02994     {
02995         m_OverviewModeChoice->SetSelection(1);
02996     }
02997     else
02998     {
02999         m_GLOverview->SetMode(GLOverview::PANOSPHERE);
03000         m_OverviewModeChoice->SetSelection(0);
03001     };
03002     wxPanel* panel=XRCCTRL(*this, "overview_command_panel", wxPanel);
03003     panel->Show(newLevel==GUI_EXPERT);
03004     panel->GetParent()->Layout();
03005     if(newLevel==GUI_SIMPLE)
03006     {
03007 #ifdef __WXMAC__
03008         wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
03009 #endif
03010         if(m_guiLevel!=GUI_SIMPLE)
03011         {
03012             GetMenuBar()->Remove(0);
03013             GetMenuBar()->Insert(0, m_filemenuSimple, _("&File"));
03014         };
03015         SetTitle(MainFrame::Get()->GetTitle());
03016     }
03017     else
03018     {
03019 #ifdef __WXMAC__
03020         wxApp::s_macExitMenuItemId = XRCID("action_exit_hugin");
03021 #endif
03022         if(m_guiLevel==GUI_SIMPLE)
03023         {
03024             GetMenuBar()->Remove(0);
03025             GetMenuBar()->Insert(0, m_filemenuAdvanced, _("&File"));
03026         };
03027         SetTitle(_("Fast Panorama preview"));
03028     };
03029     m_guiLevel=newLevel;
03030     // update menu items
03031     switch(m_guiLevel)
03032     {
03033         case GUI_SIMPLE:
03034             GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
03035             break;
03036         case GUI_ADVANCED:
03037             GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
03038             break;
03039         case GUI_EXPERT:
03040             GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
03041             break;
03042     };
03043 };
03044 
03045 void GLPreviewFrame::OnShowMainFrame(wxCommandEvent &e)
03046 {
03047     MainFrame::Get()->Show();
03048     MainFrame::Get()->Raise();
03049 };
03050 
03051 void GLPreviewFrame::OnUserExit(wxCommandEvent &e)
03052 {
03053     Close();
03054 };
03055 
03056 void GLPreviewFrame::OnLoadImages( wxCommandEvent & e )
03057 {
03058     // load the images.
03059     PanoOperation::AddImageOperation addImage;
03060     HuginBase::UIntSet images;
03061     PanoCommand::PanoCommand* cmd=addImage.GetCommand(wxGetActiveWindow(), m_pano, images, m_guiLevel);
03062     if(cmd==NULL)
03063     {
03064         return;
03065     }
03066     //distribute images only if the existing images are not connected
03067     //otherwise it would destruct the existing image pattern
03068     bool distributeImages=m_pano.getNrOfCtrlPoints()==0;
03069 
03070     long autoAlign = wxConfigBase::Get()->Read(wxT("/Assistant/autoAlign"), HUGIN_ASS_AUTO_ALIGN); 
03071     if (autoAlign)
03072     {
03073         PanoCommand::GlobalCmdHist::getInstance().addCommand(cmd);
03074         wxCommandEvent dummy;
03075         OnAlign(dummy);
03076     }
03077     else
03078     {
03079         std::vector<PanoCommand::PanoCommand*> cmds;
03080         cmds.push_back(cmd);
03081         if(distributeImages)
03082         {
03083             cmds.push_back(new PanoCommand::DistributeImagesCmd(m_pano));
03084             cmds.push_back(new PanoCommand::CenterPanoCmd(m_pano));
03085         };
03086         PanoCommand::CombinedPanoCommand* combinedCmd = new PanoCommand::CombinedPanoCommand(m_pano, cmds);
03087         combinedCmd->setName("add and distribute images");
03088         PanoCommand::GlobalCmdHist::getInstance().addCommand(combinedCmd);
03089     };
03090 }
03091 
03092 void GLPreviewFrame::OnAlign( wxCommandEvent & e )
03093 {
03094     MainFrame::Get()->RunAssistant(this);
03095 }
03096 
03097 void GLPreviewFrame::OnCreate( wxCommandEvent & e )
03098 {
03099     PanoOutputDialog dlg(this, m_pano, m_guiLevel);
03100     if(dlg.ShowModal()==wxID_OK)
03101     {
03102         PanoCommand::GlobalCmdHist::getInstance().addCommand(
03103             new PanoCommand::SetPanoOptionsCmd(m_pano, dlg.GetNewPanoramaOptions())
03104             );
03105         wxCommandEvent dummy;
03106         MainFrame::Get()->OnDoStitch(dummy);
03107     };
03108 }
03109 
03110 void GLPreviewFrame::OnLensTypeChanged (wxCommandEvent & e)
03111 {
03112     // uses enum Lens::LensProjectionFormat from PanoramaMemento.h
03113     size_t var = GetSelectedValue(m_lensTypeChoice);
03114     const HuginBase::SrcPanoImage& img=m_pano.getImage(0);
03115     if (img.getProjection() != (HuginBase::Lens::LensProjectionFormat) var)
03116     {
03117         double fl = HuginBase::SrcPanoImage::calcFocalLength(img.getProjection(), img.getHFOV(), img.getCropFactor(), img.getSize());
03118         HuginBase::UIntSet imgs;
03119         imgs.insert(0);
03120         std::vector<PanoCommand::PanoCommand*> commands;
03121         commands.push_back(
03122                 new PanoCommand::ChangeImageProjectionCmd(
03123                                     m_pano,
03124                                     imgs,
03125                                     (HuginBase::SrcPanoImage::Projection) var
03126                                 )
03127             );
03128         
03129         commands.push_back(new PanoCommand::UpdateFocalLengthCmd(m_pano, imgs, fl));
03130         PanoCommand::GlobalCmdHist::getInstance().addCommand(
03131                 new PanoCommand::CombinedPanoCommand(m_pano, commands));
03132     }
03133 }
03134 
03135 void GLPreviewFrame::OnFocalLengthChanged(wxCommandEvent & e)
03136 {
03137     if (m_pano.getNrOfImages() == 0)
03138     {
03139         return;
03140     };
03141 
03142     // always change first lens
03143     wxString text = m_focalLengthText->GetValue();
03144     DEBUG_INFO("focal length: " << text.mb_str(wxConvLocal));
03145     double val;
03146     if (!hugin_utils::str2double(text, val))
03147     {
03148         return;
03149     }
03150     //no negative values, no zero input please
03151     if (val<0.1)
03152     {
03153         wxBell();
03154         return;
03155     };    
03156 
03157     // always change first lens...
03158     HuginBase::UIntSet images0;
03159     images0.insert(0);
03160     PanoCommand::GlobalCmdHist::getInstance().addCommand(
03161         new PanoCommand::UpdateFocalLengthCmd(m_pano, images0, val)
03162     );
03163 }
03164 
03165 void GLPreviewFrame::OnCropFactorChanged(wxCommandEvent & e)
03166 {
03167     if (m_pano.getNrOfImages() == 0)
03168     {
03169         return;
03170     };
03171 
03172     wxString text = m_cropFactorText->GetValue();
03173     DEBUG_INFO("crop factor: " << text.mb_str(wxConvLocal));
03174     double val;
03175     if (!hugin_utils::str2double(text, val))
03176     {
03177         return;
03178     }
03179     //no negative values, no zero input please
03180     if (val<0.1)
03181     {
03182         wxBell();
03183         return;
03184     };    
03185 
03186     HuginBase::UIntSet images;
03187     images.insert(0);
03188     PanoCommand::GlobalCmdHist::getInstance().addCommand(
03189         new PanoCommand::UpdateCropFactorCmd(m_pano,images,val)
03190     );
03191 }
03192 
03193 // remove cp, relatively easy, we get the selected cp from the edit cp tool
03194 void GLPreviewFrame::OnRemoveCP(wxCommandEvent & e)
03195 {
03196     edit_cp_tool->SetMenuProcessed();
03197     PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::RemoveCtrlPointsCmd(m_pano, edit_cp_tool->GetFoundCPs()));
03198     // ask user, if pano should be optimized
03199     long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
03200     bool optimize = false;
03201     if (afterEditCPAction == 0)
03202     {
03203         wxDialog dlg;
03204         wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("edit_cp_optimize_dialog"));
03205         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())));
03206         XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
03207         dlg.Fit();
03208         optimize = (dlg.ShowModal() == wxID_OK);
03209         if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
03210         {
03211             if (optimize)
03212             {
03213                 wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
03214             }
03215             else
03216             {
03217                 wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
03218             };
03219         };
03220     }
03221     else
03222     {
03223         optimize = (afterEditCPAction == 1);
03224     }
03225     if (optimize)
03226     {
03227         // invoke optimization routine
03228         wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
03229         MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
03230     };
03231 };
03232 
03233 // some helper for cp generation
03234 // maximal width for remapping for cp generating
03235 #define MAX_DIMENSION 1600
03236 struct FindStruct
03237 {
03238     size_t imgNr;
03239     vigra::BRGBImage image;
03240     vigra::BImage mask;
03241 };
03242 
03243 typedef std::vector<FindStruct> FindVector;
03244 typedef std::multimap<double, vigra::Diff2D> MapPoints;
03245 
03246 static hugin_omp::Lock cpLock;
03247 
03248 void GLPreviewFrame::OnCreateCP(wxCommandEvent & e)
03249 {
03250     edit_cp_tool->SetMenuProcessed();
03251     vigra::Rect2D roi = edit_cp_tool->GetSelectedROI();
03252     HuginBase::UIntSet imgs = HuginBase::getImagesinROI(m_pano, m_pano.getActiveImages(), roi);
03253     // some checking of conditions
03254     if (imgs.empty())
03255     {
03256         wxMessageBox(_("The selected region contains no active image.\nPlease select a region which is covered by at least 2 images."),
03257 #ifdef __WXMSW__
03258             _("Hugin"),
03259 #else
03260             wxT(""),
03261 #endif
03262             wxOK | wxICON_INFORMATION, this);
03263         return;
03264     };
03265     if (imgs.size() < 2)
03266     {
03267         wxMessageBox(_("The selected region is only covered by a single image.\nCan't create control points for a single image."),
03268 #ifdef __WXMSW__
03269             _("Hugin"),
03270 #else
03271             wxT(""),
03272 #endif
03273             wxOK | wxICON_INFORMATION, this);
03274         return;
03275     };
03276     if (roi.width() > 0.25 * m_pano.getOptions().getWidth())
03277     {
03278         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?"),
03279 #ifdef __WXMSW__
03280             _("Hugin"),
03281 #else
03282             wxT(""),
03283 #endif
03284             wxYES_NO | wxICON_INFORMATION, this) == wxNO)
03285         {
03286             return;
03287         };
03288     }
03289     HuginBase::PanoramaOptions opts = m_pano.getOptions();
03290     opts.setROI(roi);
03291     // don't correct exposure
03292     opts.outputExposureValue = 0;
03293     // don't use GPU for remapping, this interfere with the fast preview window
03294     opts.remapUsingGPU = false;
03295     // rescale if size is too big
03296     if (roi.width() > MAX_DIMENSION)
03297     {
03298         opts.setWidth(opts.getWidth() * MAX_DIMENSION / roi.width(), true);
03299         roi = opts.getROI();
03300     };
03301     HuginBase::CPVector cps;
03302     {
03303         ProgressReporterDialog progress(2*imgs.size()+1, _("Searching control points"), _("Processing"), this);
03304         // remap all images to panorama projection
03305         FindVector cpInfos;
03306         HuginBase::CPVector tempCps;
03307         for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
03308         {
03309             const size_t imgNr = *it;
03310             if (!progress.updateDisplayValue(_("Remap image to panorama projection...")))
03311             {
03312                 return;
03313             };
03314             FindStruct findStruct;
03315             findStruct.imgNr = imgNr;
03316             // remap image to panorama projection
03317             ImageCache::ImageCacheRGB8Ptr CachedImg = ImageCache::getInstance().getImage(m_pano.getImage(imgNr).getFilename())->get8BitImage();
03318 
03319             HuginBase::Nona::RemappedPanoImage<vigra::BRGBImage, vigra::BImage>* remapped = new HuginBase::Nona::RemappedPanoImage<vigra::BRGBImage, vigra::BImage>;
03320             HuginBase::SrcPanoImage srcImg = m_pano.getSrcImage(imgNr);
03321             // don't correct exposure
03322             srcImg.setExposureValue(0);
03323             remapped->setPanoImage(srcImg, opts, roi);
03324             remapped->remapImage(vigra::srcImageRange(*CachedImg), vigra_ext::INTERP_CUBIC, &progress);
03325             if (!progress.updateDisplay())
03326             {
03327                 delete remapped;
03328                 return;
03329             };
03330             findStruct.image = remapped->m_image;
03331             findStruct.mask = remapped->m_mask;
03332             delete remapped;
03333             cpInfos.push_back(findStruct);
03334         };
03335         if (cpInfos.size() > 1)
03336         {
03337             // match keypoints in all image pairs
03338             // select a sensible grid size depending on ratio of selected region, maximal should it be 25 regions
03339             unsigned gridx = hugin_utils::roundi(sqrt((double)roi.width() / (double)roi.height() * 25));
03340             if (gridx < 1)
03341             {
03342                 gridx = 1;
03343             }
03344             unsigned gridy = hugin_utils::roundi(25 / gridx);
03345             if (gridy < 1)
03346             {
03347                 gridy = 1;
03348             }
03349             // template width
03350             const long templWidth = 20;
03351             // search width
03352             const long sWidth = 100;
03353             // match all images with all
03354             for (size_t img1 = 0; img1 < cpInfos.size() - 1; ++img1)
03355             {
03356                 if (!progress.updateDisplayValue(_("Matching interest points...")))
03357                 {
03358                     return;
03359                 };
03360                 vigra::Size2D size(cpInfos[img1].image.width(), cpInfos[img1].image.height());
03361                 // create a number of sub-regions
03362                 std::vector<vigra::Rect2D> rects;
03363                 for (unsigned party = 0; party < gridy; party++)
03364                 {
03365                     for (unsigned partx = 0; partx < gridx; partx++)
03366                     {
03367                         vigra::Rect2D rect(partx*size.x / gridx, party*size.y / gridy,
03368                             (partx + 1)*size.x / gridx, (party + 1)*size.y / gridy);
03369                         rect &= vigra::Rect2D(size);
03370                         if (rect.width()>0 && rect.height()>0)
03371                         {
03372                             rects.push_back(rect);
03373                         };
03374                     };
03375                 };
03376 
03377                 if (!progress.updateDisplay())
03378                 {
03379                     return;
03380                 };
03381 
03382 #pragma omp parallel for schedule(dynamic)
03383                 for (int i = 0; i < rects.size(); ++i)
03384                 {
03385                     MapPoints points;
03386                     vigra::Rect2D rect(rects[i]);
03387                     // run interest point detection in sub-region
03388                     vigra_ext::findInterestPointsPartial(srcImageRange(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >()), rect, 2, 5 * 8, points);
03389                     //check if all points are inside the given image
03390                     MapPoints validPoints;
03391                     for (MapPoints::const_iterator it = points.begin(); it != points.end(); ++it)
03392                     {
03393                         if (cpInfos[img1].mask(it->second.x, it->second.y)>0)
03394                         {
03395                             validPoints.insert(*it);
03396                         };
03397                     };
03398 
03399                     if (!validPoints.empty())
03400                     {
03401                         // now fine-tune the interest points with all other images
03402                         for (size_t img2 = img1 + 1; img2 < cpInfos.size(); ++img2)
03403                         {
03404                             unsigned nGood = 0;
03405                             // loop over all points, starting with the highest corner score
03406                             for (MapPoints::const_reverse_iterator it = validPoints.rbegin(); it != validPoints.rend(); ++it)
03407                             {
03408                                 if (nGood >= 2)
03409                                 {
03410                                     // we have enough points, stop
03411                                     break;
03412                                 }
03413                                 //check if point is covered by second image
03414                                 if (cpInfos[img2].mask(it->second.x, it->second.y) == 0)
03415                                 {
03416                                     continue;
03417                                 };
03418                                 // finally fine-tune point
03419                                 vigra_ext::CorrelationResult res = vigra_ext::PointFineTune(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, templWidth,
03420                                     cpInfos[img2].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, sWidth);
03421                                 if (res.maxi < 0.9)
03422                                 {
03423                                     continue;
03424                                 }
03425                                 nGood++;
03426                                 // add control point
03427                                 {
03428                                     hugin_omp::ScopedLock sl(cpLock);
03429                                     tempCps.push_back(HuginBase::ControlPoint(cpInfos[img1].imgNr, it->second.x, it->second.y,
03430                                         cpInfos[img2].imgNr, res.maxpos.x, res.maxpos.y, HuginBase::ControlPoint::X_Y));
03431                                 };
03432                             };
03433                         };
03434                     };
03435                 };
03436                 // free memory
03437                 cpInfos[img1].image.resize(0, 0);
03438                 cpInfos[img1].mask.resize(0, 0);
03439             };
03440 
03441             // transform coordinates back to image space
03442             for (size_t i = 0; i < tempCps.size(); ++i)
03443             {
03444                 HuginBase::ControlPoint cp = tempCps[i];
03445                 hugin_utils::FDiff2D p1(cp.x1 + roi.left(), cp.y1 + roi.top());
03446                 hugin_utils::FDiff2D p1Img;
03447                 HuginBase::PTools::Transform transform;
03448                 transform.createTransform(m_pano.getImage(cp.image1Nr), opts);
03449                 if (transform.transformImgCoord(p1Img, p1))
03450                 {
03451                     hugin_utils::FDiff2D p2(cp.x2 + roi.left(), cp.y2 + roi.top());
03452                     hugin_utils::FDiff2D p2Img;
03453                     transform.createTransform(m_pano.getImage(cp.image2Nr), opts);
03454                     if (transform.transformImgCoord(p2Img, p2))
03455                     {
03456                         cp.x1 = p1Img.x;
03457                         cp.y1 = p1Img.y;
03458                         cp.x2 = p2Img.x;
03459                         cp.y2 = p2Img.y;
03460                         cps.push_back(cp);
03461                     };
03462                 };
03463             };
03464 
03465             if (!cps.empty())
03466             {
03467                 // check newly found control points
03468                 // create copy
03469                 HuginBase::Panorama copyPano=m_pano.duplicate();
03470                 // remove all cps and set only the new found cp
03471                 copyPano.setCtrlPoints(cps);
03472                 // now create a subpano with only the selected images
03473                 HuginBase::Panorama subPano = copyPano.getSubset(imgs);
03474                 // clean control points
03475                 if (!progress.updateDisplayValue(_("Checking results...")))
03476                 {
03477                     return;
03478                 };
03479                 deregisterPTWXDlgFcn();
03480                 HuginBase::UIntSet invalidCP = HuginBase::getCPoutsideLimit(subPano);
03481                 registerPTWXDlgFcn();
03482                 if (!invalidCP.empty())
03483                 {
03484                     for (HuginBase::UIntSet::const_reverse_iterator it = invalidCP.rbegin(); it != invalidCP.rend(); ++it)
03485                     {
03486                         cps.erase(cps.begin() + *it);
03487                     };
03488                 }
03489                 // force closing progress dialog
03490                 if (!progress.updateDisplayValue())
03491                 {
03492                     return;
03493                 };
03494                 PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::AddCtrlPointsCmd(m_pano, cps));
03495                 // ask user, if pano should be optimized
03496                 long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
03497                 bool optimize = false;
03498                 if (afterEditCPAction == 0)
03499                 {
03500                     wxDialog dlg;
03501                     wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("edit_cp_optimize_dialog"));
03502                     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())));
03503                     XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
03504                     dlg.Fit();
03505                     optimize = (dlg.ShowModal() == wxID_OK);
03506                     if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
03507                     {
03508                         if (optimize)
03509                         {
03510                             wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
03511                         }
03512                         else
03513                         {
03514                             wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
03515                         };
03516                     };
03517                 }
03518                 else
03519                 {
03520                     optimize = (afterEditCPAction == 1);
03521                 }
03522                 if (optimize)
03523                 {
03524                     // invoke optimization routine
03525                     wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
03526                     MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
03527                 };
03528             };
03529         };
03530     };
03531     // finally redraw
03532     m_GLPreview->Update();
03533     m_GLPreview->Refresh();
03534 };
03535 
03536 // handle menu close event to redraw preview, so that selection rectangle is hidden
03537 void GLPreviewFrame::OnMenuClose(wxMenuEvent & e)
03538 {
03539     m_GLPreview->Refresh();
03540     e.Skip();
03541 };
03542 
03543 void GLPreviewFrame::OnSelectContextMenu(wxContextMenuEvent& e)
03544 {
03545     wxPoint point = e.GetPosition();
03546     // If from keyboard
03547     if (point.x == -1 && point.y == -1)
03548     {
03549         point = m_selectAllButton->GetPosition();
03550     }
03551     else
03552     {
03553         point = ScreenToClient(point);
03554     }
03555     PopupMenu(m_selectAllMenu, point);
03556 };
03557 
03558 void GLPreviewFrame::OnSelectAllMenu(wxCommandEvent& e)
03559 {
03560     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
03561     m_selectAllMode = SELECT_ALL_IMAGES;
03562 };
03563 
03564 void GLPreviewFrame::OnSelectMedianMenu(wxCommandEvent& e)
03565 {
03566     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 1l);
03567     m_selectAllMode = SELECT_MEDIAN_IMAGES;
03568 };
03569 
03570 void GLPreviewFrame::OnSelectBrightestMenu(wxCommandEvent& e)
03571 {
03572     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 2l);
03573     m_selectAllMode = SELECT_BRIGHTEST_IMAGES;
03574 };
03575 
03576 void GLPreviewFrame::OnSelectDarkestMenu(wxCommandEvent& e)
03577 {
03578     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 3l);
03579     m_selectAllMode = SELECT_DARKEST_IMAGES;
03580 };
03581 
03582 void GLPreviewFrame::OnSelectKeepSelection(wxCommandEvent& e)
03583 {
03584     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), true);
03585     m_selectKeepSelection = true;
03586 };
03587 
03588 void GLPreviewFrame::OnSelectResetSelection(wxCommandEvent& e)
03589 {
03590     wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), false);
03591     m_selectKeepSelection = false;
03592 };

Generated on 22 May 2017 for Hugintrunk by  doxygen 1.4.7