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     double factor;
00584     switch (e.GetSelection()) 
00585     {
00586         case 0:
00587             factor = 1;
00588             break;
00589         case 1:
00590             // fit to window
00591             factor = 0;
00592             break;
00593         case 2:
00594             factor = 2;
00595             break;
00596         case 3:
00597             factor = 1.5;
00598             break;
00599         case 4:
00600             factor = 0.75;
00601             break;
00602         case 5:
00603             factor = 0.5;
00604             break;
00605         case 6:
00606             factor = 0.25;
00607             break;
00608         default:
00609             DEBUG_ERROR("unknown scale factor");
00610             factor = 1;
00611     }
00612     m_editImg->setScale(factor);
00613 }
00614 
00615 void MaskEditorPanel::OnColourChanged(wxColourPickerEvent &e)
00616 {
00617     if(e.GetId()==XRCID("mask_editor_colour_polygon_negative"))
00618     {
00619         m_editImg->SetUserColourPolygonNegative(e.GetColour());
00620         wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ColourPolygonNegative"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
00621     }
00622     else 
00623         if(e.GetId()==XRCID("mask_editor_colour_polygon_positive"))
00624         {
00625             m_editImg->SetUserColourPolygonPositive(e.GetColour());
00626             wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ColourPolygonPositive"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
00627         }
00628         else
00629             if(e.GetId()==XRCID("mask_editor_colour_point_selected"))
00630             {
00631                 m_editImg->SetUserColourPointSelected(e.GetColour());
00632                 wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ColourPointSelected"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
00633             }
00634             else
00635             {
00636                 m_editImg->SetUserColourPointUnselected(e.GetColour());
00637                 wxConfigBase::Get()->Write(wxT("/MaskEditorPanel/ColourPointUnselected"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
00638             }
00639     m_editImg->Refresh(true);
00640 };
00641 
00642 void MaskEditorPanel::UpdateMaskList(bool restoreSelection)
00643 {
00644     unsigned int oldSelection=GetSelectedMask();
00645     m_maskList->Freeze();
00646     if(GetImgNr()<UINT_MAX)
00647     {
00648         if(m_currentMasks.size()>0)
00649         {
00650             if(m_maskList->GetItemCount()!=m_currentMasks.size())
00651             {
00652                 if(m_maskList->GetItemCount()<(int)m_currentMasks.size())
00653                 {
00654                     //added masks
00655                     for(int i=m_maskList->GetItemCount();i<(int)m_currentMasks.size();i++)
00656                         m_maskList->InsertItem(i,wxString::Format(wxT("%d"),i));
00657                 }
00658                 else
00659                 {
00660                     //deleted masks
00661                     for(int i=m_maskList->GetItemCount()-1;i>=(int)m_currentMasks.size();i--)
00662                         m_maskList->DeleteItem(i);
00663                 };
00664             };
00665             for(unsigned int i=0;i<m_currentMasks.size();i++)
00666             {
00667                 m_maskList->SetItem(i,1,m_maskType->GetString(m_currentMasks[i].getMaskType()));
00668                 if(!restoreSelection && i==oldSelection)
00669                     m_maskList->SetItemState(i,0, wxLIST_STATE_SELECTED);
00670             };
00671         }
00672         else
00673             m_maskList->DeleteAllItems();
00674     }
00675     else
00676         m_maskList->DeleteAllItems();
00677     m_maskList->Thaw();
00678     m_maskType->Enable(m_maskList->GetSelectedItemCount()>0);
00679 }
00680 
00681 unsigned int MaskEditorPanel::GetSelectedMask()
00682 {
00683     for(unsigned int i=0;i<(unsigned int)m_maskList->GetItemCount();i++)
00684     {
00685         if(m_maskList->GetItemState(i,wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
00686             return i;
00687     };
00688     return UINT_MAX;
00689 };
00690 
00691 void MaskEditorPanel::OnColumnWidthChange( wxListEvent & e )
00692 {
00693     int colNum = e.GetColumn();
00694     wxConfigBase::Get()->Write( wxString::Format(wxT("/MaskEditorPanel/ColumnWidth%d"),colNum), m_maskList->GetColumnWidth(colNum) );
00695 }
00696 
00697 MaskImageCtrl::ImageRotation MaskEditorPanel::GetRot(const unsigned int imgNr)
00698 {
00699     if(imgNr==UINT_MAX)
00700         return MaskImageCtrl::ROT0;
00701 
00702     double pitch=m_pano->getImage(imgNr).getPitch();
00703     double roll=m_pano->getImage(imgNr).getRoll();
00704     
00705     MaskImageCtrl::ImageRotation rot = MaskImageCtrl::ROT0;
00706     // normalize roll angle
00707     while (roll > 360) roll-= 360;
00708     while (roll < 0) roll += 360;
00709 
00710     while (pitch > 180) pitch -= 360;
00711     while (pitch < -180) pitch += 360;
00712     bool headOver = (pitch > 90 || pitch < -90);
00713 
00714     if (roll >= 315 || roll < 45) 
00715     {
00716         rot = headOver ? MaskImageCtrl::ROT180 : MaskImageCtrl::ROT0;
00717     } 
00718     else 
00719         if (roll >= 45 && roll < 135) 
00720         {
00721             rot = headOver ? MaskImageCtrl::ROT270 : MaskImageCtrl::ROT90;
00722         }
00723         else 
00724             if (roll >= 135 && roll < 225) 
00725             {
00726                 rot = headOver ? MaskImageCtrl::ROT0 : MaskImageCtrl::ROT180;
00727             } 
00728             else 
00729             {
00730                 rot = headOver ? MaskImageCtrl::ROT90 : MaskImageCtrl::ROT270;
00731             }
00732     return rot;
00733 }
00734 
00735 void MaskEditorPanel::OnShowActiveMasks(wxCommandEvent &e)
00736 {
00737     m_editImg->setDrawingActiveMasks(e.IsChecked());
00738 };
00739 
00740 void MaskEditorPanel::DisplayCrop(int imgNr)
00741 {
00742     const HuginBase::SrcPanoImage & img = m_pano->getImage(imgNr);
00743     m_cropMode=img.getCropMode();
00744     m_cropRect=img.getCropRect();
00745     m_autoCenterCrop=img.getAutoCenterCrop();
00746 
00747     int dx = hugin_utils::roundi(img.getRadialDistortionCenterShift().x);
00748     int dy = hugin_utils::roundi(img.getRadialDistortionCenterShift().y);
00750     m_cropCenter = vigra::Point2D(img.getSize().width()/2 + dx, img.getSize().height()/2 + dy);
00751 
00752     UpdateCropDisplay();
00753 }
00754 
00755 // transfer our state to panorama
00756 void MaskEditorPanel::UpdateCrop(bool updateFromImgCtrl)
00757 {
00758     // set crop image options.
00759     if(updateFromImgCtrl)
00760     {
00761         m_cropRect=m_editImg->getCrop();
00762     };
00763     vector<HuginBase::SrcPanoImage> imgs;
00764     for (HuginBase::UIntSet::iterator it = m_selectedImages.begin(); it != m_selectedImages.end(); ++it)
00765     {
00766         HuginBase::SrcPanoImage img=m_pano->getSrcImage(*it);
00767         img.setCropRect(m_cropRect);
00768         img.setAutoCenterCrop(m_autoCenterCrop);
00769         imgs.push_back(img);
00770     };
00771 
00772     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00773             new PanoCommand::UpdateSrcImagesCmd(*m_pano, m_selectedImages, imgs)
00774     );
00775 }
00776 
00777 void MaskEditorPanel::UpdateCropFromImage()
00778 {
00779     m_cropRect=m_editImg->getCrop();
00780     UpdateCropDisplay();
00781 };
00782 
00783 // redraw display with new information
00784 void MaskEditorPanel::UpdateCropDisplay()
00785 {
00786     DEBUG_TRACE("")
00787     m_autocenter_cb->SetValue(m_autoCenterCrop);
00788     m_left_textctrl->SetValue(wxString::Format(wxT("%d"),m_cropRect.left()));
00789     m_right_textctrl->SetValue(wxString::Format(wxT("%d"),m_cropRect.right()));
00790     m_top_textctrl->SetValue(wxString::Format(wxT("%d"),m_cropRect.top()));
00791     m_bottom_textctrl->SetValue(wxString::Format(wxT("%d"),m_cropRect.bottom()));
00792 }
00793 
00794 
00795 void MaskEditorPanel::OnSetTop(wxCommandEvent & e)
00796 {
00797     long val;
00798     if (m_top_textctrl->GetValue().ToLong(&val))
00799     {
00800         m_cropRect.setUpperLeft(vigra::Point2D(m_cropRect.left(), val));
00801         if (m_autoCenterCrop)
00802         {
00803             CenterCrop();
00804             UpdateCropDisplay();
00805         };
00806         UpdateCrop();
00807     }
00808     else
00809     {
00810         wxLogError(_("Please enter a valid number"));
00811     };
00812 };
00813 
00814 void MaskEditorPanel::OnSetBottom(wxCommandEvent & e)
00815 {
00816     long val;
00817     if (m_bottom_textctrl->GetValue().ToLong(&val))
00818     {
00819         m_cropRect.setLowerRight(vigra::Point2D(m_cropRect.right(), val));
00820         if (m_autoCenterCrop)
00821         {
00822             CenterCrop();
00823             UpdateCropDisplay();
00824         }
00825         UpdateCrop();
00826     }
00827     else
00828     {
00829         wxLogError(_("Please enter a valid number"));
00830     };
00831 };
00832 
00833 void MaskEditorPanel::OnSetLeft(wxCommandEvent & e)
00834 {
00835     long val = 0;
00836     if (m_left_textctrl->GetValue().ToLong(&val))
00837     {
00838         m_cropRect.setUpperLeft(vigra::Point2D(val, m_cropRect.top()));
00839         if (m_autoCenterCrop)
00840         {
00841             CenterCrop();
00842             UpdateCropDisplay();
00843         }
00844         UpdateCrop();
00845     }
00846     else
00847     {
00848         wxLogError(_("Please enter a valid number"));
00849     };
00850 };
00851 
00852 void MaskEditorPanel::OnSetRight(wxCommandEvent & e)
00853 {
00854     long val = 0;
00855     if (m_right_textctrl->GetValue().ToLong(&val))
00856     {
00857         m_cropRect.setLowerRight(vigra::Point2D(val, m_cropRect.bottom()));
00858         if (m_autoCenterCrop)
00859         {
00860             CenterCrop();
00861             UpdateCropDisplay();
00862         };
00863         UpdateCrop();
00864     }
00865     else
00866     {
00867         wxLogError(_("Please enter a valid number"));
00868     };
00869 };
00870 
00871 void MaskEditorPanel::OnResetButton(wxCommandEvent & e)
00872 {
00873     // suitable defaults.
00874     m_cropRect.setUpperLeft(vigra::Point2D(0,0));
00875     m_cropRect.setLowerRight(vigra::Point2D(0,0));
00876     m_autoCenterCrop = true;
00877     m_cropMode=HuginBase::SrcPanoImage::NO_CROP;
00878     UpdateCropDisplay();
00879     UpdateCrop();
00880 }
00881 
00882 void MaskEditorPanel::OnAutoCenter(wxCommandEvent & e)
00883 {
00884     m_autoCenterCrop = e.IsChecked();
00885     if (m_autoCenterCrop)
00886     {
00887         CenterCrop();
00888         UpdateCropDisplay();
00889     };
00890     UpdateCrop();
00891 }
00892 
00893 void MaskEditorPanel::CenterCrop()
00894 {
00895     vigra::Diff2D d(m_cropRect.width()/2, m_cropRect.height() / 2);
00896     m_cropRect.setUpperLeft( m_cropCenter - d);
00897     m_cropRect.setLowerRight( m_cropCenter + d);
00898 }
00899 
00900 void MaskEditorPanel::OnModeChanged(wxNotebookEvent& e)
00901 {
00902     if(m_maskCropCtrl==NULL)
00903     {
00904         return;
00905     };
00906     if(m_maskCropCtrl->GetSelection()==0)
00907     {
00908         m_maskMode=true;
00909         size_t imgNr=GetImgNr();
00910         m_selectedImages.clear();
00911         m_selectedImages.insert(imgNr);
00912         m_imagesListMask->SetSingleSelect(true);
00913         m_imagesListMask->SelectSingleImage(imgNr);
00914         m_editImg->SetMaskMode(true);
00915     }
00916     else
00917     {
00918         m_maskMode=false;
00919         m_imagesListMask->SetSingleSelect(false);
00920         m_editImg->SetMaskMode(false);
00921         SelectMask(UINT_MAX);
00922     };
00923     m_editImg->Refresh();
00924 };
00925 
00926 IMPLEMENT_DYNAMIC_CLASS(MaskEditorPanel, wxPanel)
00927 
00928 MaskEditorPanelXmlHandler::MaskEditorPanelXmlHandler()
00929                 : wxXmlResourceHandler()
00930 {
00931     AddWindowStyles();
00932 }
00933 
00934 wxObject *MaskEditorPanelXmlHandler::DoCreateResource()
00935 {
00936     XRC_MAKE_INSTANCE(cp, MaskEditorPanel)
00937 
00938     cp->Create(m_parentAsWindow,
00939                    GetID(),
00940                    GetPosition(), GetSize(),
00941                    GetStyle(wxT("style")),
00942                    GetName());
00943 
00944     SetupWindow(cp);
00945 
00946     return cp;
00947 }
00948 
00949 bool MaskEditorPanelXmlHandler::CanHandle(wxXmlNode *node)
00950 {
00951     return IsOfClass(node, wxT("MaskEditorPanel"));
00952 }
00953 
00954 IMPLEMENT_DYNAMIC_CLASS(MaskEditorPanelXmlHandler, wxXmlResourceHandler)

Generated on 3 Aug 2015 for Hugintrunk by  doxygen 1.4.7