MaskEditorPanel.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00011 /*  This program is free software; you can redistribute it and/or
00012  *  modify it under the terms of the GNU General Public
00013  *  License as published by the Free Software Foundation; either
00014  *  version 2 of the License, or (at your option) any later version.
00015  *
00016  *  This software is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  *  General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public
00022  *  License along with this software. If not, see
00023  *  <http://www.gnu.org/licenses/>.
00024  *
00025  */
00026 
00027 // often necessary before panoinc.h
00028 #ifdef __APPLE__
00029 #include "panoinc_WX.h"
00030 #endif
00031 
00032 #include "panoinc.h"
00033 #include <hugin_utils/stl_utils.h>
00034 
00035 // hugin's
00036 #include "base_wx/platform.h"
00037 #include "hugin/MainFrame.h"
00038 #include "hugin/config_defaults.h"
00039 #include "base_wx/CommandHistory.h"
00040 #include "base_wx/PanoCommand.h"
00041 #include "hugin/MaskEditorPanel.h"
00042 #include "hugin/MaskLoadDialog.h"
00043 #include <wx/clipbrd.h>
00044 #include "hugin/TextKillFocusHandler.h"
00045 
00046 BEGIN_EVENT_TABLE(MaskEditorPanel, wxPanel)
00047     EVT_LIST_ITEM_SELECTED(XRCID("mask_editor_images_list"), MaskEditorPanel::OnImageSelect)
00048     EVT_LIST_ITEM_DESELECTED(XRCID("mask_editor_images_list"), MaskEditorPanel::OnImageSelect)
00049     EVT_LIST_ITEM_SELECTED(XRCID("mask_editor_mask_list"), MaskEditorPanel::OnMaskSelect)
00050     EVT_LIST_ITEM_DESELECTED(XRCID("mask_editor_mask_list"), MaskEditorPanel::OnMaskSelect)
00051     EVT_LIST_COL_END_DRAG(XRCID("mask_editor_mask_list"), MaskEditorPanel::OnColumnWidthChange)
00052     EVT_CHOICE(XRCID("mask_editor_choice_zoom"), MaskEditorPanel::OnZoom)
00053     EVT_CHOICE(XRCID("mask_editor_choice_masktype"), MaskEditorPanel::OnMaskTypeChange)
00054     EVT_BUTTON(XRCID("mask_editor_add"), MaskEditorPanel::OnMaskAdd)
00055     EVT_BUTTON(XRCID("mask_editor_load"), MaskEditorPanel::OnMaskLoad)
00056     EVT_BUTTON(XRCID("mask_editor_save"), MaskEditorPanel::OnMaskSave)
00057     EVT_BUTTON(XRCID("mask_editor_copy"), MaskEditorPanel::OnMaskCopy)
00058     EVT_BUTTON(XRCID("mask_editor_paste"), MaskEditorPanel::OnMaskPaste)
00059     EVT_BUTTON(XRCID("mask_editor_delete"), MaskEditorPanel::OnMaskDelete)
00060     EVT_CHECKBOX(XRCID("mask_editor_show_active_masks"), MaskEditorPanel::OnShowActiveMasks)
00061     EVT_COLOURPICKER_CHANGED(XRCID("mask_editor_colour_polygon_negative"),MaskEditorPanel::OnColourChanged)
00062     EVT_COLOURPICKER_CHANGED(XRCID("mask_editor_colour_polygon_positive"),MaskEditorPanel::OnColourChanged)
00063     EVT_COLOURPICKER_CHANGED(XRCID("mask_editor_colour_point_selected"),MaskEditorPanel::OnColourChanged)
00064     EVT_COLOURPICKER_CHANGED(XRCID("mask_editor_colour_point_unselected"),MaskEditorPanel::OnColourChanged)
00065     EVT_TEXT_ENTER (XRCID("crop_left_text") ,MaskEditorPanel::OnSetLeft )
00066     EVT_TEXT_ENTER (XRCID("crop_right_text") ,MaskEditorPanel::OnSetRight )
00067     EVT_TEXT_ENTER (XRCID("crop_top_text") ,MaskEditorPanel::OnSetTop )
00068     EVT_TEXT_ENTER (XRCID("crop_bottom_text") ,MaskEditorPanel::OnSetBottom )
00069     EVT_BUTTON ( XRCID("crop_reset_button") , MaskEditorPanel::OnResetButton )
00070     EVT_CHECKBOX( XRCID("crop_autocenter_cb") , MaskEditorPanel::OnAutoCenter)
00071     EVT_NOTEBOOK_PAGE_CHANGED(XRCID("mask_editor_mask_crop_notebook"), MaskEditorPanel::OnModeChanged)
00072 END_EVENT_TABLE()
00073 
00074 MaskEditorPanel::MaskEditorPanel()
00075 {
00076     DEBUG_TRACE("**********************");
00077     m_pano = 0;
00078     m_maskCropCtrl=NULL;
00079     m_defaultMaskType=HuginBase::MaskPolygon::Mask_negative;
00080 }
00081 
00082 bool MaskEditorPanel::Create(wxWindow* parent, wxWindowID id,
00083                     const wxPoint& pos,
00084                     const wxSize& size,
00085                     long style,
00086                     const wxString& name)
00087 {
00088     DEBUG_TRACE(" Create called *************");
00089     if (! wxPanel::Create(parent, id, pos, size, style, name))
00090     {
00091         return false;
00092     }
00093 
00094     m_selectedImages.clear();
00095     m_MaskNr=UINT_MAX;
00096     m_File="";
00097 
00098     wxXmlResource::Get()->LoadPanel(this, wxT("mask_panel"));
00099     wxPanel * panel = XRCCTRL(*this, "mask_panel", wxPanel);
00100 
00101     wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
00102     topsizer->Add(panel, 1, wxEXPAND, 0);
00103     SetSizer(topsizer);
00104 
00105     m_editImg = XRCCTRL(*this, "mask_editor_polygon_editor", MaskImageCtrl);
00106     assert(m_editImg);
00107     m_editImg->Init(this);
00108 
00109     // images list
00110     m_imagesListMask = XRCCTRL(*this, "mask_editor_images_list", ImagesListMask);
00111     // mask list
00112     m_maskList = XRCCTRL(*this, "mask_editor_mask_list", wxListCtrl);
00113     m_maskList->InsertColumn( 0, wxT("#"), wxLIST_FORMAT_RIGHT, 35);
00114     m_maskList->InsertColumn( 1, _("Mask type"), wxLIST_FORMAT_LEFT, 120);
00115 
00116     m_maskCropCtrl = XRCCTRL(*this, "mask_editor_mask_crop_notebook", wxNotebook);
00117     DEBUG_ASSERT(m_maskCropCtrl);
00118     m_maskCropCtrl->SetSelection(0);
00119     m_maskMode=true;
00120 
00121     //get saved width
00122     wxConfigBase *config=wxConfigBase::Get();
00123     for ( int j=0; j < m_maskList->GetColumnCount() ; j++ )
00124     {
00125         // -1 is auto
00126         int width = config->Read(wxString::Format( wxT("/MaskEditorPanel/ColumnWidth%d"), j ), -1);
00127         if(width != -1)
00128             m_maskList->SetColumnWidth(j, width);
00129     }
00130     bool activeMasks;
00131     config->Read(wxT("/MaskEditorPanel/ShowActiveMasks"),&activeMasks,false);
00132     XRCCTRL(*this,"mask_editor_show_active_masks",wxCheckBox)->SetValue(activeMasks);
00133     m_editImg->setDrawingActiveMasks(activeMasks);
00134 
00135     //load and set colours
00136     wxColour defaultColour;
00137     defaultColour.Set(wxT(HUGIN_MASK_COLOUR_POLYGON_NEGATIVE));
00138     wxColour colour=wxConfigBase::Get()->Read(wxT("/MaskEditorPanel/ColourPolygonNegative"),defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
00139     XRCCTRL(*this,"mask_editor_colour_polygon_negative",wxColourPickerCtrl)->SetColour(colour);
00140     m_editImg->SetUserColourPolygonNegative(colour);
00141     defaultColour.Set(wxT(HUGIN_MASK_COLOUR_POLYGON_POSITIVE));
00142     colour=wxConfigBase::Get()->Read(wxT("/MaskEditorPanel/ColourPolygonPositive"),defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
00143     XRCCTRL(*this,"mask_editor_colour_polygon_positive",wxColourPickerCtrl)->SetColour(colour);
00144     m_editImg->SetUserColourPolygonPositive(colour);
00145     defaultColour.Set(wxT(HUGIN_MASK_COLOUR_POINT_SELECTED));
00146     colour=wxConfigBase::Get()->Read(wxT("/MaskEditorPanel/ColourPointSelected"),defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
00147     XRCCTRL(*this,"mask_editor_colour_point_selected",wxColourPickerCtrl)->SetColour(colour);
00148     m_editImg->SetUserColourPointSelected(colour);
00149     defaultColour.Set(wxT(HUGIN_MASK_COLOUR_POINT_UNSELECTED));
00150     colour=wxConfigBase::Get()->Read(wxT("/MaskEditorPanel/ColourPointUnselected"),defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
00151     XRCCTRL(*this,"mask_editor_colour_point_unselected",wxColourPickerCtrl)->SetColour(colour);
00152     m_editImg->SetUserColourPointUnselected(colour);
00153 
00154     // other controls
00155     m_maskType = XRCCTRL(*this, "mask_editor_choice_masktype", wxChoice);
00156     m_defaultMaskType=(HuginBase::MaskPolygon::MaskType)wxConfigBase::Get()->Read(wxT("/MaskEditorPanel/DefaultMaskType"), 0l);
00157     m_maskType->SetSelection((int)m_defaultMaskType);
00158     // disable some controls
00159     m_maskType->Disable();
00160     XRCCTRL(*this, "mask_editor_choice_zoom", wxChoice)->Disable();
00161     XRCCTRL(*this, "mask_editor_add", wxButton)->Disable();
00162     XRCCTRL(*this, "mask_editor_load", wxButton)->Disable();
00163     XRCCTRL(*this, "mask_editor_save", wxButton)->Disable();
00164     XRCCTRL(*this, "mask_editor_copy", wxButton)->Disable();
00165     XRCCTRL(*this, "mask_editor_paste", wxButton)->Disable();
00166     XRCCTRL(*this, "mask_editor_delete", wxButton)->Disable();
00167 
00168     m_left_textctrl = XRCCTRL(*this,"crop_left_text", wxTextCtrl);
00169     DEBUG_ASSERT(m_left_textctrl);
00170     m_left_textctrl->PushEventHandler(new TextKillFocusHandler(this));
00171 
00172     m_top_textctrl = XRCCTRL(*this,"crop_top_text", wxTextCtrl);
00173     DEBUG_ASSERT(m_top_textctrl);
00174     m_top_textctrl->PushEventHandler(new TextKillFocusHandler(this));
00175 
00176     m_right_textctrl = XRCCTRL(*this,"crop_right_text", wxTextCtrl);
00177     DEBUG_ASSERT(m_right_textctrl);
00178     m_right_textctrl->PushEventHandler(new TextKillFocusHandler(this));
00179 
00180     m_bottom_textctrl = XRCCTRL(*this,"crop_bottom_text", wxTextCtrl);
00181     DEBUG_ASSERT(m_bottom_textctrl);
00182     m_bottom_textctrl->PushEventHandler(new TextKillFocusHandler(this));
00183 
00184     m_autocenter_cb = XRCCTRL(*this,"crop_autocenter_cb", wxCheckBox);
00185     DEBUG_ASSERT(m_autocenter_cb);
00186 
00187     //set shortcuts
00188     wxAcceleratorEntry entries[2];
00189     entries[0].Set(wxACCEL_CMD,(int)'C',XRCID("mask_editor_copy"));
00190     entries[1].Set(wxACCEL_CMD,(int)'V',XRCID("mask_editor_paste"));
00191     wxAcceleratorTable accel(2, entries);
00192     SetAcceleratorTable(accel);
00193 
00194     // apply zoom specified in xrc file
00195     wxCommandEvent dummy;
00196     dummy.SetInt(XRCCTRL(*this,"mask_editor_choice_zoom",wxChoice)->GetSelection());
00197     OnZoom(dummy);
00198     return true;
00199 }
00200 
00201 void MaskEditorPanel::Init(HuginBase::Panorama * pano)
00202 {
00203     m_pano=pano;
00204     m_imagesListMask->Init(m_pano);
00205     // observe the panorama
00206     m_pano->addObserver(this);
00207 }
00208 
00209 MaskEditorPanel::~MaskEditorPanel()
00210 {
00211     m_left_textctrl->PopEventHandler(true);
00212     m_right_textctrl->PopEventHandler(true);
00213     m_top_textctrl->PopEventHandler(true);
00214     m_bottom_textctrl->PopEventHandler(true);
00215     wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ShowActiveMasks"),XRCCTRL(*this,"mask_editor_show_active_masks",wxCheckBox)->GetValue());
00216     wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/DefaultMaskType"),(long)m_defaultMaskType);
00217     DEBUG_TRACE("dtor");
00218     m_pano->removeObserver(this);
00219 }
00220 
00221 size_t MaskEditorPanel::GetImgNr()
00222 {
00223     if(m_selectedImages.size()==0)
00224     {
00225         return UINT_MAX;
00226     }
00227     else
00228     {
00229         return *(m_selectedImages.begin());
00230     };
00231 };
00232 
00233 void MaskEditorPanel::setImage(unsigned int imgNr, bool updateListSelection)
00234 {
00235     DEBUG_TRACE("image " << imgNr);
00236     bool restoreMaskSelection=(imgNr==GetImgNr());
00237     bool updateImage=true;
00238     if(imgNr==UINT_MAX)
00239     {
00240         m_selectedImages.clear();
00241     }
00242     else
00243     {
00244         m_selectedImages.insert(imgNr);
00245     };
00246     HuginBase::MaskPolygonVector masksToDraw;
00247     if (imgNr == UINT_MAX) 
00248     {
00249         m_File = "";
00250         HuginBase::MaskPolygonVector mask;
00251         m_currentMasks=mask;
00252         m_editImg->setCrop(HuginBase::SrcPanoImage::NO_CROP,vigra::Rect2D(), false, hugin_utils::FDiff2D(), false);
00253     } 
00254     else 
00255     {
00256         const HuginBase::SrcPanoImage& image=m_pano->getImage(imgNr);
00257         updateImage=(m_File!=image.getFilename());
00258         if(updateImage)
00259             m_File=image.getFilename();
00260         else
00261             if(GetRot(imgNr)!=m_editImg->getCurrentRotation())
00262             {
00263                 updateImage=true;
00264                 m_File=image.getFilename();
00265             };
00266         m_currentMasks=image.getMasks();
00267         masksToDraw=image.getActiveMasks();
00268         m_editImg->setCrop(image.getCropMode(),image.getCropRect(), image.getAutoCenterCrop(), image.getRadialDistortionCenter(), image.isCircularCrop());
00269     };
00270     // update mask editor
00271     if(updateImage)
00272         m_editImg->setImage(m_File,m_currentMasks,masksToDraw,GetRot(imgNr));
00273     else
00274         m_editImg->setNewMasks(m_currentMasks,masksToDraw);
00275     if(m_currentMasks.size()==0)
00276         setMask(UINT_MAX);
00277     // enables or disables controls
00278     bool enableCtrl=(imgNr<UINT_MAX);
00279     XRCCTRL(*this, "mask_editor_choice_zoom", wxChoice)->Enable(enableCtrl);
00280     XRCCTRL(*this, "mask_editor_add", wxButton)->Enable(enableCtrl);
00281     XRCCTRL(*this, "mask_editor_delete", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
00282     XRCCTRL(*this, "mask_editor_load", wxButton)->Enable(enableCtrl);
00283     XRCCTRL(*this, "mask_editor_save", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
00284     XRCCTRL(*this, "mask_editor_paste", wxButton)->Enable(enableCtrl);
00285     XRCCTRL(*this, "mask_editor_copy", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
00286     UpdateMaskList(restoreMaskSelection);
00287     // FIXME: lets hope that nobody holds references to these images..
00288     ImageCache::getInstance().softFlush();
00289     if(updateListSelection)
00290     {
00291         m_imagesListMask->SelectSingleImage(imgNr);
00292     };
00293 }
00294 
00295 void MaskEditorPanel::setMask(unsigned int maskNr)
00296 {
00297     m_MaskNr=maskNr;
00298     m_maskType->Enable(m_MaskNr<UINT_MAX);
00299     m_editImg->setActiveMask(m_MaskNr);
00300     XRCCTRL(*this,"mask_editor_delete", wxButton)->Enable(m_MaskNr<UINT_MAX);
00301     XRCCTRL(*this, "mask_editor_save", wxButton)->Enable(m_MaskNr<UINT_MAX);
00302     XRCCTRL(*this, "mask_editor_copy", wxButton)->Enable(m_MaskNr<UINT_MAX);
00303     if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
00304         m_maskType->SetSelection(m_currentMasks[m_MaskNr].getMaskType());
00305     else
00306         m_maskType->SetSelection((int)m_defaultMaskType);
00307 };
00308 
00309 void MaskEditorPanel::UpdateMask()
00310 {
00311     if(GetImgNr()<UINT_MAX)
00312     {
00313         m_currentMasks=m_editImg->getNewMask();
00314         PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::UpdateMaskForImgCmd(*m_pano, GetImgNr(), m_currentMasks));
00315     };
00316 };
00317 
00318 void MaskEditorPanel::AddMask()
00319 {
00320     if(GetImgNr()<UINT_MAX)
00321     {
00322         m_currentMasks=m_editImg->getNewMask();
00323         m_currentMasks[m_currentMasks.size()-1].setMaskType(m_defaultMaskType);
00324         PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::UpdateMaskForImgCmd(*m_pano, GetImgNr(), m_currentMasks));
00325         //select added mask
00326         SelectMask(m_currentMasks.size()-1);
00327         m_editImg->selectAllMarkers();
00328     };
00329 };
00330 
00331 void MaskEditorPanel::SelectMask(unsigned int newMaskNr)
00332 {
00333     if (GetImgNr() < UINT_MAX)
00334     {
00335         if (newMaskNr < m_currentMasks.size())
00336         {
00337             m_maskList->SetItemState(newMaskNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
00338         }
00339         else
00340         {
00341             if (m_MaskNr < UINT_MAX)
00342             {
00343                 m_maskList->SetItemState(m_MaskNr, 0, wxLIST_STATE_SELECTED);
00344             };
00345         };
00346     };
00347 };
00348 
00349 void MaskEditorPanel::panoramaChanged(HuginBase::Panorama &pano)
00350 {
00351 };
00352 
00353 void MaskEditorPanel::panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
00354 {
00355     unsigned int nrImages = pano.getNrOfImages();
00356     ImageCache::getInstance().softFlush();
00357     if (nrImages==0)
00358         setImage(UINT_MAX);
00359     else
00360     {
00361         // select some other image if we deleted the current image
00362         if ((GetImgNr()<UINT_MAX) && (GetImgNr() >= nrImages))
00363             setImage(nrImages-1);
00364         else
00365             // update changed images
00366             if(set_contains(changed,GetImgNr()))
00367             {
00368                 unsigned int countOldMasks=m_currentMasks.size();
00369                 setImage(GetImgNr());
00370                 if(countOldMasks!=pano.getImage(GetImgNr()).getMasks().size())
00371                     SelectMask(UINT_MAX);
00372             };
00373     };
00374 
00375     if (m_selectedImages.size() > 0)
00376     {
00377         if (set_contains(changed, GetImgNr()))
00378         {
00379             DisplayCrop(GetImgNr());
00380         }
00381     }
00382     else
00383     {
00384         UpdateCropDisplay();
00385     }
00386 
00387 }
00388 
00389 void MaskEditorPanel::OnImageSelect(wxListEvent &e)
00390 {
00391     m_selectedImages=m_imagesListMask->GetSelected();
00392     //select no mask
00393     setMask(UINT_MAX);
00394     setImage(GetImgNr());
00395 
00396     bool hasImage = (m_selectedImages.size() > 0);
00397     m_left_textctrl->Enable(hasImage);
00398     m_top_textctrl->Enable(hasImage);
00399     m_bottom_textctrl->Enable(hasImage);
00400     m_right_textctrl->Enable(hasImage);
00401     if (hasImage)
00402     {
00403         // show first image.
00404         DisplayCrop(GetImgNr());
00405     };
00406 };
00407 
00408 void MaskEditorPanel::OnMaskSelect(wxListEvent &e)
00409 {
00410     setMask(GetSelectedMask());
00411 };
00412 
00413 void MaskEditorPanel::OnMaskTypeChange(wxCommandEvent &e)
00414 {
00415     if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
00416     {
00417         m_currentMasks[m_MaskNr].setMaskType((HuginBase::MaskPolygon::MaskType)e.GetSelection());
00418         m_defaultMaskType=(HuginBase::MaskPolygon::MaskType)e.GetSelection();
00419         PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::UpdateMaskForImgCmd(*m_pano, GetImgNr(), m_currentMasks));
00420     };
00421 };
00422 
00423 void MaskEditorPanel::OnMaskAdd(wxCommandEvent &e)
00424 {
00425     if(GetImgNr()<UINT_MAX)
00426     {
00427         //deselect current selected mask
00428         if(m_MaskNr<UINT_MAX)
00429             m_maskList->SetItemState(m_MaskNr,0,wxLIST_STATE_SELECTED);
00430         setMask(UINT_MAX);
00431         MainFrame::Get()->SetStatusText(_("Create a polygon mask by clicking with the left mouse button on image, set the last point with the right mouse button."),0);
00432         m_editImg->startNewPolygon();
00433     };
00434 };
00435 
00436 void MaskEditorPanel::OnMaskSave(wxCommandEvent &e)
00437 {
00438     if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
00439     {
00440         wxFileDialog dlg(this, _("Save mask"),
00441                 wxConfigBase::Get()->Read(wxT("/actualPath"), wxT("")),
00442                 wxT(""), _("Mask files (*.msk)|*.msk|All files (*)|*"), 
00443                 wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
00444         if (dlg.ShowModal() == wxID_OK) 
00445         {
00446             wxString fn = dlg.GetPath();
00447             if (fn.Right(4) != wxT(".msk"))
00448             {
00449                 fn.Append(wxT(".msk"));
00450                 if (wxFile::Exists(fn))
00451                 {
00452                     int d = wxMessageBox(wxString::Format(_("File %s exists. Overwrite?"),
00453                         fn.c_str()), _("Save mask"),
00454                         wxYES_NO | wxICON_QUESTION);
00455                     if (d != wxYES) {
00456                         return;
00457                     }
00458                 }
00459             };
00460             wxFileName filename = fn;
00461             std::ofstream maskFile(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
00462             SaveMaskToStream(maskFile, m_pano->getImage(GetImgNr()).getSize(), m_currentMasks[m_MaskNr], GetImgNr());
00463             maskFile.close();
00464         };
00465     }
00466 };
00467 
00468 void MaskEditorPanel::OnMaskLoad(wxCommandEvent &e)
00469 {
00470     if (GetImgNr()<UINT_MAX)
00471     {
00472         wxFileDialog dlg(this,_("Load mask"),
00473                 wxConfigBase::Get()->Read(wxT("/actualPath"),wxT("")),
00474                 wxT(""),_("Mask files (*.msk)|*.msk|All files (*)|*"),
00475                 wxFD_OPEN, wxDefaultPosition);
00476         if (dlg.ShowModal() != wxID_OK)
00477         {
00478             MainFrame::Get()->SetStatusText(_("Load mask: cancel"));
00479             return;
00480         }
00481         wxFileName filename(dlg.GetPath());
00482         std::ifstream in(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
00483         vigra::Size2D maskImageSize;
00484         HuginBase::MaskPolygonVector loadedMasks;
00485         LoadMaskFromStream(in, maskImageSize, loadedMasks, GetImgNr());
00486         in.close();
00487         if(maskImageSize.area()==0 || loadedMasks.size()==0)
00488         {
00489             wxMessageBox(wxString::Format(_("Could not parse mask from file %s."),dlg.GetPath().c_str()),_("Warning"),wxOK | wxICON_EXCLAMATION,this);
00490             return;
00491         };
00492         // compare image size from file with that of current image alert user
00493         // if different.
00494         if (maskImageSize != m_pano->getImage(GetImgNr()).getSize()) 
00495         {
00496             MaskLoadDialog dlg(this);
00497             dlg.initValues(m_pano->getImage(GetImgNr()),loadedMasks,maskImageSize);
00498             if(dlg.ShowModal()!=wxID_OK)
00499             {
00500                 // abort
00501                 return;
00502             }
00503             loadedMasks=dlg.getProcessedMask();
00504         }
00505         for(unsigned int i=0;i<loadedMasks.size();i++)
00506             m_currentMasks.push_back(loadedMasks[i]);
00507         // Update the pano with the imported masks
00508         PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::UpdateMaskForImgCmd(*m_pano, GetImgNr(), m_currentMasks));
00509     }
00510 };
00511 
00512 void MaskEditorPanel::OnMaskCopy(wxCommandEvent &e)
00513 {
00514     if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX && m_maskMode)
00515     {
00516         std::ostringstream stream;
00517         SaveMaskToStream(stream, m_pano->getImage(GetImgNr()).getSize(), m_currentMasks[m_MaskNr], GetImgNr());
00518         if (wxTheClipboard->Open())
00519         {
00520             // This data objects are held by the clipboard,
00521             // so do not delete them in the app.
00522             wxTheClipboard->SetData(new wxTextDataObject(wxString(stream.str().c_str(),wxConvLocal)));
00523             wxTheClipboard->Close();
00524         };
00525     };
00526 };
00527 
00528 void MaskEditorPanel::OnMaskPaste(wxCommandEvent &e)
00529 {
00530     if(GetImgNr()<UINT_MAX && m_maskMode)
00531     {
00532         if (wxTheClipboard->Open())
00533         {
00534             vigra::Size2D maskImageSize;
00535             HuginBase::MaskPolygonVector loadedMasks;
00536             if (wxTheClipboard->IsSupported( wxDF_TEXT ))
00537             {
00538                 wxTextDataObject data;
00539                 wxTheClipboard->GetData(data);
00540                 std::istringstream stream(std::string(data.GetText().mb_str()));
00541                 LoadMaskFromStream(stream, maskImageSize, loadedMasks, GetImgNr());
00542             }
00543             wxTheClipboard->Close();
00544             if(maskImageSize.area()==0 || loadedMasks.size()==0)
00545             {
00546                 wxBell();
00547                 return;
00548             };
00549             // compare image size from file with that of current image alert user
00550             // if different.
00551             if (maskImageSize != m_pano->getImage(GetImgNr()).getSize()) 
00552             {
00553                 MaskLoadDialog dlg(this);
00554                 dlg.initValues(m_pano->getImage(GetImgNr()),loadedMasks,maskImageSize);
00555                 if(dlg.ShowModal()!=wxID_OK)
00556                 {
00557                     // abort
00558                     return;
00559                 }
00560                 loadedMasks=dlg.getProcessedMask();
00561             }
00562             for(unsigned int i=0;i<loadedMasks.size();i++)
00563                 m_currentMasks.push_back(loadedMasks[i]);
00564             // Update the pano with the imported masks
00565             PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::UpdateMaskForImgCmd(*m_pano, GetImgNr(), m_currentMasks));
00566         };
00567     };
00568 };
00569 
00570 void MaskEditorPanel::OnMaskDelete(wxCommandEvent &e)
00571 {
00572     if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
00573     {
00574         HuginBase::MaskPolygonVector editedMasks=m_currentMasks;
00575         editedMasks.erase(editedMasks.begin()+m_MaskNr);
00576         //setMask(UINT_MAX);
00577         PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::UpdateMaskForImgCmd(*m_pano, GetImgNr(), editedMasks));
00578     };
00579 };
00580 
00581 void MaskEditorPanel::OnZoom(wxCommandEvent & e)
00582 {
00583     int posX = 0;
00584     int posY = 0;
00585     const wxSize ctrlSize = m_editImg->GetClientSize();
00586     if (m_editImg->getScale() > 0)
00587     {
00588         // remember old scroll position
00589         posX = (m_editImg->GetScrollPos(wxHORIZONTAL) + ctrlSize.GetWidth() / 2) / m_editImg->getScale();
00590         posY = (m_editImg->GetScrollPos(wxVERTICAL) + ctrlSize.GetHeight() / 2) / m_editImg->getScale();
00591     };
00592     double factor;
00593     switch (e.GetSelection()) 
00594     {
00595         case 0:
00596             factor = 1;
00597             break;
00598         case 1:
00599             // fit to window
00600             factor = 0;
00601             break;
00602         case 2:
00603             factor = 2;
00604             break;
00605         case 3:
00606             factor = 1.5;
00607             break;
00608         case 4:
00609             factor = 0.75;
00610             break;
00611         case 5:
00612             factor = 0.5;
00613             break;
00614         case 6:
00615             factor = 0.25;
00616             break;
00617         default:
00618             DEBUG_ERROR("unknown scale factor");
00619             factor = 1;
00620     }
00621     m_editImg->setScale(factor);
00622     if (factor > 0)
00623     {
00624         m_editImg->Scroll(posX*factor - ctrlSize.GetWidth() / 2, posY*factor - ctrlSize.GetHeight() / 2);
00625     };
00626 }
00627 
00628 void MaskEditorPanel::OnColourChanged(wxColourPickerEvent &e)
00629 {
00630     if(e.GetId()==XRCID("mask_editor_colour_polygon_negative"))
00631     {
00632         m_editImg->SetUserColourPolygonNegative(e.GetColour());
00633         wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ColourPolygonNegative"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
00634     }
00635     else 
00636         if(e.GetId()==XRCID("mask_editor_colour_polygon_positive"))
00637         {
00638             m_editImg->SetUserColourPolygonPositive(e.GetColour());
00639             wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ColourPolygonPositive"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
00640         }
00641         else
00642             if(e.GetId()==XRCID("mask_editor_colour_point_selected"))
00643             {
00644                 m_editImg->SetUserColourPointSelected(e.GetColour());
00645                 wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ColourPointSelected"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
00646             }
00647             else
00648             {
00649                 m_editImg->SetUserColourPointUnselected(e.GetColour());
00650                 wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ColourPointUnselected"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
00651             }
00652     m_editImg->Refresh(true);
00653 };
00654 
00655 void MaskEditorPanel::UpdateMaskList(bool restoreSelection)
00656 {
00657     unsigned int oldSelection=GetSelectedMask();
00658     m_maskList->Freeze();
00659     if(GetImgNr()<UINT_MAX)
00660     {
00661         if(m_currentMasks.size()>0)
00662         {
00663             if(m_maskList->GetItemCount()!=m_currentMasks.size())
00664             {
00665                 if(m_maskList->GetItemCount()<(int)m_currentMasks.size())
00666                 {
00667                     //added masks
00668                     for(int i=m_maskList->GetItemCount();i<(int)m_currentMasks.size();i++)
00669                         m_maskList->InsertItem(i,wxString::Format(wxT("%d"),i));
00670                 }
00671                 else
00672                 {
00673                     //deleted masks
00674                     for(int i=m_maskList->GetItemCount()-1;i>=(int)m_currentMasks.size();i--)
00675                         m_maskList->DeleteItem(i);
00676                 };
00677             };
00678             for(unsigned int i=0;i<m_currentMasks.size();i++)
00679             {
00680                 m_maskList->SetItem(i,1,m_maskType->GetString(m_currentMasks[i].getMaskType()));
00681                 if(!restoreSelection && i==oldSelection)
00682                     m_maskList->SetItemState(i,0, wxLIST_STATE_SELECTED);
00683             };
00684         }
00685         else
00686             m_maskList->DeleteAllItems();
00687     }
00688     else
00689         m_maskList->DeleteAllItems();
00690     m_maskList->Thaw();
00691     m_maskType->Enable(m_maskList->GetSelectedItemCount()>0);
00692 }
00693 
00694 unsigned int MaskEditorPanel::GetSelectedMask()
00695 {
00696     for(unsigned int i=0;i<(unsigned int)m_maskList->GetItemCount();i++)
00697     {
00698         if(m_maskList->GetItemState(i,wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
00699             return i;
00700     };
00701     return UINT_MAX;
00702 };
00703 
00704 void MaskEditorPanel::OnColumnWidthChange( wxListEvent & e )
00705 {
00706     int colNum = e.GetColumn();
00707     wxConfigBase::Get()->Write( wxString::Format(wxT("/MaskEditorPanel/ColumnWidth%d"),colNum), m_maskList->GetColumnWidth(colNum) );
00708 }
00709 
00710 MaskImageCtrl::ImageRotation MaskEditorPanel::GetRot(const unsigned int imgNr)
00711 {
00712     if(imgNr==UINT_MAX)
00713         return MaskImageCtrl::ROT0;
00714 
00715     double pitch=m_pano->getImage(imgNr).getPitch();
00716     double roll=m_pano->getImage(imgNr).getRoll();
00717     
00718     MaskImageCtrl::ImageRotation rot = MaskImageCtrl::ROT0;
00719     // normalize roll angle
00720     while (roll > 360) roll-= 360;
00721     while (roll < 0) roll += 360;
00722 
00723     while (pitch > 180) pitch -= 360;
00724     while (pitch < -180) pitch += 360;
00725     bool headOver = (pitch > 90 || pitch < -90);
00726 
00727     if (roll >= 315 || roll < 45) 
00728     {
00729         rot = headOver ? MaskImageCtrl::ROT180 : MaskImageCtrl::ROT0;
00730     } 
00731     else 
00732         if (roll >= 45 && roll < 135) 
00733         {
00734             rot = headOver ? MaskImageCtrl::ROT270 : MaskImageCtrl::ROT90;
00735         }
00736         else 
00737             if (roll >= 135 && roll < 225) 
00738             {
00739                 rot = headOver ? MaskImageCtrl::ROT0 : MaskImageCtrl::ROT180;
00740             } 
00741             else 
00742             {
00743                 rot = headOver ? MaskImageCtrl::ROT90 : MaskImageCtrl::ROT270;
00744             }
00745     return rot;
00746 }
00747 
00748 void MaskEditorPanel::OnShowActiveMasks(wxCommandEvent &e)
00749 {
00750     m_editImg->setDrawingActiveMasks(e.IsChecked());
00751 };
00752 
00753 void MaskEditorPanel::DisplayCrop(int imgNr)
00754 {
00755     const HuginBase::SrcPanoImage & img = m_pano->getImage(imgNr);
00756     m_cropMode=img.getCropMode();
00757     m_cropRect=img.getCropRect();
00758     m_autoCenterCrop=img.getAutoCenterCrop();
00759 
00760     int dx = hugin_utils::roundi(img.getRadialDistortionCenterShift().x);
00761     int dy = hugin_utils::roundi(img.getRadialDistortionCenterShift().y);
00763     m_cropCenter = vigra::Point2D(img.getSize().width()/2 + dx, img.getSize().height()/2 + dy);
00764 
00765     UpdateCropDisplay();
00766 }
00767 
00768 // transfer our state to panorama
00769 void MaskEditorPanel::UpdateCrop(bool updateFromImgCtrl)
00770 {
00771     // set crop image options.
00772     if(updateFromImgCtrl)
00773     {
00774         m_cropRect=m_editImg->getCrop();
00775     };
00776     std::vector<HuginBase::SrcPanoImage> imgs;
00777     for (HuginBase::UIntSet::iterator it = m_selectedImages.begin(); it != m_selectedImages.end(); ++it)
00778     {
00779         HuginBase::SrcPanoImage img=m_pano->getSrcImage(*it);
00780         img.setCropRect(m_cropRect);
00781         img.setAutoCenterCrop(m_autoCenterCrop);
00782         imgs.push_back(img);
00783     };
00784 
00785     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00786             new PanoCommand::UpdateSrcImagesCmd(*m_pano, m_selectedImages, imgs)
00787     );
00788 }
00789 
00790 void MaskEditorPanel::UpdateCropFromImage()
00791 {
00792     m_cropRect=m_editImg->getCrop();
00793     UpdateCropDisplay();
00794 };
00795 
00796 // redraw display with new information
00797 void MaskEditorPanel::UpdateCropDisplay()
00798 {
00799     DEBUG_TRACE("")
00800     m_autocenter_cb->SetValue(m_autoCenterCrop);
00801     m_left_textctrl->SetValue(wxString::Format(wxT("%d"),m_cropRect.left()));
00802     m_right_textctrl->SetValue(wxString::Format(wxT("%d"),m_cropRect.right()));
00803     m_top_textctrl->SetValue(wxString::Format(wxT("%d"),m_cropRect.top()));
00804     m_bottom_textctrl->SetValue(wxString::Format(wxT("%d"),m_cropRect.bottom()));
00805 }
00806 
00807 
00808 void MaskEditorPanel::OnSetTop(wxCommandEvent & e)
00809 {
00810     long val;
00811     if (m_top_textctrl->GetValue().ToLong(&val))
00812     {
00813         m_cropRect.setUpperLeft(vigra::Point2D(m_cropRect.left(), val));
00814         if (m_autoCenterCrop)
00815         {
00816             CenterCrop();
00817             UpdateCropDisplay();
00818         };
00819         UpdateCrop();
00820     }
00821     else
00822     {
00823         wxLogError(_("Please enter a valid number"));
00824     };
00825 };
00826 
00827 void MaskEditorPanel::OnSetBottom(wxCommandEvent & e)
00828 {
00829     long val;
00830     if (m_bottom_textctrl->GetValue().ToLong(&val))
00831     {
00832         m_cropRect.setLowerRight(vigra::Point2D(m_cropRect.right(), val));
00833         if (m_autoCenterCrop)
00834         {
00835             CenterCrop();
00836             UpdateCropDisplay();
00837         }
00838         UpdateCrop();
00839     }
00840     else
00841     {
00842         wxLogError(_("Please enter a valid number"));
00843     };
00844 };
00845 
00846 void MaskEditorPanel::OnSetLeft(wxCommandEvent & e)
00847 {
00848     long val = 0;
00849     if (m_left_textctrl->GetValue().ToLong(&val))
00850     {
00851         m_cropRect.setUpperLeft(vigra::Point2D(val, m_cropRect.top()));
00852         if (m_autoCenterCrop)
00853         {
00854             CenterCrop();
00855             UpdateCropDisplay();
00856         }
00857         UpdateCrop();
00858     }
00859     else
00860     {
00861         wxLogError(_("Please enter a valid number"));
00862     };
00863 };
00864 
00865 void MaskEditorPanel::OnSetRight(wxCommandEvent & e)
00866 {
00867     long val = 0;
00868     if (m_right_textctrl->GetValue().ToLong(&val))
00869     {
00870         m_cropRect.setLowerRight(vigra::Point2D(val, m_cropRect.bottom()));
00871         if (m_autoCenterCrop)
00872         {
00873             CenterCrop();
00874             UpdateCropDisplay();
00875         };
00876         UpdateCrop();
00877     }
00878     else
00879     {
00880         wxLogError(_("Please enter a valid number"));
00881     };
00882 };
00883 
00884 void MaskEditorPanel::OnResetButton(wxCommandEvent & e)
00885 {
00886     // suitable defaults.
00887     m_cropRect.setUpperLeft(vigra::Point2D(0,0));
00888     m_cropRect.setLowerRight(vigra::Point2D(0,0));
00889     m_autoCenterCrop = true;
00890     m_cropMode=HuginBase::SrcPanoImage::NO_CROP;
00891     UpdateCropDisplay();
00892     UpdateCrop();
00893 }
00894 
00895 void MaskEditorPanel::OnAutoCenter(wxCommandEvent & e)
00896 {
00897     m_autoCenterCrop = e.IsChecked();
00898     if (m_autoCenterCrop)
00899     {
00900         CenterCrop();
00901         UpdateCropDisplay();
00902     };
00903     UpdateCrop();
00904 }
00905 
00906 void MaskEditorPanel::CenterCrop()
00907 {
00908     vigra::Diff2D d(m_cropRect.width()/2, m_cropRect.height() / 2);
00909     m_cropRect.setUpperLeft( m_cropCenter - d);
00910     m_cropRect.setLowerRight( m_cropCenter + d);
00911 }
00912 
00913 void MaskEditorPanel::OnModeChanged(wxNotebookEvent& e)
00914 {
00915     if(m_maskCropCtrl==NULL)
00916     {
00917         return;
00918     };
00919     if(m_maskCropCtrl->GetSelection()==0)
00920     {
00921         m_maskMode=true;
00922         size_t imgNr=GetImgNr();
00923         m_selectedImages.clear();
00924         m_selectedImages.insert(imgNr);
00925         m_imagesListMask->SetSingleSelect(true);
00926         m_imagesListMask->SelectSingleImage(imgNr);
00927         m_editImg->SetMaskMode(true);
00928     }
00929     else
00930     {
00931         m_maskMode=false;
00932         m_imagesListMask->SetSingleSelect(false);
00933         m_editImg->SetMaskMode(false);
00934         SelectMask(UINT_MAX);
00935     };
00936     m_editImg->Refresh();
00937 };
00938 
00939 IMPLEMENT_DYNAMIC_CLASS(MaskEditorPanel, wxPanel)
00940 
00941 MaskEditorPanelXmlHandler::MaskEditorPanelXmlHandler()
00942                 : wxXmlResourceHandler()
00943 {
00944     AddWindowStyles();
00945 }
00946 
00947 wxObject *MaskEditorPanelXmlHandler::DoCreateResource()
00948 {
00949     XRC_MAKE_INSTANCE(cp, MaskEditorPanel)
00950 
00951     cp->Create(m_parentAsWindow,
00952                    GetID(),
00953                    GetPosition(), GetSize(),
00954                    GetStyle(wxT("style")),
00955                    GetName());
00956 
00957     SetupWindow(cp);
00958 
00959     return cp;
00960 }
00961 
00962 bool MaskEditorPanelXmlHandler::CanHandle(wxXmlNode *node)
00963 {
00964     return IsOfClass(node, wxT("MaskEditorPanel"));
00965 }
00966 
00967 IMPLEMENT_DYNAMIC_CLASS(MaskEditorPanelXmlHandler, wxXmlResourceHandler)

Generated on 6 Feb 2016 for Hugintrunk by  doxygen 1.4.7