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