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  if (imgNr != UINT_MAX)
268  {
269  list->SetItemState(imgNr, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
270  };
271 }
272 
273 void MaskEditorPanel::setImage(unsigned int imgNr, bool updateListSelection)
274 {
275  DEBUG_TRACE("image " << imgNr);
276  bool restoreMaskSelection=(imgNr==GetImgNr());
277  bool updateImage=true;
278  HuginBase::MaskPolygonVector masksToDraw;
279  if (imgNr == UINT_MAX)
280  {
281  m_File = "";
283  m_currentMasks=mask;
284  m_editImg->setCrop(HuginBase::SrcPanoImage::NO_CROP,vigra::Rect2D(), false, hugin_utils::FDiff2D(), false);
285  }
286  else
287  {
288  const HuginBase::SrcPanoImage& image=m_pano->getImage(imgNr);
289  updateImage=(m_File!=image.getFilename());
290  if(updateImage)
291  m_File=image.getFilename();
292  else
293  if(GetRot(imgNr)!=m_editImg->getCurrentRotation())
294  {
295  updateImage=true;
296  m_File=image.getFilename();
297  };
298  m_currentMasks=image.getMasks();
299  masksToDraw=image.getActiveMasks();
300  m_editImg->setCrop(image.getCropMode(),image.getCropRect(), image.getAutoCenterCrop(), image.getRadialDistortionCenter(), image.isCircularCrop());
301  };
302  // update mask editor
303  if(updateImage)
304  m_editImg->setImage(m_File,m_currentMasks,masksToDraw,GetRot(imgNr));
305  else
306  m_editImg->setNewMasks(m_currentMasks,masksToDraw);
307  if (m_currentMasks.empty() || m_MaskNr >= m_currentMasks.size())
308  setMask(UINT_MAX);
309  // enables or disables controls
310  bool enableCtrl=(imgNr<UINT_MAX);
311  XRCCTRL(*this, "mask_editor_choice_zoom", wxChoice)->Enable(enableCtrl);
312  XRCCTRL(*this, "mask_editor_add", wxButton)->Enable(enableCtrl);
313  XRCCTRL(*this, "mask_editor_delete", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
314  XRCCTRL(*this, "mask_editor_load", wxButton)->Enable(enableCtrl);
315  XRCCTRL(*this, "mask_editor_save", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
316  XRCCTRL(*this, "mask_editor_paste", wxButton)->Enable(enableCtrl);
317  XRCCTRL(*this, "mask_editor_copy", wxButton)->Enable(enableCtrl && m_MaskNr<UINT_MAX);
318  UpdateMaskList(restoreMaskSelection);
319  // FIXME: lets hope that nobody holds references to these images..
320  ImageCache::getInstance().softFlush();
321  if(updateListSelection)
322  {
324  m_imagesListMask->EnsureVisible(imgNr);
325  };
326 }
327 
328 void MaskEditorPanel::setMask(unsigned int maskNr)
329 {
330  m_MaskNr=maskNr;
331  m_maskType->Enable(m_MaskNr<UINT_MAX);
333  XRCCTRL(*this,"mask_editor_delete", wxButton)->Enable(m_MaskNr<UINT_MAX);
334  XRCCTRL(*this, "mask_editor_save", wxButton)->Enable(m_MaskNr<UINT_MAX);
335  XRCCTRL(*this, "mask_editor_copy", wxButton)->Enable(m_MaskNr<UINT_MAX);
336  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
337  m_maskType->SetSelection(m_currentMasks[m_MaskNr].getMaskType());
338  else
339  m_maskType->SetSelection((int)m_defaultMaskType);
340 };
341 
343 {
344  if(GetImgNr()<UINT_MAX)
345  {
348  };
349 };
350 
352 {
353  if(GetImgNr()<UINT_MAX)
354  {
356  m_currentMasks[m_currentMasks.size()-1].setMaskType(m_defaultMaskType);
358  //select added mask
359  SelectMask(m_currentMasks.size()-1);
361  };
362 };
363 
364 void MaskEditorPanel::SelectMask(unsigned int newMaskNr)
365 {
366  if (GetImgNr() < UINT_MAX)
367  {
368  if (newMaskNr < m_currentMasks.size())
369  {
370  m_maskList->SetItemState(newMaskNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
371  }
372  else
373  {
374  if (m_MaskNr < UINT_MAX)
375  {
376  m_maskList->SetItemState(m_MaskNr, 0, wxLIST_STATE_SELECTED);
377  };
378  };
379  };
380 };
381 
383 {
384 };
385 
387 {
388  const HuginBase::SrcPanoImage& img = m_pano->getImage(imgNr);
389  wxFileName fn(wxString(img.getFilename().c_str(), HUGIN_CONV_FILENAME));
390  m_imagesListMask->SetItem(imgNr, 1, fn.GetFullName());
391 
392  wxString maskstr;
393  if (img.hasMasks())
394  {
395  maskstr = wxString::Format("%lu", (unsigned long int) m_pano->getImage(imgNr).getMasks().size());
396  }
397  else
398  {
399  maskstr = wxString("-");
400  };
401  m_imagesListMask->SetItem(imgNr, 2, maskstr);
402 
403  wxString cropstr("-");
404  if (img.getCropMode() != HuginBase::SrcPanoImage::NO_CROP)
405  {
406  vigra::Rect2D c = img.getCropRect();
407  cropstr.Printf("%d,%d,%d,%d", c.left(), c.right(), c.top(), c.bottom());
408  }
409  m_imagesListMask->SetItem(imgNr, 3, cropstr);
410 }
411 
413 {
414  const long nrImages = pano.getNrOfImages();
416  ImageCache::getInstance().softFlush();
418  {
419  m_imagesListMask->Freeze();
420  const size_t nrItems = m_imagesListMask->GetItemCount();
421  // remove items for nonexisting images
422  if (nrItems > nrImages)
423  {
424  for (long i = nrItems - 1; i >= nrImages; i--)
425  {
426  m_imagesListMask->DeleteItem(i);
427  }
428  }
429  // add newly added images
430  if (nrImages >= nrItems)
431  {
432  for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
433  {
434  if (*it >= nrItems)
435  {
436  m_imagesListMask->InsertItem(*it, wxString::Format("%d", *it));
437  }
438  }
439  }
440  // update existing items
441  for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
442  {
443  UpdateImage(*it);
444  }
445  m_imagesListMask->Thaw();
446  }
447 
448  if (nrImages == 0)
449  {
450  setImage(UINT_MAX);
451  }
452  else
453  {
454  // select some other image if we deleted the current image
455  if ((GetImgNr() < UINT_MAX) && (GetImgNr() >= nrImages))
456  {
457  setImage(nrImages - 1);
458  }
459  else
460  // update changed images
461  if(set_contains(changed,GetImgNr()))
462  {
463  unsigned int countOldMasks=m_currentMasks.size();
464  setImage(GetImgNr());
465  if(countOldMasks!=pano.getImage(GetImgNr()).getMasks().size())
466  SelectMask(UINT_MAX);
467  };
468  };
469 
470  if (m_imagesListMask->GetSelectedItemCount() > 0)
471  {
472  if (set_contains(changed, GetImgNr()))
473  {
475  }
476  }
477  else
478  {
480  }
481 
482 }
483 
485 {
486  // only for multi selection mode
487  if ((m_imagesListMask->GetWindowStyle() & wxLC_SINGLE_SEL) == 0)
488  {
489  // ctrl + a
490  if (e.GetKeyCode() == 1 && e.CmdDown())
491  {
492  // select all
493  for (int i = 0; i < m_imagesListMask->GetItemCount(); i++)
494  {
495  m_imagesListMask->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
496  }
497  }
498  }
499  e.Skip();
500 }
501 
502 void MaskEditorPanel::OnImageSelect(wxListEvent &e)
503 {
504  const HuginBase::UIntSet selectedImages=GetSelectedImages();
505  //select no mask
506  setMask(UINT_MAX);
507  setImage(GetImgNr());
508 
509  const bool hasImage = !selectedImages.empty();
510  m_left_textctrl->Enable(hasImage);
511  m_top_textctrl->Enable(hasImage);
512  m_bottom_textctrl->Enable(hasImage);
513  m_right_textctrl->Enable(hasImage);
514  if (hasImage)
515  {
516  // show first image.
518  };
519 };
520 
521 void MaskEditorPanel::OnMaskSelect(wxListEvent &e)
522 {
524 };
525 
526 void MaskEditorPanel::OnMaskTypeChange(wxCommandEvent &e)
527 {
528  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
529  {
530  m_currentMasks[m_MaskNr].setMaskType((HuginBase::MaskPolygon::MaskType)e.GetSelection());
533  };
534 };
535 
536 void MaskEditorPanel::OnMaskAdd(wxCommandEvent &e)
537 {
538  if(GetImgNr()<UINT_MAX)
539  {
540  //deselect current selected mask
541  if(m_MaskNr<UINT_MAX)
542  m_maskList->SetItemState(m_MaskNr,0,wxLIST_STATE_SELECTED);
543  setMask(UINT_MAX);
544  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);
546  };
547 };
548 
549 void MaskEditorPanel::OnMaskSave(wxCommandEvent &e)
550 {
551  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
552  {
553  wxFileDialog dlg(this, _("Save mask"),
554  wxConfigBase::Get()->Read("/actualPath", wxEmptyString),
555  wxEmptyString, _("Mask files (*.msk)|*.msk|All files (*)|*"),
556  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
557  if (dlg.ShowModal() == wxID_OK)
558  {
559  wxString fn = dlg.GetPath();
560  if (fn.Right(4) != ".msk")
561  {
562  fn.Append(".msk");
563  if (wxFile::Exists(fn))
564  {
565  if (!hugin_utils::AskUserOverwrite(fn, _("Hugin"), this))
566  {
567  return;
568  }
569  }
570  };
571  wxFileName filename = fn;
572  std::ofstream maskFile(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
574  maskFile.close();
575  };
576  }
577 };
578 
579 void MaskEditorPanel::OnMaskLoad(wxCommandEvent &e)
580 {
581  if (GetImgNr()<UINT_MAX)
582  {
583  wxFileDialog dlg(this,_("Load mask"),
584  wxConfigBase::Get()->Read("/actualPath",wxEmptyString),
585  wxEmptyString,_("Mask files (*.msk)|*.msk|All files (*)|*"),
586  wxFD_OPEN, wxDefaultPosition);
587  if (dlg.ShowModal() != wxID_OK)
588  {
589  MainFrame::Get()->SetStatusText(_("Load mask: cancel"));
590  return;
591  }
592  wxFileName filename(dlg.GetPath());
593  std::ifstream in(filename.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
594  vigra::Size2D maskImageSize;
595  HuginBase::MaskPolygonVector loadedMasks;
596  LoadMaskFromStream(in, maskImageSize, loadedMasks, GetImgNr());
597  in.close();
598  if(maskImageSize.area()==0 || loadedMasks.empty())
599  {
600  hugin_utils::HuginMessageBox(wxString::Format(_("Could not parse mask from file %s."), dlg.GetPath()), _("Hugin"), wxOK | wxICON_EXCLAMATION, this);
601  return;
602  };
603  // compare image size from file with that of current image alert user
604  // if different.
605  if (maskImageSize != m_pano->getImage(GetImgNr()).getSize())
606  {
607  MaskLoadDialog dlg(this);
608  dlg.initValues(m_pano->getImage(GetImgNr()),loadedMasks,maskImageSize);
609  if(dlg.ShowModal()!=wxID_OK)
610  {
611  // abort
612  return;
613  }
614  loadedMasks=dlg.getProcessedMask();
615  }
616  for(unsigned int i=0;i<loadedMasks.size();i++)
617  m_currentMasks.push_back(loadedMasks[i]);
618  // Update the pano with the imported masks
620  }
621 };
622 
623 void MaskEditorPanel::OnMaskCopy(wxCommandEvent &e)
624 {
625  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX && m_maskMode)
626  {
627  std::ostringstream stream;
629  if (wxTheClipboard->Open())
630  {
631  // This data objects are held by the clipboard,
632  // so do not delete them in the app.
633  wxTheClipboard->SetData(new wxTextDataObject(wxString(stream.str().c_str(),wxConvLocal)));
634  wxTheClipboard->Close();
635  };
636  };
637 };
638 
639 void MaskEditorPanel::OnMaskPaste(wxCommandEvent &e)
640 {
641  if(GetImgNr()<UINT_MAX && m_maskMode)
642  {
643  if (wxTheClipboard->Open())
644  {
645  vigra::Size2D maskImageSize;
646  HuginBase::MaskPolygonVector loadedMasks;
647  if (wxTheClipboard->IsSupported( wxDF_TEXT ))
648  {
649  wxTextDataObject data;
650  wxTheClipboard->GetData(data);
651  std::istringstream stream(std::string(data.GetText().mb_str()));
652  LoadMaskFromStream(stream, maskImageSize, loadedMasks, GetImgNr());
653  }
654  wxTheClipboard->Close();
655  if(maskImageSize.area()==0 || loadedMasks.empty())
656  {
657  wxBell();
658  return;
659  };
660  // compare image size from file with that of current image alert user
661  // if different.
662  if (maskImageSize != m_pano->getImage(GetImgNr()).getSize())
663  {
664  MaskLoadDialog dlg(this);
665  dlg.initValues(m_pano->getImage(GetImgNr()),loadedMasks,maskImageSize);
666  if(dlg.ShowModal()!=wxID_OK)
667  {
668  // abort
669  return;
670  }
671  loadedMasks=dlg.getProcessedMask();
672  }
673  for(unsigned int i=0;i<loadedMasks.size();i++)
674  m_currentMasks.push_back(loadedMasks[i]);
675  // Update the pano with the imported masks
677  };
678  };
679 };
680 
681 void MaskEditorPanel::OnMaskDelete(wxCommandEvent &e)
682 {
683  if(GetImgNr()<UINT_MAX && m_MaskNr<UINT_MAX)
684  {
686  editedMasks.erase(editedMasks.begin()+m_MaskNr);
687  //setMask(UINT_MAX);
689  };
690 };
691 
692 void MaskEditorPanel::OnZoom(wxCommandEvent & e)
693 {
694  int posX = 0;
695  int posY = 0;
696  const wxSize ctrlSize = m_editImg->GetClientSize();
697  if (m_editImg->getScale() > 0)
698  {
699  // remember old scroll position
700  posX = (m_editImg->GetScrollPos(wxHORIZONTAL) + ctrlSize.GetWidth() / 2) / m_editImg->getScale();
701  posY = (m_editImg->GetScrollPos(wxVERTICAL) + ctrlSize.GetHeight() / 2) / m_editImg->getScale();
702  };
703  double factor;
704  switch (e.GetSelection())
705  {
706  case 0:
707  factor = 1;
708  break;
709  case 1:
710  // fit to window
711  factor = 0;
712  break;
713  case 2:
714  factor = 2;
715  break;
716  case 3:
717  factor = 1.5;
718  break;
719  case 4:
720  factor = 0.75;
721  break;
722  case 5:
723  factor = 0.5;
724  break;
725  case 6:
726  factor = 0.25;
727  break;
728  default:
729  DEBUG_ERROR("unknown scale factor");
730  factor = 1;
731  }
732  m_editImg->setScale(factor);
733  if (factor > 0)
734  {
735  m_editImg->Scroll(posX*factor - ctrlSize.GetWidth() / 2, posY*factor - ctrlSize.GetHeight() / 2);
736  };
737  if (e.GetString() == "update_selection")
738  {
739  XRCCTRL(*this, "mask_editor_choice_zoom", wxChoice)->SetSelection(e.GetSelection());
740  };
741 }
742 
743 void MaskEditorPanel::OnColourChanged(wxColourPickerEvent &e)
744 {
745  if(e.GetId()==XRCID("mask_editor_colour_polygon_negative"))
746  {
747  m_editImg->SetUserColourPolygonNegative(e.GetColour());
748  wxConfigBase::Get()->Write("/MaskEditorPanel/ColourPolygonNegative",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
749  }
750  else
751  if(e.GetId()==XRCID("mask_editor_colour_polygon_positive"))
752  {
753  m_editImg->SetUserColourPolygonPositive(e.GetColour());
754  wxConfigBase::Get()->Write("/MaskEditorPanel/ColourPolygonPositive",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
755  }
756  else
757  if(e.GetId()==XRCID("mask_editor_colour_point_selected"))
758  {
759  m_editImg->SetUserColourPointSelected(e.GetColour());
760  wxConfigBase::Get()->Write("/MaskEditorPanel/ColourPointSelected",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
761  }
762  else
763  {
764  m_editImg->SetUserColourPointUnselected(e.GetColour());
765  wxConfigBase::Get()->Write("/MaskEditorPanel/ColourPointUnselected",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
766  }
767  m_editImg->Refresh(true);
768 };
769 
770 void MaskEditorPanel::UpdateMaskList(bool restoreSelection)
771 {
772  unsigned int oldSelection=GetSelectedMask();
773  m_maskList->Freeze();
774  if(GetImgNr()<UINT_MAX)
775  {
776  if(!m_currentMasks.empty())
777  {
778  if(m_maskList->GetItemCount()!=m_currentMasks.size())
779  {
780  if(m_maskList->GetItemCount()<(int)m_currentMasks.size())
781  {
782  //added masks
783  for(int i=m_maskList->GetItemCount();i<(int)m_currentMasks.size();i++)
784  m_maskList->InsertItem(i,wxString::Format("%d",i));
785  }
786  else
787  {
788  //deleted masks
789  for(int i=m_maskList->GetItemCount()-1;i>=(int)m_currentMasks.size();i--)
790  m_maskList->DeleteItem(i);
791  };
792  };
793  for(unsigned int i=0;i<m_currentMasks.size();i++)
794  {
795  m_maskList->SetItem(i,1,m_maskType->GetString(m_currentMasks[i].getMaskType()));
796  if(!restoreSelection && i==oldSelection)
797  m_maskList->SetItemState(i,0, wxLIST_STATE_SELECTED);
798  };
799  }
800  else
801  m_maskList->DeleteAllItems();
802  }
803  else
804  m_maskList->DeleteAllItems();
805  m_maskList->Thaw();
806  m_maskType->Enable(m_maskList->GetSelectedItemCount()>0);
807 }
808 
810 {
811  for(unsigned int i=0;i<(unsigned int)m_maskList->GetItemCount();i++)
812  {
813  if(m_maskList->GetItemState(i,wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
814  return i;
815  };
816  return UINT_MAX;
817 };
818 
820 {
821  HuginBase::UIntSet selectedImages;
822  for (unsigned int i = 0; i < (unsigned int)m_imagesListMask->GetItemCount(); i++)
823  {
824  if (m_imagesListMask->GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
825  {
826  selectedImages.insert(i);
827  }
828  }
829  return selectedImages;
830 }
831 
833 {
834  int colNum = e.GetColumn();
835  wxConfigBase::Get()->Write(wxString::Format("/ImagesListMask/ColumnWidth%d", colNum), m_imagesListMask->GetColumnWidth(colNum));
836 }
837 
839 {
840  int colNum = e.GetColumn();
841  wxConfigBase::Get()->Write( wxString::Format("/MaskEditorPanel/ColumnWidth%d",colNum), m_maskList->GetColumnWidth(colNum) );
842 }
843 
845 {
846  if(imgNr==UINT_MAX)
847  return MaskImageCtrl::ROT0;
848 
849  double pitch=m_pano->getImage(imgNr).getPitch();
850  double roll=m_pano->getImage(imgNr).getRoll();
851 
853  // normalize roll angle
854  while (roll > 360) roll-= 360;
855  while (roll < 0) roll += 360;
856 
857  while (pitch > 180) pitch -= 360;
858  while (pitch < -180) pitch += 360;
859  const bool headOver = (pitch > 90 || pitch < -90);
860 
861  if (wxConfig::Get()->Read("/CPEditorPanel/AutoRot", 1L))
862  {
863  if (roll >= 315 || roll < 45)
864  {
865  rot = headOver ? MaskImageCtrl::ROT180 : MaskImageCtrl::ROT0;
866  }
867  else
868  {
869  if (roll >= 45 && roll < 135)
870  {
871  rot = headOver ? MaskImageCtrl::ROT270 : MaskImageCtrl::ROT90;
872  }
873  else
874  {
875  if (roll >= 135 && roll < 225)
876  {
877  rot = headOver ? MaskImageCtrl::ROT0 : MaskImageCtrl::ROT180;
878  }
879  else
880  {
881  rot = headOver ? MaskImageCtrl::ROT90 : MaskImageCtrl::ROT270;
882  };
883  };
884  };
885  };
886  return rot;
887 }
888 
889 void MaskEditorPanel::OnShowActiveMasks(wxCommandEvent &e)
890 {
891  m_editImg->setDrawingActiveMasks(e.IsChecked());
892 };
893 
895 {
896  const HuginBase::SrcPanoImage & img = m_pano->getImage(imgNr);
897  m_cropMode=img.getCropMode();
898  m_cropRect=img.getCropRect();
899  m_autoCenterCrop=img.getAutoCenterCrop();
900 
901  int dx = hugin_utils::roundi(img.getRadialDistortionCenterShift().x);
902  int dy = hugin_utils::roundi(img.getRadialDistortionCenterShift().y);
904  m_cropCenter = vigra::Point2D(img.getSize().width()/2 + dx, img.getSize().height()/2 + dy);
905 
907 }
908 
909 // transfer our state to panorama
910 void MaskEditorPanel::UpdateCrop(bool updateFromImgCtrl)
911 {
912  // set crop image options.
913  if(updateFromImgCtrl)
914  {
916  };
917  std::vector<HuginBase::SrcPanoImage> srcImgs;
918  HuginBase::UIntSet imgs;
919  if (m_cropLens->IsChecked())
920  {
921  const HuginBase::UIntSetVector lensImageVector = m_imageGroups->getLenses().getPartsSet();
922  for (auto i : GetSelectedImages())
923  {
924  for (auto j : lensImageVector)
925  {
926  if (set_contains(j, i))
927  {
928  std::copy(j.begin(), j.end(), std::inserter(imgs, imgs.begin()));
929  break;
930  };
931  };
932  };
933  }
934  else
935  {
936  imgs = GetSelectedImages();
937  }
938  for (auto i:imgs)
939  {
941  img.setCropRect(m_cropRect);
942  img.setAutoCenterCrop(m_autoCenterCrop);
943  srcImgs.push_back(img);
944  };
945 
947  new PanoCommand::UpdateSrcImagesCmd(*m_pano, imgs, srcImgs)
948  );
949 }
950 
952 {
955 };
956 
957 // redraw display with new information
959 {
960  DEBUG_TRACE("")
962  m_left_textctrl->SetValue(wxString::Format("%d",m_cropRect.left()));
963  m_right_textctrl->SetValue(wxString::Format("%d",m_cropRect.right()));
964  m_top_textctrl->SetValue(wxString::Format("%d",m_cropRect.top()));
965  m_bottom_textctrl->SetValue(wxString::Format("%d",m_cropRect.bottom()));
966 }
967 
968 
969 void MaskEditorPanel::OnSetTop(wxCommandEvent & e)
970 {
971  long val;
972  if (m_top_textctrl->GetValue().ToLong(&val))
973  {
974  m_cropRect.setUpperLeft(vigra::Point2D(m_cropRect.left(), val));
975  if (m_autoCenterCrop)
976  {
977  CenterCrop();
979  };
980  UpdateCrop();
981  }
982  else
983  {
984  wxLogError(_("Please enter a valid number"));
985  };
986 };
987 
988 void MaskEditorPanel::OnSetBottom(wxCommandEvent & e)
989 {
990  long val;
991  if (m_bottom_textctrl->GetValue().ToLong(&val))
992  {
993  m_cropRect.setLowerRight(vigra::Point2D(m_cropRect.right(), val));
994  if (m_autoCenterCrop)
995  {
996  CenterCrop();
998  }
999  UpdateCrop();
1000  }
1001  else
1002  {
1003  wxLogError(_("Please enter a valid number"));
1004  };
1005 };
1006 
1007 void MaskEditorPanel::OnSetLeft(wxCommandEvent & e)
1008 {
1009  long val = 0;
1010  if (m_left_textctrl->GetValue().ToLong(&val))
1011  {
1012  m_cropRect.setUpperLeft(vigra::Point2D(val, m_cropRect.top()));
1013  if (m_autoCenterCrop)
1014  {
1015  CenterCrop();
1017  }
1018  UpdateCrop();
1019  }
1020  else
1021  {
1022  wxLogError(_("Please enter a valid number"));
1023  };
1024 };
1025 
1026 void MaskEditorPanel::OnSetRight(wxCommandEvent & e)
1027 {
1028  long val = 0;
1029  if (m_right_textctrl->GetValue().ToLong(&val))
1030  {
1031  m_cropRect.setLowerRight(vigra::Point2D(val, m_cropRect.bottom()));
1032  if (m_autoCenterCrop)
1033  {
1034  CenterCrop();
1036  };
1037  UpdateCrop();
1038  }
1039  else
1040  {
1041  wxLogError(_("Please enter a valid number"));
1042  };
1043 };
1044 
1045 void MaskEditorPanel::OnResetButton(wxCommandEvent & e)
1046 {
1047  // suitable defaults.
1048  m_cropRect.setUpperLeft(vigra::Point2D(0,0));
1049  m_cropRect.setLowerRight(vigra::Point2D(0,0));
1050  m_autoCenterCrop = true;
1053  UpdateCrop();
1054 }
1055 
1056 void MaskEditorPanel::OnAutoCenter(wxCommandEvent & e)
1057 {
1058  m_autoCenterCrop = e.IsChecked();
1059  if (m_autoCenterCrop)
1060  {
1061  CenterCrop();
1063  };
1064  UpdateCrop();
1065 }
1066 
1068 {
1069  vigra::Diff2D d(m_cropRect.width()/2, m_cropRect.height() / 2);
1070  m_cropRect.setUpperLeft( m_cropCenter - d);
1071  m_cropRect.setLowerRight( m_cropCenter + d);
1072 }
1073 
1074 void MaskEditorPanel::SetSingleSelection(bool singleSelMode)
1075 {
1076  const size_t imgNr = GetImgNr();
1077 #ifdef __WXMSW__
1078  m_imagesListMask->SetSingleStyle(wxLC_SINGLE_SEL, singleSelMode);
1079 #else
1080  // updating the style flags invalidates the items in the list box
1081  // so first delete all items, then change style and add them again
1082  m_imagesListMask->Freeze();
1083  m_imagesListMask->DeleteAllItems();
1084  m_imagesListMask->SetSingleStyle(wxLC_SINGLE_SEL, singleSelMode);
1085  for (size_t i = 0; i < m_pano->getNrOfImages(); ++i)
1086  {
1087  m_imagesListMask->InsertItem(m_imagesListMask->GetItemCount(), wxEmptyString);
1088  UpdateImage(i);
1089  };
1090  m_imagesListMask->Thaw();
1091 #endif
1093 }
1094 
1095 void MaskEditorPanel::OnModeChanged(wxNotebookEvent& e)
1096 {
1097  if(m_maskCropCtrl==NULL)
1098  {
1099  return;
1100  };
1101  if(m_maskCropCtrl->GetSelection()==0)
1102  {
1103  m_maskMode=true;
1104  SetSingleSelection(true);
1105  m_editImg->SetMaskMode(true);
1106  }
1107  else
1108  {
1109  m_maskMode=false;
1110  SetSingleSelection(false);
1111  m_editImg->SetMaskMode(false);
1112  SelectMask(UINT_MAX);
1113  };
1114  m_editImg->Refresh();
1115 };
1116 
1118 {
1119  m_maskCropCtrl->SetSelection(1);
1120  wxNotebookEvent dummy;
1121  OnModeChanged(dummy);
1122 }
1123 
1125 
1127  : wxXmlResourceHandler()
1128 {
1129  AddWindowStyles();
1130 }
1131 
1133 {
1134  XRC_MAKE_INSTANCE(cp, MaskEditorPanel)
1135 
1136  cp->Create(m_parentAsWindow,
1137  GetID(),
1138  GetPosition(), GetSize(),
1139  GetStyle("style"),
1140  GetName());
1141 
1142  SetupWindow(cp);
1143 
1144  return cp;
1145 }
1146 
1148 {
1149  return IsOfClass(node, "MaskEditorPanel");
1150 }
1151 
void OnResetButton(wxCommandEvent &e)
update source images
Definition: PanoCommand.h:404
ImageRotation
image rotation.
Definition: MaskImageCtrl.h:55
void SetSingleSelection(bool singleSelMode)
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:708
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:663
#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:150
#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