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

Generated on 27 Feb 2017 for Hugintrunk by  doxygen 1.4.7