GLPreviewFrame.cpp

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

Generated on 2 Sep 2015 for Hugintrunk by  doxygen 1.4.7