Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MaskEditorPanel.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /* This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This software is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public
22  * License along with this software. If not, see
23  * <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #include "panoinc_WX.h"
28 #include "panoinc.h"
29 #include <hugin_utils/stl_utils.h>
30 
31 // hugin's
32 #include "base_wx/platform.h"
33 #include "hugin/MainFrame.h"
34 #include "hugin/config_defaults.h"
35 #include "base_wx/CommandHistory.h"
36 #include "base_wx/PanoCommand.h"
37 #include "hugin/MaskEditorPanel.h"
38 #include "hugin/MaskLoadDialog.h"
39 #include <wx/clipbrd.h>
41 #include "base_wx/wxutils.h"
42 
44 {
45  DEBUG_TRACE("**********************");
46  m_pano = 0;
47  m_maskCropCtrl=NULL;
49 }
50 
51 bool MaskEditorPanel::Create(wxWindow* parent, wxWindowID id,
52  const wxPoint& pos,
53  const wxSize& size,
54  long style,
55  const wxString& name)
56 {
57  DEBUG_TRACE(" Create called *************");
58  if (! wxPanel::Create(parent, id, pos, size, style, name))
59  {
60  return false;
61  }
62 
63  m_MaskNr=UINT_MAX;
64  m_File="";
65 
66  wxXmlResource::Get()->LoadPanel(this, "mask_panel");
67  wxPanel * panel = XRCCTRL(*this, "mask_panel", wxPanel);
68 
69  wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
70  topsizer->Add(panel, 1, wxEXPAND, 0);
71  SetSizer(topsizer);
72 
73  m_editImg = XRCCTRL(*this, "mask_editor_polygon_editor", MaskImageCtrl);
74  assert(m_editImg);
75  m_editImg->Init(this);
76 
77  // images list
78  m_imagesListMask = XRCCTRL(*this, "mask_editor_images_list", wxListCtrl);
79  m_imagesListMask->InsertColumn(0, "#", wxLIST_FORMAT_RIGHT, 35);
80  m_imagesListMask->InsertColumn(1, _("Filename"), wxLIST_FORMAT_LEFT, 200);
81  m_imagesListMask->InsertColumn(2, _("Number of masks"), wxLIST_FORMAT_RIGHT, 120);
82  m_imagesListMask->InsertColumn(3, _("Crop"), wxLIST_FORMAT_RIGHT, 120);
83  m_imagesListMask->Bind(wxEVT_LIST_ITEM_SELECTED, &MaskEditorPanel::OnImageSelect, this);
84  m_imagesListMask->Bind(wxEVT_LIST_ITEM_DESELECTED, &MaskEditorPanel::OnImageSelect, this);
85  m_imagesListMask->Bind(wxEVT_LIST_COL_END_DRAG, &MaskEditorPanel::OnImagesColumnWidthChange, this);
86  m_imagesListMask->Bind(wxEVT_CHAR, &MaskEditorPanel::OnImageListChar, this);
87 
88  //get saved width
89  wxConfigBase* config = wxConfigBase::Get();
90  for (int j = 0; j < m_imagesListMask->GetColumnCount(); j++)
91  {
92  // -1 is auto
93  int width = config->Read(wxString::Format("/ImagesListMask/ColumnWidth%d", j), -1);
94  if (width != -1)
95  {
96  m_imagesListMask->SetColumnWidth(j, width);
97  }
98  }
99  // mask list
100  m_maskList = XRCCTRL(*this, "mask_editor_mask_list", wxListCtrl);
101  m_maskList->InsertColumn( 0, "#", wxLIST_FORMAT_RIGHT, 35);
102  m_maskList->InsertColumn( 1, _("Mask type"), wxLIST_FORMAT_LEFT, 120);
103  m_maskList->Bind(wxEVT_LIST_ITEM_SELECTED, &MaskEditorPanel::OnMaskSelect, this);
104  m_maskList->Bind(wxEVT_LIST_ITEM_DESELECTED, &MaskEditorPanel::OnMaskSelect, this);
105  m_maskList->Bind(wxEVT_LIST_COL_END_DRAG, &MaskEditorPanel::OnMaskColumnWidthChange, this);
106 
107  m_maskCropCtrl = XRCCTRL(*this, "mask_editor_mask_crop_notebook", wxNotebook);
109  m_maskCropCtrl->SetSelection(0);
110  m_maskCropCtrl->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, &MaskEditorPanel::OnModeChanged, this);
111  m_maskMode=true;
112 
113  //get saved width
114  for ( int j=0; j < m_maskList->GetColumnCount() ; j++ )
115  {
116  // -1 is auto
117  int width = config->Read(wxString::Format( "/MaskEditorPanel/ColumnWidth%d", j ), -1);
118  if(width != -1)
119  m_maskList->SetColumnWidth(j, width);
120  }
121  bool activeMasks;
122  config->Read("/MaskEditorPanel/ShowActiveMasks",&activeMasks,false);
123  XRCCTRL(*this,"mask_editor_show_active_masks",wxCheckBox)->SetValue(activeMasks);
124  m_editImg->setDrawingActiveMasks(activeMasks);
125 
126  //load and set colours
127  wxColour defaultColour;
128  defaultColour.Set(HUGIN_MASK_COLOUR_POLYGON_NEGATIVE);
129  wxColour colour = config->Read("/MaskEditorPanel/ColourPolygonNegative", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
130  XRCCTRL(*this,"mask_editor_colour_polygon_negative",wxColourPickerCtrl)->SetColour(colour);
132  defaultColour.Set(HUGIN_MASK_COLOUR_POLYGON_POSITIVE);
133  colour = config->Read("/MaskEditorPanel/ColourPolygonPositive", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
134  XRCCTRL(*this,"mask_editor_colour_polygon_positive",wxColourPickerCtrl)->SetColour(colour);
136  defaultColour.Set(HUGIN_MASK_COLOUR_POINT_SELECTED);
137  colour = config->Read("/MaskEditorPanel/ColourPointSelected", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
138  XRCCTRL(*this,"mask_editor_colour_point_selected",wxColourPickerCtrl)->SetColour(colour);
140  defaultColour.Set(HUGIN_MASK_COLOUR_POINT_UNSELECTED);
141  colour = config->Read("/MaskEditorPanel/ColourPointUnselected", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
142  XRCCTRL(*this,"mask_editor_colour_point_unselected",wxColourPickerCtrl)->SetColour(colour);
144  Bind(wxEVT_COLOURPICKER_CHANGED, &MaskEditorPanel::OnColourChanged, this);
145 
146  // other controls
147  m_maskType = XRCCTRL(*this, "mask_editor_choice_masktype", wxChoice);
148  m_defaultMaskType=(HuginBase::MaskPolygon::MaskType)config->Read("/MaskEditorPanel/DefaultMaskType", 0l);
149  m_maskType->SetSelection((int)m_defaultMaskType);
150  m_maskType->Bind(wxEVT_CHOICE, &MaskEditorPanel::OnMaskTypeChange, this);
151  // disable some controls
152  m_maskType->Disable();
153  XRCCTRL(*this, "mask_editor_choice_zoom", wxChoice)->Disable();
154  XRCCTRL(*this, "mask_editor_add", wxButton)->Disable();
155  XRCCTRL(*this, "mask_editor_load", wxButton)->Disable();
156  XRCCTRL(*this, "mask_editor_save", wxButton)->Disable();
157  XRCCTRL(*this, "mask_editor_copy", wxButton)->Disable();
158  XRCCTRL(*this, "mask_editor_paste", wxButton)->Disable();
159  XRCCTRL(*this, "mask_editor_delete", wxButton)->Disable();
160 
161  m_left_textctrl = XRCCTRL(*this,"crop_left_text", wxTextCtrl);
163  m_left_textctrl->PushEventHandler(new TextKillFocusHandler(this));
164  m_left_textctrl->Bind(wxEVT_TEXT_ENTER, &MaskEditorPanel::OnSetLeft, this);
165 
166  m_cropLens = XRCCTRL(*this, "crop_all_images_lens", wxCheckBox);
168  bool doCropImagesLens;
169  config->Read("/MaskEditorPanel/CropImagesLens", &doCropImagesLens, true);
170  m_cropLens->SetValue(doCropImagesLens);
171  m_top_textctrl = XRCCTRL(*this,"crop_top_text", wxTextCtrl);
173  m_top_textctrl->PushEventHandler(new TextKillFocusHandler(this));
174  m_top_textctrl->Bind(wxEVT_TEXT_ENTER, &MaskEditorPanel::OnSetTop, this);
175 
176  m_right_textctrl = XRCCTRL(*this,"crop_right_text", wxTextCtrl);
178  m_right_textctrl->PushEventHandler(new TextKillFocusHandler(this));
179  m_right_textctrl->Bind(wxEVT_TEXT_ENTER, &MaskEditorPanel::OnSetRight, this);
180 
181  m_bottom_textctrl = XRCCTRL(*this,"crop_bottom_text", wxTextCtrl);
183  m_bottom_textctrl->PushEventHandler(new TextKillFocusHandler(this));
184  m_bottom_textctrl->Bind(wxEVT_TEXT_ENTER, &MaskEditorPanel::OnSetBottom, this);
185 
186 
187  m_autocenter_cb = XRCCTRL(*this,"crop_autocenter_cb", wxCheckBox);
189  m_autocenter_cb->Bind(wxEVT_CHECKBOX, &MaskEditorPanel::OnAutoCenter, this);
190 
191  //set shortcuts
192  wxAcceleratorEntry entries[2];
193  entries[0].Set(wxACCEL_CMD,(int)'C',XRCID("mask_editor_copy"));
194  entries[1].Set(wxACCEL_CMD,(int)'V',XRCID("mask_editor_paste"));
195  wxAcceleratorTable accel(2, entries);
196  SetAcceleratorTable(accel);
197 
198  // apply zoom specified in xrc file
199  wxCommandEvent dummy;
200  dummy.SetInt(XRCCTRL(*this,"mask_editor_choice_zoom",wxChoice)->GetSelection());
201  OnZoom(dummy);
202  // bind remaining event handler
203  Bind(wxEVT_CHOICE, &MaskEditorPanel::OnZoom, this);
204  Bind(wxEVT_BUTTON, &MaskEditorPanel::OnMaskAdd, this, XRCID("mask_editor_add"));
205  Bind(wxEVT_BUTTON, &MaskEditorPanel::OnMaskLoad, this, XRCID("mask_editor_load"));
206  Bind(wxEVT_BUTTON, &MaskEditorPanel::OnMaskSave, this, XRCID("mask_editor_save"));
207  Bind(wxEVT_BUTTON, &MaskEditorPanel::OnMaskCopy, this, XRCID("mask_editor_copy"));
208  Bind(wxEVT_BUTTON, &MaskEditorPanel::OnMaskPaste, this, XRCID("mask_editor_paste"));
209  Bind(wxEVT_BUTTON, &MaskEditorPanel::OnMaskDelete, this, XRCID("mask_editor_delete"));
210  Bind(wxEVT_CHECKBOX, &MaskEditorPanel::OnShowActiveMasks, this, XRCID("mask_editor_show_active_masks"));
211  Bind(wxEVT_BUTTON, &MaskEditorPanel::OnResetButton, this, XRCID("crop_reset_button"));
212  return true;
213 }
214 
216 {
217  m_pano=pano;
219  // observe the panorama
220  m_pano->addObserver(this);
221 }
222 
224 {
225  m_left_textctrl->PopEventHandler(true);
226  m_right_textctrl->PopEventHandler(true);
227  m_top_textctrl->PopEventHandler(true);
228  m_bottom_textctrl->PopEventHandler(true);
229  wxConfigBase* config = wxConfigBase::Get();
230  config->Write("/MaskEditorPanel/ShowActiveMasks",XRCCTRL(*this,"mask_editor_show_active_masks",wxCheckBox)->GetValue());
231  config->Write("/MaskEditorPanel/DefaultMaskType",(long)m_defaultMaskType);
232  config->Write("/MaskEditorPanel/CropImagesLens", m_cropLens->GetValue());
233  config->Flush();
234 
235  DEBUG_TRACE("dtor");
236  if (m_imageGroups)
237  {
238  delete m_imageGroups;
239  }
240  m_pano->removeObserver(this);
241 }
242 
244 {
245  if(m_imagesListMask->GetSelectedItemCount()==0)
246  {
247  return UINT_MAX;
248  }
249  else
250  {
251  return *(GetSelectedImages().begin());
252  };
253 };
254 
255 void SelectSingleImage(wxListCtrl* list, unsigned int imgNr)
256 {
257  unsigned int nrItems = list->GetItemCount();
258  // remove potentially existing selection
259  for (unsigned int i = 0; i < nrItems; i++)
260  {
261  if (i == imgNr)
262  {
263  continue;
264  };
265  list->SetItemState(i, 0, wxLIST_STATE_SELECTED);
266  }
267  list->SetItemState(imgNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
268 }
269 
270 void MaskEditorPanel::setImage(unsigned int imgNr, bool updateListSelection)
271 {
272  DEBUG_TRACE("image " << imgNr);
273  bool restoreMaskSelection=(imgNr==GetImgNr());
274  bool updateImage=true;
275  HuginBase::MaskPolygonVector masksToDraw;
276  if (imgNr == UINT_MAX)
277  {
278  m_File = "";
280  m_currentMasks=mask;
281  m_editImg->setCrop(HuginBase::SrcPanoImage::NO_CROP,vigra::Rect2D(), false, hugin_utils::FDiff2D(), false);
282  }
283  else
284  {
285  const HuginBase::SrcPanoImage& image=m_pano->getImage(imgNr);
286  updateImage=(m_File!=image.getFilename());
287  if(updateImage)
288  m_File=image.getFilename();
289  else
290  if(GetRot(imgNr)!=m_editImg->getCurrentRotation())
291  {
292  updateImage=true;
293  m_File=image.getFilename();
294  };
295  m_currentMasks=image.getMasks();
296  masksToDraw=image.getActiveMasks();
297  m_editImg->setCrop(image.getCropMode(),image.getCropRect(), image.getAutoCenterCrop(), image.getRadialDistortionCenter(), image.isCircularCrop());
298  };
299  // update mask editor
300  if(updateImage)
301  m_editImg->setImage(m_File,m_currentMasks,masksToDraw,GetRot(imgNr));
302  else
303  m_editImg->setNewMasks(m_currentMasks,masksToDraw);
304  if (m_currentMasks.empty() || m_MaskNr >= m_currentMasks.size())
305  setMask(UINT_MAX);
306  // enables or disables controls
307  bool enableCtrl=(imgNr<UINT_MAX);
308  XRCCTRL(*this, "mask_editor_choice_zoom", wxChoice)->Enable(enableCtrl);
309  XRCCTRL(*this, "mask_editor_add", wxButton)->Enable(enableCtrl);
310  XRCCTRL(*this, "mask_editor_delete", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
311  XRCCTRL(*this, "mask_editor_load", wxButton)->Enable(enableCtrl);
312  XRCCTRL(*this, "mask_editor_save", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
313  XRCCTRL(*this, "mask_editor_paste", wxButton)->Enable(enableCtrl);
314  XRCCTRL(*this, "mask_editor_copy", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
315  UpdateMaskList(restoreMaskSelection);
316  // FIXME: lets hope that nobody holds references to these images..
317  ImageCache::getInstance().softFlush();
318  if(updateListSelection)
319  {
321  m_imagesListMask->EnsureVisible(imgNr);
322  };
323 }
324 
325 void MaskEditorPanel::setMask(unsigned int maskNr)
326 {
327  m_MaskNr=maskNr;
328  m_maskType->Enable(m_MaskNr<UINT_MAX);
330  XRCCTRL(*this,"mask_editor_delete", wxButton)->Enable(m_MaskNr<UINT_MAX);
331  XRCCTRL(*this, "mask_editor_save", wxButton)->Enable(m_MaskNr<UINT_MAX);
332  XRCCTRL(*this, "mask_editor_copy", wxButton)->Enable(m_MaskNr<UINT_MAX);
333  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
334  m_maskType->SetSelection(m_currentMasks[m_MaskNr].getMaskType());
335  else
336  m_maskType->SetSelection((int)m_defaultMaskType);
337 };
338 
340 {
341  if(GetImgNr()<UINT_MAX)
342  {
345  };
346 };
347 
349 {
350  if(GetImgNr()<UINT_MAX)
351  {
353  m_currentMasks[m_currentMasks.size()-1].setMaskType(m_defaultMaskType);
355  //select added mask
356  SelectMask(m_currentMasks.size()-1);
358  };
359 };
360 
361 void MaskEditorPanel::SelectMask(unsigned int newMaskNr)
362 {
363  if (GetImgNr() < UINT_MAX)
364  {
365  if (newMaskNr < m_currentMasks.size())
366  {
367  m_maskList->SetItemState(newMaskNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
368  }
369  else
370  {
371  if (m_MaskNr < UINT_MAX)
372  {
373  m_maskList->SetItemState(m_MaskNr, 0, wxLIST_STATE_SELECTED);
374  };
375  };
376  };
377 };
378 
380 {
381 };
382 
384 {
385  const HuginBase::SrcPanoImage& img = m_pano->getImage(imgNr);
386  wxFileName fn(wxString(img.getFilename().c_str(), HUGIN_CONV_FILENAME));
387  m_imagesListMask->SetItem(imgNr, 1, fn.GetFullName());
388 
389  wxString maskstr;
390  if (img.hasMasks())
391  {
392  maskstr = wxString::Format("%lu", (unsigned long int) m_pano->getImage(imgNr).getMasks().size());
393  }
394  else
395  {
396  maskstr = wxString("-");
397  };
398  m_imagesListMask->SetItem(imgNr, 2, maskstr);
399 
400  wxString cropstr("-");
401  if (img.getCropMode() != HuginBase::SrcPanoImage::NO_CROP)
402  {
403  vigra::Rect2D c = img.getCropRect();
404  cropstr.Printf("%d,%d,%d,%d", c.left(), c.right(), c.top(), c.bottom());
405  }
406  m_imagesListMask->SetItem(imgNr, 3, cropstr);
407 }
408 
410 {
411  const long nrImages = pano.getNrOfImages();
413  ImageCache::getInstance().softFlush();
415  {
416  m_imagesListMask->Freeze();
417  const size_t nrItems = m_imagesListMask->GetItemCount();
418  // remove items for nonexisting images
419  if (nrItems > nrImages)
420  {
421  for (long i = nrItems - 1; i >= nrImages; i--)
422  {
423  m_imagesListMask->DeleteItem(i);
424  }
425  }
426  // add newly added images
427  if (nrImages >= nrItems)
428  {
429  for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
430  {
431  if (*it >= nrItems)
432  {
433  m_imagesListMask->InsertItem(*it, wxString::Format("%d", *it));
434  }
435  }
436  }
437  // update existing items
438  for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
439  {
440  UpdateImage(*it);
441  }
442  m_imagesListMask->Thaw();
443  }
444 
445  if (nrImages == 0)
446  {
447  setImage(UINT_MAX);
448  }
449  else
450  {
451  // select some other image if we deleted the current image
452  if ((GetImgNr() < UINT_MAX) && (GetImgNr() >= nrImages))
453  {
454  setImage(nrImages - 1);
455  }
456  else
457  // update changed images
458  if(set_contains(changed,GetImgNr()))
459  {
460  unsigned int countOldMasks=m_currentMasks.size();
461  setImage(GetImgNr());
462  if(countOldMasks!=pano.getImage(GetImgNr()).getMasks().size())
463  SelectMask(UINT_MAX);
464  };
465  };
466 
467  if (m_imagesListMask->GetSelectedItemCount() > 0)
468  {
469  if (set_contains(changed, GetImgNr()))
470  {
472  }
473  }
474  else
475  {
477  }
478 
479 }
480 
482 {
483  // only for multi selection mode
484  if ((m_imagesListMask->GetWindowStyle() & wxLC_SINGLE_SEL) == 0)
485  {
486  // ctrl + a
487  if (e.GetKeyCode() == 1 && e.CmdDown())
488  {
489  // select all
490  for (int i = 0; i < m_imagesListMask->GetItemCount(); i++)
491  {
492  m_imagesListMask->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
493  }
494  }
495  }
496  e.Skip();
497 }
498 
499 void MaskEditorPanel::OnImageSelect(wxListEvent &e)
500 {
501  const HuginBase::UIntSet selectedImages=GetSelectedImages();
502  //select no mask
503  setMask(UINT_MAX);
504  setImage(GetImgNr());
505 
506  const bool hasImage = !selectedImages.empty();
507  m_left_textctrl->Enable(hasImage);
508  m_top_textctrl->Enable(hasImage);
509  m_bottom_textctrl->Enable(hasImage);
510  m_right_textctrl->Enable(hasImage);
511  if (hasImage)
512  {
513  // show first image.
515  };
516 };
517 
518 void MaskEditorPanel::OnMaskSelect(wxListEvent &e)
519 {
521 };
522 
523 void MaskEditorPanel::OnMaskTypeChange(wxCommandEvent &e)
524 {
525  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
526  {
527  m_currentMasks[m_MaskNr].setMaskType((HuginBase::MaskPolygon::MaskType)e.GetSelection());
530  };
531 };
532 
533 void MaskEditorPanel::OnMaskAdd(wxCommandEvent &e)
534 {
535  if(GetImgNr()<UINT_MAX)
536  {
537  //deselect current selected mask
538  if(m_MaskNr<UINT_MAX)
539  m_maskList->SetItemState(m_MaskNr,0,wxLIST_STATE_SELECTED);
540  setMask(UINT_MAX);
541  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);
543  };
544 };
545 
546 void MaskEditorPanel::OnMaskSave(wxCommandEvent &e)
547 {
548  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
549  {
550  wxFileDialog dlg(this, _("Save mask"),
551  wxConfigBase::Get()->Read("/actualPath", wxEmptyString),
552  wxEmptyString, _("Mask files (*.msk)|*.msk|All files (*)|*"),
553  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
554  if (dlg.ShowModal() == wxID_OK)
555  {
556  wxString fn = dlg.GetPath();
557  if (fn.Right(4) != ".msk")
558  {
559  fn.Append(".msk");
560  if (wxFile::Exists(fn))
561  {
562  if (!hugin_utils::AskUserOverwrite(fn, _("Hugin"), this))
563  {
564  return;
565  }
566  }
567  };
568  wxFileName filename = fn;
569  std::ofstream maskFile(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
571  maskFile.close();
572  };
573  }
574 };
575 
576 void MaskEditorPanel::OnMaskLoad(wxCommandEvent &e)
577 {
578  if (GetImgNr()<UINT_MAX)
579  {
580  wxFileDialog dlg(this,_("Load mask"),
581  wxConfigBase::Get()->Read("/actualPath",wxEmptyString),
582  wxEmptyString,_("Mask files (*.msk)|*.msk|All files (*)|*"),
583  wxFD_OPEN, wxDefaultPosition);
584  if (dlg.ShowModal() != wxID_OK)
585  {
586  MainFrame::Get()->SetStatusText(_("Load mask: cancel"));
587  return;
588  }
589  wxFileName filename(dlg.GetPath());
590  std::ifstream in(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
591  vigra::Size2D maskImageSize;
592  HuginBase::MaskPolygonVector loadedMasks;
593  LoadMaskFromStream(in, maskImageSize, loadedMasks, GetImgNr());
594  in.close();
595  if(maskImageSize.area()==0 || loadedMasks.empty())
596  {
597  hugin_utils::HuginMessageBox(wxString::Format(_("Could not parse mask from file %s."), dlg.GetPath()), _("Hugin"), wxOK | wxICON_EXCLAMATION, this);
598  return;
599  };
600  // compare image size from file with that of current image alert user
601  // if different.
602  if (maskImageSize != m_pano->getImage(GetImgNr()).getSize())
603  {
604  MaskLoadDialog dlg(this);
605  dlg.initValues(m_pano->getImage(GetImgNr()),loadedMasks,maskImageSize);
606  if(dlg.ShowModal()!=wxID_OK)
607  {
608  // abort
609  return;
610  }
611  loadedMasks=dlg.getProcessedMask();
612  }
613  for(unsigned int i=0;i<loadedMasks.size();i++)
614  m_currentMasks.push_back(loadedMasks[i]);
615  // Update the pano with the imported masks
617  }
618 };
619 
620 void MaskEditorPanel::OnMaskCopy(wxCommandEvent &e)
621 {
622  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX && m_maskMode)
623  {
624  std::ostringstream stream;
626  if (wxTheClipboard->Open())
627  {
628  // This data objects are held by the clipboard,
629  // so do not delete them in the app.
630  wxTheClipboard->SetData(new wxTextDataObject(wxString(stream.str().c_str(),wxConvLocal)));
631  wxTheClipboard->Close();
632  };
633  };
634 };
635 
636 void MaskEditorPanel::OnMaskPaste(wxCommandEvent &e)
637 {
638  if(GetImgNr()<UINT_MAX && m_maskMode)
639  {
640  if (wxTheClipboard->Open())
641  {
642  vigra::Size2D maskImageSize;
643  HuginBase::MaskPolygonVector loadedMasks;
644  if (wxTheClipboard->IsSupported( wxDF_TEXT ))
645  {
646  wxTextDataObject data;
647  wxTheClipboard->GetData(data);
648  std::istringstream stream(std::string(data.GetText().mb_str()));
649  LoadMaskFromStream(stream, maskImageSize, loadedMasks, GetImgNr());
650  }
651  wxTheClipboard->Close();
652  if(maskImageSize.area()==0 || loadedMasks.empty())
653  {
654  wxBell();
655  return;
656  };
657  // compare image size from file with that of current image alert user
658  // if different.
659  if (maskImageSize != m_pano->getImage(GetImgNr()).getSize())
660  {
661  MaskLoadDialog dlg(this);
662  dlg.initValues(m_pano->getImage(GetImgNr()),loadedMasks,maskImageSize);
663  if(dlg.ShowModal()!=wxID_OK)
664  {
665  // abort
666  return;
667  }
668  loadedMasks=dlg.getProcessedMask();
669  }
670  for(unsigned int i=0;i<loadedMasks.size();i++)
671  m_currentMasks.push_back(loadedMasks[i]);
672  // Update the pano with the imported masks
674  };
675  };
676 };
677 
678 void MaskEditorPanel::OnMaskDelete(wxCommandEvent &e)
679 {
680  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
681  {
683  editedMasks.erase(editedMasks.begin()+m_MaskNr);
684  //setMask(UINT_MAX);
686  };
687 };
688 
689 void MaskEditorPanel::OnZoom(wxCommandEvent & e)
690 {
691  int posX = 0;
692  int posY = 0;
693  const wxSize ctrlSize = m_editImg->GetClientSize();
694  if (m_editImg->getScale() > 0)
695  {
696  // remember old scroll position
697  posX = (m_editImg->GetScrollPos(wxHORIZONTAL) + ctrlSize.GetWidth() / 2) / m_editImg->getScale();
698  posY = (m_editImg->GetScrollPos(wxVERTICAL) + ctrlSize.GetHeight() / 2) / m_editImg->getScale();
699  };
700  double factor;
701  switch (e.GetSelection())
702  {
703  case 0:
704  factor = 1;
705  break;
706  case 1:
707  // fit to window
708  factor = 0;
709  break;
710  case 2:
711  factor = 2;
712  break;
713  case 3:
714  factor = 1.5;
715  break;
716  case 4:
717  factor = 0.75;
718  break;
719  case 5:
720  factor = 0.5;
721  break;
722  case 6:
723  factor = 0.25;
724  break;
725  default:
726  DEBUG_ERROR("unknown scale factor");
727  factor = 1;
728  }
729  m_editImg->setScale(factor);
730  if (factor > 0)
731  {
732  m_editImg->Scroll(posX*factor - ctrlSize.GetWidth() / 2, posY*factor - ctrlSize.GetHeight() / 2);
733  };
734  if (e.GetString() == "update_selection")
735  {
736  XRCCTRL(*this, "mask_editor_choice_zoom", wxChoice)->SetSelection(e.GetSelection());
737  };
738 }
739 
740 void MaskEditorPanel::OnColourChanged(wxColourPickerEvent &e)
741 {
742  if(e.GetId()==XRCID("mask_editor_colour_polygon_negative"))
743  {
744  m_editImg->SetUserColourPolygonNegative(e.GetColour());
745  wxConfigBase::Get()->Write("/MaskEditorPanel/ColourPolygonNegative",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
746  }
747  else
748  if(e.GetId()==XRCID("mask_editor_colour_polygon_positive"))
749  {
750  m_editImg->SetUserColourPolygonPositive(e.GetColour());
751  wxConfigBase::Get()->Write("/MaskEditorPanel/ColourPolygonPositive",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
752  }
753  else
754  if(e.GetId()==XRCID("mask_editor_colour_point_selected"))
755  {
756  m_editImg->SetUserColourPointSelected(e.GetColour());
757  wxConfigBase::Get()->Write("/MaskEditorPanel/ColourPointSelected",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
758  }
759  else
760  {
761  m_editImg->SetUserColourPointUnselected(e.GetColour());
762  wxConfigBase::Get()->Write("/MaskEditorPanel/ColourPointUnselected",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
763  }
764  m_editImg->Refresh(true);
765 };
766 
767 void MaskEditorPanel::UpdateMaskList(bool restoreSelection)
768 {
769  unsigned int oldSelection=GetSelectedMask();
770  m_maskList->Freeze();
771  if(GetImgNr()<UINT_MAX)
772  {
773  if(!m_currentMasks.empty())
774  {
775  if(m_maskList->GetItemCount()!=m_currentMasks.size())
776  {
777  if(m_maskList->GetItemCount()<(int)m_currentMasks.size())
778  {
779  //added masks
780  for(int i=m_maskList->GetItemCount();i<(int)m_currentMasks.size();i++)
781  m_maskList->InsertItem(i,wxString::Format("%d",i));
782  }
783  else
784  {
785  //deleted masks
786  for(int i=m_maskList->GetItemCount()-1;i>=(int)m_currentMasks.size();i--)
787  m_maskList->DeleteItem(i);
788  };
789  };
790  for(unsigned int i=0;i<m_currentMasks.size();i++)
791  {
792  m_maskList->SetItem(i,1,m_maskType->GetString(m_currentMasks[i].getMaskType()));
793  if(!restoreSelection && i==oldSelection)
794  m_maskList->SetItemState(i,0, wxLIST_STATE_SELECTED);
795  };
796  }
797  else
798  m_maskList->DeleteAllItems();
799  }
800  else
801  m_maskList->DeleteAllItems();
802  m_maskList->Thaw();
803  m_maskType->Enable(m_maskList->GetSelectedItemCount()>0);
804 }
805 
807 {
808  for(unsigned int i=0;i<(unsigned int)m_maskList->GetItemCount();i++)
809  {
810  if(m_maskList->GetItemState(i,wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
811  return i;
812  };
813  return UINT_MAX;
814 };
815 
817 {
818  HuginBase::UIntSet selectedImages;
819  for (unsigned int i = 0; i < (unsigned int)m_imagesListMask->GetItemCount(); i++)
820  {
821  if (m_imagesListMask->GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
822  {
823  selectedImages.insert(i);
824  }
825  }
826  return selectedImages;
827 }
828 
830 {
831  int colNum = e.GetColumn();
832  wxConfigBase::Get()->Write(wxString::Format("/ImagesListMask/ColumnWidth%d", colNum), m_imagesListMask->GetColumnWidth(colNum));
833 }
834 
836 {
837  int colNum = e.GetColumn();
838  wxConfigBase::Get()->Write( wxString::Format("/MaskEditorPanel/ColumnWidth%d",colNum), m_maskList->GetColumnWidth(colNum) );
839 }
840 
842 {
843  if(imgNr==UINT_MAX)
844  return MaskImageCtrl::ROT0;
845 
846  double pitch=m_pano->getImage(imgNr).getPitch();
847  double roll=m_pano->getImage(imgNr).getRoll();
848 
850  // normalize roll angle
851  while (roll > 360) roll-= 360;
852  while (roll < 0) roll += 360;
853 
854  while (pitch > 180) pitch -= 360;
855  while (pitch < -180) pitch += 360;
856  const bool headOver = (pitch > 90 || pitch < -90);
857 
858  if (wxConfig::Get()->Read("/CPEditorPanel/AutoRot", 1L))
859  {
860  if (roll >= 315 || roll < 45)
861  {
862  rot = headOver ? MaskImageCtrl::ROT180 : MaskImageCtrl::ROT0;
863  }
864  else
865  {
866  if (roll >= 45 && roll < 135)
867  {
868  rot = headOver ? MaskImageCtrl::ROT270 : MaskImageCtrl::ROT90;
869  }
870  else
871  {
872  if (roll >= 135 && roll < 225)
873  {
874  rot = headOver ? MaskImageCtrl::ROT0 : MaskImageCtrl::ROT180;
875  }
876  else
877  {
878  rot = headOver ? MaskImageCtrl::ROT90 : MaskImageCtrl::ROT270;
879  };
880  };
881  };
882  };
883  return rot;
884 }
885 
886 void MaskEditorPanel::OnShowActiveMasks(wxCommandEvent &e)
887 {
888  m_editImg->setDrawingActiveMasks(e.IsChecked());
889 };
890 
892 {
893  const HuginBase::SrcPanoImage & img = m_pano->getImage(imgNr);
894  m_cropMode=img.getCropMode();
895  m_cropRect=img.getCropRect();
896  m_autoCenterCrop=img.getAutoCenterCrop();
897 
898  int dx = hugin_utils::roundi(img.getRadialDistortionCenterShift().x);
899  int dy = hugin_utils::roundi(img.getRadialDistortionCenterShift().y);
901  m_cropCenter = vigra::Point2D(img.getSize().width()/2 + dx, img.getSize().height()/2 + dy);
902 
904 }
905 
906 // transfer our state to panorama
907 void MaskEditorPanel::UpdateCrop(bool updateFromImgCtrl)
908 {
909  // set crop image options.
910  if(updateFromImgCtrl)
911  {
913  };
914  std::vector<HuginBase::SrcPanoImage> srcImgs;
915  HuginBase::UIntSet imgs;
916  if (m_cropLens->IsChecked())
917  {
918  const HuginBase::UIntSetVector lensImageVector = m_imageGroups->getLenses().getPartsSet();
919  for (auto i : GetSelectedImages())
920  {
921  for (auto j : lensImageVector)
922  {
923  if (set_contains(j, i))
924  {
925  std::copy(j.begin(), j.end(), std::inserter(imgs, imgs.begin()));
926  break;
927  };
928  };
929  };
930  }
931  else
932  {
933  imgs = GetSelectedImages();
934  }
935  for (auto i:imgs)
936  {
938  img.setCropRect(m_cropRect);
939  img.setAutoCenterCrop(m_autoCenterCrop);
940  srcImgs.push_back(img);
941  };
942 
944  new PanoCommand::UpdateSrcImagesCmd(*m_pano, imgs, srcImgs)
945  );
946 }
947 
949 {
952 };
953 
954 // redraw display with new information
956 {
957  DEBUG_TRACE("")
959  m_left_textctrl->SetValue(wxString::Format("%d",m_cropRect.left()));
960  m_right_textctrl->SetValue(wxString::Format("%d",m_cropRect.right()));
961  m_top_textctrl->SetValue(wxString::Format("%d",m_cropRect.top()));
962  m_bottom_textctrl->SetValue(wxString::Format("%d",m_cropRect.bottom()));
963 }
964 
965 
966 void MaskEditorPanel::OnSetTop(wxCommandEvent & e)
967 {
968  long val;
969  if (m_top_textctrl->GetValue().ToLong(&val))
970  {
971  m_cropRect.setUpperLeft(vigra::Point2D(m_cropRect.left(), val));
972  if (m_autoCenterCrop)
973  {
974  CenterCrop();
976  };
977  UpdateCrop();
978  }
979  else
980  {
981  wxLogError(_("Please enter a valid number"));
982  };
983 };
984 
985 void MaskEditorPanel::OnSetBottom(wxCommandEvent & e)
986 {
987  long val;
988  if (m_bottom_textctrl->GetValue().ToLong(&val))
989  {
990  m_cropRect.setLowerRight(vigra::Point2D(m_cropRect.right(), val));
991  if (m_autoCenterCrop)
992  {
993  CenterCrop();
995  }
996  UpdateCrop();
997  }
998  else
999  {
1000  wxLogError(_("Please enter a valid number"));
1001  };
1002 };
1003 
1004 void MaskEditorPanel::OnSetLeft(wxCommandEvent & e)
1005 {
1006  long val = 0;
1007  if (m_left_textctrl->GetValue().ToLong(&val))
1008  {
1009  m_cropRect.setUpperLeft(vigra::Point2D(val, m_cropRect.top()));
1010  if (m_autoCenterCrop)
1011  {
1012  CenterCrop();
1014  }
1015  UpdateCrop();
1016  }
1017  else
1018  {
1019  wxLogError(_("Please enter a valid number"));
1020  };
1021 };
1022 
1023 void MaskEditorPanel::OnSetRight(wxCommandEvent & e)
1024 {
1025  long val = 0;
1026  if (m_right_textctrl->GetValue().ToLong(&val))
1027  {
1028  m_cropRect.setLowerRight(vigra::Point2D(val, m_cropRect.bottom()));
1029  if (m_autoCenterCrop)
1030  {
1031  CenterCrop();
1033  };
1034  UpdateCrop();
1035  }
1036  else
1037  {
1038  wxLogError(_("Please enter a valid number"));
1039  };
1040 };
1041 
1042 void MaskEditorPanel::OnResetButton(wxCommandEvent & e)
1043 {
1044  // suitable defaults.
1045  m_cropRect.setUpperLeft(vigra::Point2D(0,0));
1046  m_cropRect.setLowerRight(vigra::Point2D(0,0));
1047  m_autoCenterCrop = true;
1050  UpdateCrop();
1051 }
1052 
1053 void MaskEditorPanel::OnAutoCenter(wxCommandEvent & e)
1054 {
1055  m_autoCenterCrop = e.IsChecked();
1056  if (m_autoCenterCrop)
1057  {
1058  CenterCrop();
1060  };
1061  UpdateCrop();
1062 }
1063 
1065 {
1066  vigra::Diff2D d(m_cropRect.width()/2, m_cropRect.height() / 2);
1067  m_cropRect.setUpperLeft( m_cropCenter - d);
1068  m_cropRect.setLowerRight( m_cropCenter + d);
1069 }
1070 
1071 void MaskEditorPanel::OnModeChanged(wxNotebookEvent& e)
1072 {
1073  if(m_maskCropCtrl==NULL)
1074  {
1075  return;
1076  };
1077  if(m_maskCropCtrl->GetSelection()==0)
1078  {
1079  m_maskMode=true;
1080  size_t imgNr=GetImgNr();
1081  m_imagesListMask->SetSingleStyle(wxLC_SINGLE_SEL, true);
1083  m_editImg->SetMaskMode(true);
1084  }
1085  else
1086  {
1087  m_maskMode=false;
1088  m_imagesListMask->SetSingleStyle(wxLC_SINGLE_SEL, false);
1089  m_editImg->SetMaskMode(false);
1090  SelectMask(UINT_MAX);
1091  };
1092  m_editImg->Refresh();
1093 };
1094 
1096 {
1097  m_maskCropCtrl->SetSelection(1);
1098  wxNotebookEvent dummy;
1099  OnModeChanged(dummy);
1100 }
1101 
1103 
1105  : wxXmlResourceHandler()
1106 {
1107  AddWindowStyles();
1108 }
1109 
1111 {
1112  XRC_MAKE_INSTANCE(cp, MaskEditorPanel)
1113 
1114  cp->Create(m_parentAsWindow,
1115  GetID(),
1116  GetPosition(), GetSize(),
1117  GetStyle("style"),
1118  GetName());
1119 
1120  SetupWindow(cp);
1121 
1122  return cp;
1123 }
1124 
1126 {
1127  return IsOfClass(node, "MaskEditorPanel");
1128 }
1129 
void OnResetButton(wxCommandEvent &e)
update source images
Definition: PanoCommand.h:404
ImageRotation
image rotation.
Definition: MaskImageCtrl.h:55
HuginBase::ConstStandardImageVariableGroups * m_imageGroups
void OnSetTop(wxCommandEvent &e)
void SaveMaskToStream(std::ostream &stream, vigra::Size2D imageSize, MaskPolygon &maskToWrite, size_t imgNr)
save the mask into stream
Definition: Mask.cpp:685
implementation of huginApp Class
bool AskUserOverwrite(const wxString &filename, const wxString &caption, wxWindow *parent)
ask user if the given file should be overwritten, return true if the user confirmed the overwritting ...
Definition: wxutils.cpp:233
hugin_utils::FDiff2D getRadialDistortionCenter() const
std::vector< UIntSet > UIntSetVector
Definition: PanoramaData.h:56
void UpdateMaskList(bool restoreSelection=false)
updates the display after another image has been selected.
void UpdateCropFromImage()
updates the displayed crop in the text boxes (for dragging)
unsigned int m_MaskNr
int roundi(T x)
Definition: hugin_math.h:73
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
wxListCtrl * m_imagesListMask
wxListCtrl * m_maskList
bool isCircularCrop() const
returns true, if projection requires cicular crop
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
void setActiveMask(unsigned int newMask, bool doUpdate=true)
mark mask with image as beeing editing
HuginBase::Panorama * m_pano
void LoadMaskFromStream(std::istream &stream, vigra::Size2D &imageSize, MaskPolygonVector &newMasks, size_t imgNr)
load the mask from stream
Definition: Mask.cpp:640
#define DEBUG_TRACE(msg)
Definition: utils.h:67
void OnMaskPaste(wxCommandEvent &e)
called when user wants to paste a mask from clipboard
void SelectMask(unsigned int newMaskNr)
selects the mask with index newMaskNr in the listbox
void SetUserColourPointUnselected(wxColour newColour)
xrc handler for handling mask editor panel
MaskImageCtrl * m_editImg
HuginBase::MaskPolygonVector getProcessedMask() const
return the processed mask
void OnMaskColumnWidthChange(wxListEvent &e)
called, when column with of mask list box was changed
void OnImageSelect(wxListEvent &e)
called when user selected another image
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
virtual bool CanHandle(wxXmlNode *node)
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
wxChoice * m_maskType
HuginBase::SrcPanoImage::CropMode m_cropMode
include file for the hugin project
mask editor panel.
void setImage(unsigned int imgNr, bool updateListSelection=false)
sets the image, which is currently edited
vigra::Rect2D getCrop()
returns the current crop rect
Definition: MaskImageCtrl.h:66
void OnMaskLoad(wxCommandEvent &e)
called when user wants to load a mask into the selected image
HuginBase::MaskPolygonVector m_currentMasks
void OnImageListChar(wxKeyEvent &e)
key handler for images list
void OnAutoCenter(wxCommandEvent &e)
wxTextCtrl * m_right_textctrl
void OnSetBottom(wxCommandEvent &e)
void OnSetRight(wxCommandEvent &e)
bool hasMasks() const
returns true, if image has masks associated
void SetUserColourPolygonNegative(wxColour newColour)
sets the colour for different parts
const HuginBase::UIntSet GetSelectedImages()
return the currently selected image(s)
void SetUserColourPointSelected(wxColour newColour)
mask editor
Definition: MaskImageCtrl.h:38
void setMask(unsigned int maskNr)
sets active mask number, set to UINT_MAX, if no mask is currently editing
vigra::Rect2D m_cropRect
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
void OnZoom(wxCommandEvent &e)
sets the actual zoom factor
update mask for given image
Definition: PanoCommand.h:612
Model for a panorama.
Definition: Panorama.h:152
void setImage(const std::string &filename, HuginBase::MaskPolygonVector newMask, HuginBase::MaskPolygonVector masksToDraw, ImageRotation rot)
set the current image and mask list, this loads also the image from cache
ConstImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables.
UIntSetVector getPartsSet() const
return a vector which contains a HuginBase::UIntSet for each group with the corresponding images numb...
void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &imgNr)
notifies about changes to images
HuginBase::MaskPolygon::MaskType m_defaultMaskType
void OnMaskTypeChange(wxCommandEvent &e)
handler when mask type was changed
void OnImagesColumnWidthChange(wxListEvent &e)
called, when column with of images list box was changed
HuginBase::MaskPolygonVector getNewMask() const
returns the vector of all mask (including new created mask)
Definition: MaskImageCtrl.h:70
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
static MainFrame * Get()
hack.. kind of a pseudo singleton...
Definition: MainFrame.cpp:2129
void SwitchToCropMode()
switches the controls to crop mode
MaskType
enumeration with type of possible masks
Definition: Mask.h:56
void OnColourChanged(wxColourPickerEvent &e)
event handler for changing colours
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
void OnModeChanged(wxNotebookEvent &e)
ImageRotation getCurrentRotation()
returns the current rotation of displayed image
vigra::Point2D m_cropCenter
double getScale()
return scale factor, 0 for autoscale
void UpdateMask()
called when mask where changed in MaskImageCtrl
Make an ImageVariableGroup for lenses and other common concepts.
static GlobalCmdHist & getInstance()
void UpdateCrop(bool updateFromImgCtrl=false)
updated the crop in the Panorama object with the current values from GUI
void SelectSingleImage(wxListCtrl *list, unsigned int imgNr)
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
wxCheckBox * m_autocenter_cb
void OnMaskSave(wxCommandEvent &e)
called when user wants to save active mask
std::vector< MaskPolygon > MaskPolygonVector
Definition: Mask.h:147
#define DEBUG_ERROR(msg)
Definition: utils.h:76
void Init(HuginBase::Panorama *pano)
wxCheckBox * m_cropLens
#define HUGIN_MASK_COLOUR_POINT_UNSELECTED
void selectAllMarkers()
select all points of active mask
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name="panel")
std::string m_File
Dialog for loading masks.
void setNewMasks(HuginBase::MaskPolygonVector newMasks, HuginBase::MaskPolygonVector masksToDraw)
updates masks for currently selected image
void OnSetLeft(wxCommandEvent &e)
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
include file for the hugin project
Handle EVT_KILL_FOCUS and convert it to a EVT_TEXT_ENTER event.
wxNotebook * m_maskCropCtrl
virtual ~MaskEditorPanel()
dtor.
options wxIntPtr wxIntPtr sortData std::vector< PanoInfo > * data
void DisplayCrop(int imgNr)
copies the crop information from the Panorama object to GUI
void setScale(double factor)
set the scaling factor for mask editing display.
#define HUGIN_MASK_COLOUR_POINT_SELECTED
void Init(MaskEditorPanel *parent)
void UpdateCropDisplay()
update GUI display
wxTextCtrl * m_bottom_textctrl
void SetMaskMode(bool newMaskMode)
sets the control to mask (newMaskMode=true) or crop (newMaskMode=false) mode
#define HUGIN_MASK_COLOUR_POLYGON_NEGATIVE
MaskImageCtrl::ImageRotation GetRot(const unsigned int imgNr)
determines, if the image should be rotated for display
void OnMaskDelete(wxCommandEvent &e)
called when user wants to delete active mask
void update()
Update part numbers for each variable group.
Definition of mask load dialog.
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
void UpdateImage(size_t imgNr)
update the list box for the given imgNr
void SetUserColourPolygonPositive(wxColour newColour)
void OnMaskSelect(wxListEvent &e)
called when user selected another mask
void OnMaskAdd(wxCommandEvent &e)
called when user wants to create new polygon
void panoramaChanged(HuginBase::Panorama &pano)
called when the panorama changes and we should update our display
void OnShowActiveMasks(wxCommandEvent &e)
event handler for changing option if active masks should be drawn
#define HUGIN_MASK_COLOUR_POLYGON_POSITIVE
void startNewPolygon()
starts creating a new polygon
void AddMask()
called when new mask added in MaskImageCtrl
wxTextCtrl * m_top_textctrl
All variables of a source image.
Definition: SrcPanoImage.h:194
void setCrop(HuginBase::SrcPanoImage::CropMode newCropMode, vigra::Rect2D newCropRect, bool isCentered, hugin_utils::FDiff2D center, bool isCircleCrop)
updates the crop mode and crop rect
virtual wxObject * DoCreateResource()
void initValues(const HuginBase::SrcPanoImage image, const HuginBase::MaskPolygonVector newMask, const vigra::Size2D maskSize)
sets the default values
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:176
wxTextCtrl * m_left_textctrl
unsigned int GetSelectedMask()
return index of currently selected masks, return UINT_MAX if no mask is selected
void setDrawingActiveMasks(bool newDrawActiveMasks)
set if active masks should be drawn
void OnMaskCopy(wxCommandEvent &e)
called when user wants to copy a mask to clipboard