Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImagesTree.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
10 /* This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This software is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public
21  * License along with this software. If not, see
22  * <http://www.gnu.org/licenses/>.
23  *
24  */
25 
26 #include "hugin_config.h"
27 #include "panoinc_WX.h"
28 #include "panoinc.h"
29 
30 #include "base_wx/wxPlatform.h"
31 #include "base_wx/LensTools.h"
32 #include "hugin/ImagesTree.h"
33 #include "base_wx/wxImageCache.h"
34 #include "base_wx/platform.h"
38 #include "base_wx/CommandHistory.h"
39 #include "base_wx/PanoCommand.h"
40 #include <hugin_utils/stl_utils.h>
42 #include "hugin/huginApp.h"
43 #include "hugin/MainFrame.h"
44 #include "hugin/GLPreviewFrame.h"
45 #include <wx/renderer.h>
46 
47 enum
48 {
49  ID_LINK=wxID_HIGHEST+230,
58  ID_OPERATION_START=wxID_HIGHEST+300
59 };
60 
61 BEGIN_EVENT_TABLE(ImagesTreeCtrl, wxTreeListCtrl)
62  EVT_LIST_COL_END_DRAG(-1, ImagesTreeCtrl::OnColumnWidthChange)
63  EVT_TREE_ITEM_MENU(-1, ImagesTreeCtrl::OnContextMenu)
64  EVT_LIST_COL_RIGHT_CLICK(-1, ImagesTreeCtrl::OnHeaderContextMenu)
65  EVT_MENU(ID_LINK, ImagesTreeCtrl::OnLinkImageVariables)
66  EVT_MENU(ID_UNLINK, ImagesTreeCtrl::OnUnlinkImageVariables)
67  EVT_MENU(ID_EDIT, ImagesTreeCtrl::OnEditImageVariables)
68  EVT_MENU(ID_SELECT_ALL, ImagesTreeCtrl::OnSelectAll)
69  EVT_MENU(ID_UNSELECT_ALL, ImagesTreeCtrl::OnUnselectAll)
70  EVT_MENU(ID_SELECT_LENS_STACK, ImagesTreeCtrl::OnSelectLensStack)
71  EVT_MENU(ID_UNSELECT_LENS_STACK, ImagesTreeCtrl::OnUnselectLensStack)
72  EVT_MENU(ID_ACTIVATE_IMAGE, ImagesTreeCtrl::OnActivateImage)
73  EVT_MENU(ID_DEACTIVATE_IMAGE, ImagesTreeCtrl::OnDeactivateImage)
74  EVT_MENU_RANGE(ID_OPERATION_START, ID_OPERATION_START+50, ImagesTreeCtrl::OnExecuteOperation)
75  EVT_TREE_BEGIN_DRAG(-1, ImagesTreeCtrl::OnBeginDrag)
76  EVT_LEFT_UP(ImagesTreeCtrl::OnLeftUp)
77  EVT_LEFT_DCLICK(ImagesTreeCtrl::OnLeftDblClick)
78  EVT_TREE_KEY_DOWN(-1, ImagesTreeCtrl::OnChar)
79  EVT_TREE_BEGIN_LABEL_EDIT(-1, ImagesTreeCtrl::OnBeginEdit)
80  EVT_TREE_END_LABEL_EDIT(-1, ImagesTreeCtrl::OnEndEdit)
81 #if wxCHECK_VERSION(3,1,3)
82  EVT_DPI_CHANGED(ImagesTreeCtrl::OnDpiChanged)
83 #endif
85 
86 class ImagesTreeData : public wxTreeItemData
87 {
88 public:
89  explicit ImagesTreeData(const long& nr) : m_nr(nr) { };
90  const long GetImgNr() const { return m_nr;};
91  void SetImgNr(long newImgNr) { m_nr=newImgNr;};
92  const long GetGroupNr() const { return -(m_nr+1);};
93  const bool IsGroup() const { return (m_nr<0); };
94 
95 private:
96  long m_nr;
97 };
98 
99 // Define a constructor for the Images Panel
101 {
102  m_pano = NULL;
105  m_dragging=false;
107  m_optimizerMode=false;
108  m_needsUpdate=true;
109  m_markDisabledImages = false;
110 }
111 
112 bool ImagesTreeCtrl::Create(wxWindow* parent, wxWindowID id,
113  const wxPoint& pos,
114  const wxSize& size,
115  long style,
116  const wxString& name)
117 {
118  DEBUG_TRACE("List");
119  if (! wxTreeListCtrl::Create(parent, id, pos, size, style | wxTR_DEFAULT_STYLE|wxTR_HIDE_ROOT|wxTR_NO_LINES|wxTR_FULL_ROW_HIGHLIGHT|wxTR_ROW_LINES|wxTR_LINES_AT_ROOT|wxTR_MULTIPLE) )
120  {
121  return false;
122  }
123 
124  DEBUG_TRACE("Tree, adding columns");
125  m_configClassName = wxT("/ImagesTree");
126  CreateColumns();
127  DEBUG_TRACE("");
128  m_degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigits"),1);
129  m_pixelDigits = wxConfigBase::Get()->Read(wxT("/General/PixelFractionalDigits"),1);
130  m_distDigits = wxConfigBase::Get()->Read(wxT("/General/DistortionFractionalDigits"),3);
131  //create root
132  m_root=AddRoot(wxT("root"));
133  return true;
134 }
135 
137 {
138  size_t counter=0;
139 #define ADDCOLUMN(header, mapName, width, align, isEditable, IVE, tooltip) \
140  AddColumn(header, width, align, -1, true, false, tooltip);\
141  m_columnMap[mapName]=counter;\
142  m_columnVector.push_back(mapName);\
143  if(isEditable)\
144  {\
145  m_editableColumns.insert(counter);\
146  };\
147  m_variableVector.push_back(IVE);\
148  counter++;
149  ADDCOLUMN(wxT("#"), "imgNr", 35, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image number"))
150  ADDCOLUMN(_("Filename"), "filename", 200, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Filename"))
151  ADDCOLUMN(_("Width"), "width", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image width"))
152  ADDCOLUMN(_("Height"), "height", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image height"))
153  ADDCOLUMN(_("Anchor"), "anchor", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Anchor image for position and/or exposure"))
154  ADDCOLUMN(_("# Ctrl Pnts"), "cps", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Number of control points in this image"))
155  ADDCOLUMN(_("Lens no."), "lensNr", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Assigned lens number"))
156  ADDCOLUMN(_("Stack no."), "stackNr", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Assigned stack number"))
157 
158  ADDCOLUMN(_("Maker"), "maker", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera maker"))
159  ADDCOLUMN(_("Model"), "model", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera model"))
160  ADDCOLUMN(_("Lens"), "lens", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Used lens"))
161  ADDCOLUMN(_("Capture date"), "date", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Date, image was taken"))
162  ADDCOLUMN(_("Focal length"), "focallength", 80, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Focal length"))
163  ADDCOLUMN(_("Aperture"), "aperture", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Aperture"))
164  ADDCOLUMN(_("Shutter Speed"), "time", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Shutter speed"))
165  ADDCOLUMN(_("ISO"), "iso", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("ISO speed"))
166 
167  ADDCOLUMN(_("Yaw (y)"), "y", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Yaw"))
168  ADDCOLUMN(_("Pitch (p)"), "p", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Pitch"))
169  ADDCOLUMN(_("Roll (r)"), "r", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Roll"))
170  ADDCOLUMN(wxT("X (TrX)"), "TrX", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation X"))
171  ADDCOLUMN(wxT("Y (TrY)"), "TrY", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation Y"))
172  ADDCOLUMN(wxT("Z (TrZ)"), "TrZ", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation Z"))
173  ADDCOLUMN(_("Plane yaw"), "Tpy", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Translation remap plane yaw"))
174  ADDCOLUMN(_("Plane pitch"), "Tpp", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Translation remap plane pitch"))
175  ADDCOLUMN(_("Camera translation"), "cam_trans", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation"))
176 
177  ADDCOLUMN(_("Lens type (f)"), "projection", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Lens type (rectilinear, fisheye, equirectangular, ...)"))
178  ADDCOLUMN(_("Hfov (v)"), "v", 80, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_HFOV, _("Horizontal field of view (v)"))
179  ADDCOLUMN(wxT("a"), "a", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (a)"))
180  ADDCOLUMN(wxT("b"), "b", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (b, barrel)"))
181  ADDCOLUMN(wxT("c"), "c", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (c)"))
182  ADDCOLUMN(wxT("d"), "d", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortionCenterShift, _("Horizontal image center shift (d)"))
183  ADDCOLUMN(wxT("e"), "e", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortionCenterShift, _("Vertical image center shift (e)"))
184  ADDCOLUMN(wxT("g"), "g", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Shear, _("Horizontal image shearing (g)"))
185  ADDCOLUMN(wxT("t"), "t", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Shear, _("Vertical image shearing (t)"))
186 
187  ADDCOLUMN(wxT("EV"), "Eev", 50, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_ExposureValue, _("Exposure value (Eev)"))
188  ADDCOLUMN(wxT("Er"), "Er", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_WhiteBalanceRed, _("Red multiplier (Er)"))
189  ADDCOLUMN(wxT("Eb"), "Eb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_WhiteBalanceBlue, _("Blue multiplier (Eb)"))
190  ADDCOLUMN(wxT("Vb"), "Vb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
191  ADDCOLUMN(wxT("Vc"), "Vc", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
192  ADDCOLUMN(wxT("Vd"), "Vd", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
193  ADDCOLUMN(wxT("Vx"), "Vx", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift, _("Horizontal vignetting center shift (Vx)"))
194  ADDCOLUMN(wxT("Vy"), "Vy", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift, _("Vertical vignetting center shift (Vy)"))
195  ADDCOLUMN(_("Response type"), "response", 80, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera response type"))
196  ADDCOLUMN(wxT("Ra"), "Ra", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
197  ADDCOLUMN(wxT("Rb"), "Rb", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
198  ADDCOLUMN(wxT("Rc"), "Rc", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
199  ADDCOLUMN(wxT("Rd"), "Rd", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
200  ADDCOLUMN(wxT("Re"), "Re", 40, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
201 
202  //empty column to have enough space on the right side
203  AddColumn(wxEmptyString,10);
204 
205  //get saved width
206  for ( int j=0; j < GetColumnCount() ; j++ )
207  {
208  // -1 is auto
209  int width = wxConfigBase::Get()->Read(wxString::Format(m_configClassName+wxT("/ColumnWidth%d"), j ), -1);
210  if(width != -1)
211  SetColumnWidth(j, width);
212  }
213 };
214 
216 {
217  m_pano = panorama;
218  m_pano->addObserver(this);
219 
223 
224 #ifdef __WXMAC__
225  SetDropTarget(new PanoDropTarget(*m_pano, true));
226 #endif
227 }
228 
230 {
231  DEBUG_TRACE("");
232  m_pano->removeObserver(this);
233  delete m_variable_groups;
234 };
235 
237 {
238  if(m_optimizerMode)
239  {
240  Freeze();
242  Thaw();
243 #ifdef __WXGTK__
244  Refresh();
245 #endif
246  };
248  {
249  HuginBase::UIntSet imgs;
250  fill_set(imgs, 0, pano.getNrOfImages()-1);
251  panoramaImagesChanged(pano, imgs);
252  };
253  m_needsUpdate=true;
254 };
255 
257 {
258  DEBUG_TRACE("");
259 
260  Freeze();
261  HuginBase::UIntSet changedImgs(changed);
262  // Make sure the part numbers are up to date before writing them to the table.
263  size_t oldLensCount=m_variable_groups->getLenses().getNumberOfParts();
264  size_t oldStackCount=m_variable_groups->getStacks().getNumberOfParts();
266  //if the number of lenses or stacks have changed we need to update all images
267  //because the changed images set contains only the list of the changed imagges
268  //but not these images where the stack or lens number has changed because
269  //an images has been inserted
270  if(pano.getNrOfImages()>0)
271  {
272  if(m_variable_groups->getLenses().getNumberOfParts()!=oldLensCount ||
273  m_variable_groups->getStacks().getNumberOfParts()!=oldStackCount)
274  {
275  fill_set(changedImgs, 0, pano.getNrOfImages()-1);
276  };
277  };
278  if(m_optimizerMode)
279  {
281  {
283  };
285  {
287  };
288  };
290  {
291  HuginBase::UIntSet imgs;
292  if(m_pano->getNrOfImages()>0)
293  {
294  fill_set(imgs,0,m_pano->getNrOfImages()-1);
295  };
296  UpdateGroup(m_root,imgs,changedImgs);
297  }
298  else
299  {
300  HuginBase::UIntSetVector imageGroups;
301  switch (m_groupMode)
302  {
303  case GROUP_LENS:
304  imageGroups = m_variable_groups->getLenses().getPartsSet();
305  break;
306  case GROUP_STACK:
307  imageGroups = m_variable_groups->getStacks().getPartsSet();
308  break;
309  case GROUP_OUTPUTSTACK:
311  break;
312  case GROUP_OUTPUTLAYERS:
314  break;
315  };
316 
317  size_t nrItems=GetChildrenCount(m_root,false);
318  if(nrItems!=imageGroups.size())
319  {
320  if(nrItems<imageGroups.size())
321  {
322  for(size_t i=nrItems;i<imageGroups.size();i++)
323  {
324  AppendItem(m_root,wxEmptyString,-1,-1,new ImagesTreeData(-(long)i-1));
325  };
326  }
327  else
328  {
329  while(GetChildrenCount(m_root,false)>imageGroups.size())
330  {
331  wxTreeItemIdValue cookie;
332  wxTreeItemId item=GetLastChild(m_root,cookie);
333  Delete(item);
334  };
335  };
336  };
337 
338  wxTreeItemIdValue cookie;
339  wxTreeItemId item=GetFirstChild(m_root, cookie);
340  size_t i=0;
341  while(item.IsOk())
342  {
343  UpdateGroup(item,imageGroups[i++],changedImgs);
344  UpdateGroupText(item);
345  item=GetNextChild(m_root, cookie);
346  };
347  };
348  // updates checkboxes images for optimizer variables
349  if(m_optimizerMode)
350  {
352  };
354  {
355  UpdateItemFont();
356  };
357 
358  Thaw();
359  m_needsUpdate = false;
360 
361  // HACK! need to notify clients anyway... send dummy event..
362  // lets hope our clients query for the selected images with GetSelected()
363  // and do not try to interpret the event.
364  wxListEvent e;
365  e.SetEventType(wxEVT_COMMAND_LIST_ITEM_SELECTED);
366  e.m_itemIndex = -1;
367  GetEventHandler()->ProcessEvent(e);
368 }
369 
370 void ImagesTreeCtrl::UpdateImageText(wxTreeItemId item)
371 {
372  ImagesTreeData* itemData=static_cast<ImagesTreeData*>(GetItemData(item));
373  // NAMEisLinked returns always false, if the lens or stacks contains only a single image
374  // so add a special handling for this case
375  bool isSingleImage = false;
376  if (m_groupMode != GROUP_NONE)
377  {
378  isSingleImage = (GetChildrenCount(GetItemParent(item)) == 1);
379  };
380  wxString s;
381  const size_t imgNr=itemData->GetImgNr();
382  const HuginBase::SrcPanoImage & img = m_pano->getImage(imgNr);
383  wxFileName fn(wxString (img.getFilename().c_str(), HUGIN_CONV_FILENAME));
384 
385  s << imgNr;
386  SetItemText(item, m_columnMap["imgNr"], s);
387  s.Clear();
388  SetItemText(item, m_columnMap["filename"], fn.GetFullName() );
389  SetItemText(item, m_columnMap["width"], wxString::Format(wxT("%d"), img.getSize().width()));
390  SetItemText(item, m_columnMap["height"], wxString::Format(wxT("%d"), img.getSize().height()));
391 
392  wxChar flags[] = wxT("--");
393  if (m_pano->getOptions().optimizeReferenceImage == imgNr)
394  {
395  flags[0]='A';
396  }
397  if (m_pano->getOptions().colorReferenceImage == imgNr)
398  {
399  flags[1]='C';
400  }
401  SetItemText(item, m_columnMap["anchor"], wxString(flags, wxConvLocal));
402  std::vector<unsigned int> cps = m_pano->getCtrlPointsForImage(imgNr);
403  s << cps.size();
404  SetItemText(item, m_columnMap["cps"], s);
405  s.Clear();
406  const unsigned int stackNumber = m_variable_groups->getStacks().getPartNumber(imgNr);
407  SetItemText(item, m_columnMap["stackNr"], wxString::Format(wxT("%u"), stackNumber));
408  const unsigned int lensNr=m_variable_groups->getLenses().getPartNumber(imgNr);
409  SetItemText(item, m_columnMap["lensNr"], wxString::Format(wxT("%u"), lensNr));
410 
411  SetItemText(item, m_columnMap["maker"], wxString(img.getExifMake().c_str(), wxConvLocal));
412  SetItemText(item, m_columnMap["model"], wxString(img.getExifModel().c_str(), wxConvLocal));
413  SetItemText(item, m_columnMap["lens"], wxString(img.getExifLens().c_str(), wxConvLocal));
415  SetItemText(item, m_columnMap["focallength"], FormatString::GetFocalLength(&img));
416  SetItemText(item, m_columnMap["aperture"], FormatString::GetAperture(&img));
418  SetItemText(item, m_columnMap["iso"], FormatString::GetIso(&img));
419 
420  if (m_groupMode == GROUP_STACK && (img.YawisLinked() || isSingleImage))
421  {
422  SetItemText(item, m_columnMap["y"], wxEmptyString);
423  SetItemText(item, m_columnMap["p"], wxEmptyString);
424  SetItemText(item, m_columnMap["r"], wxEmptyString);
425  SetItemText(item, m_columnMap["TrX"], wxEmptyString);
426  SetItemText(item, m_columnMap["TrY"], wxEmptyString);
427  SetItemText(item, m_columnMap["TrZ"], wxEmptyString);
428  SetItemText(item, m_columnMap["Tpy"], wxEmptyString);
429  SetItemText(item, m_columnMap["Tpp"], wxEmptyString);
430  SetItemText(item, m_columnMap["cam_trans"], wxEmptyString);
431  }
432  else
433  {
440  SetItemText(item, m_columnMap["Tpy"], hugin_utils::doubleTowxString(img.getTranslationPlaneYaw(), m_degDigits));
441  SetItemText(item, m_columnMap["Tpp"], hugin_utils::doubleTowxString(img.getTranslationPlanePitch(), m_degDigits));
442  wxString text=_("not active");
443  if(img.getX()!=0.0 || img.getY()!=0.0 || img.getZ()!=0.0 || img.getTranslationPlaneYaw()!=0.0 || img.getTranslationPlanePitch()!=0.0)
444  {
445  text=_("active");
446  };
447  text.Prepend(wxT(" "));
448  SetItemText(item, m_columnMap["cam_trans"], text);
449  };
450 
452  {
453  SetItemText(item, m_columnMap["projection"], wxEmptyString);
454  SetItemText(item, m_columnMap["response"], wxEmptyString);
455  }
456  else
457  {
458  SetItemText(item, m_columnMap["projection"], getProjectionString(img));
459  SetItemText(item, m_columnMap["response"], getResponseString(img));
460  };
461 
462  if (m_groupMode == GROUP_LENS && (img.HFOVisLinked() || isSingleImage))
463  {
464  SetItemText(item, m_columnMap["v"], wxEmptyString);
465  }
466  else
467  {
469  };
470 
471  if (m_groupMode == GROUP_LENS && (img.RadialDistortionisLinked() || isSingleImage))
472  {
473  SetItemText(item, m_columnMap["a"], wxEmptyString);
474  SetItemText(item, m_columnMap["b"], wxEmptyString);
475  SetItemText(item, m_columnMap["c"], wxEmptyString);
476  }
477  else
478  {
479  std::vector<double> dist=img.getRadialDistortion();
483  };
484 
485  if (m_groupMode == GROUP_LENS && (img.RadialDistortionCenterShiftisLinked() || isSingleImage))
486  {
487  SetItemText(item, m_columnMap["d"], wxEmptyString);
488  SetItemText(item, m_columnMap["e"], wxEmptyString);
489  }
490  else
491  {
492  hugin_utils::FDiff2D p=img.getRadialDistortionCenterShift();
495  };
496 
497  if (m_groupMode == GROUP_LENS && (img.ShearisLinked() || isSingleImage))
498  {
499  SetItemText(item, m_columnMap["g"], wxEmptyString);
500  SetItemText(item, m_columnMap["t"], wxEmptyString);
501  }
502  else
503  {
504  hugin_utils::FDiff2D p=img.getShear();
507  };
508 
509  if (m_groupMode == GROUP_LENS && (img.ExposureValueisLinked() || isSingleImage))
510  {
511  SetItemText(item, m_columnMap["Eev"], wxEmptyString);
512  }
513  else
514  {
515  SetItemText(item, m_columnMap["Eev"], hugin_utils::doubleTowxString(img.getExposureValue(), m_pixelDigits));
516  };
517 
518  if (m_groupMode == GROUP_LENS && (img.WhiteBalanceRedisLinked() || isSingleImage))
519  {
520  SetItemText(item, m_columnMap["Er"], wxEmptyString);
521  }
522  else
523  {
524  SetItemText(item, m_columnMap["Er"], hugin_utils::doubleTowxString(img.getWhiteBalanceRed(), m_pixelDigits+1));
525  };
526 
527  if (m_groupMode == GROUP_LENS && (img.WhiteBalanceBlueisLinked() || isSingleImage))
528  {
529  SetItemText(item, m_columnMap["Eb"], wxEmptyString);
530  }
531  else
532  {
533  SetItemText(item, m_columnMap["Eb"], hugin_utils::doubleTowxString(img.getWhiteBalanceBlue(), m_pixelDigits+1));
534  };
535 
536  if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCoeffisLinked() || isSingleImage))
537  {
538  SetItemText(item, m_columnMap["Vb"], wxEmptyString);
539  SetItemText(item, m_columnMap["Vc"], wxEmptyString);
540  SetItemText(item, m_columnMap["Vd"], wxEmptyString);
541  }
542  else
543  {
544  std::vector<double> dist=img.getRadialVigCorrCoeff();
548  };
549 
550  if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCenterShiftisLinked() || isSingleImage))
551  {
552  SetItemText(item, m_columnMap["Vx"], wxEmptyString);
553  SetItemText(item, m_columnMap["Vy"], wxEmptyString);
554  }
555  else
556  {
557  hugin_utils::FDiff2D p=img.getRadialVigCorrCenterShift();
560  };
561 
562  if (m_groupMode == GROUP_LENS && (img.EMoRParamsisLinked() || isSingleImage))
563  {
564  SetItemText(item, m_columnMap["Ra"], wxEmptyString);
565  SetItemText(item, m_columnMap["Rb"], wxEmptyString);
566  SetItemText(item, m_columnMap["Rc"], wxEmptyString);
567  SetItemText(item, m_columnMap["Rd"], wxEmptyString);
568  SetItemText(item, m_columnMap["Re"], wxEmptyString);
569  }
570  else
571  {
572  if (img.getResponseType() == HuginBase::SrcPanoImage::RESPONSE_EMOR)
573  {
574  // display Ra..Re only when response type is emor
575  // otherwise they have no meaning
576  std::vector<float> vec = img.getEMoRParams();
582  }
583  else
584  {
585  SetItemText(item, m_columnMap["Ra"], wxEmptyString);
586  SetItemText(item, m_columnMap["Rb"], wxEmptyString);
587  SetItemText(item, m_columnMap["Rc"], wxEmptyString);
588  SetItemText(item, m_columnMap["Rd"], wxEmptyString);
589  SetItemText(item, m_columnMap["Re"], wxEmptyString);
590  };
591  };
592 };
593 
594 void ImagesTreeCtrl::UpdateGroupText(wxTreeItemId item)
595 {
596  ImagesTreeData* itemData=static_cast<ImagesTreeData*>(GetItemData(item));
597  switch(m_groupMode)
598  {
599  case GROUP_LENS:
600  SetItemText(item, 1, wxString::Format(_("Lens %ld"),itemData->GetGroupNr()));
601  break;
602  case GROUP_STACK:
603  SetItemText(item, 1, wxString::Format(_("Stack %ld"),itemData->GetGroupNr()));
604  break;
605  case GROUP_OUTPUTSTACK:
606  SetItemText(item, 1, wxString::Format(_("Output stack %ld"),itemData->GetGroupNr()));
607  break;
608  case GROUP_OUTPUTLAYERS:
609  SetItemText(item, 1, wxString::Format(_("Output exposure layer %ld"),itemData->GetGroupNr()));
610  break;
611  };
612  SetItemBold(item,1,true);
613  wxTreeItemIdValue cookie;
614  wxTreeItemId childItem=GetFirstChild(item,cookie);
615  // NAMEisLinked returns always false, if the lens or stacks contains only a single image
616  // so add a special handling for this case
617  bool haveSingleChild = false;
618  if (m_groupMode != GROUP_NONE)
619  {
620  haveSingleChild = (GetChildrenCount(item, false) == 1);
621  };
622  if(childItem.IsOk())
623  {
624  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(childItem));
625  const HuginBase::SrcPanoImage& img=m_pano->getImage(data->GetImgNr());
626 
627  if (m_groupMode == GROUP_STACK && (img.YawisLinked() || haveSingleChild))
628  {
635  SetItemText(item, m_columnMap["Tpy"], hugin_utils::doubleTowxString(img.getTranslationPlaneYaw(), m_degDigits));
636  SetItemText(item, m_columnMap["Tpp"], hugin_utils::doubleTowxString(img.getTranslationPlanePitch(), m_degDigits));
637  wxString text=_("not active");
638  if(img.getX()!=0.0 || img.getY()!=0.0 || img.getZ()!=0.0 || img.getTranslationPlaneYaw()!=0.0 || img.getTranslationPlanePitch()!=0.0)
639  {
640  text=_("active");
641  };
642  text.Prepend(wxT(" "));
643  SetItemText(item, m_columnMap["cam_trans"], text);
644  }
645  else
646  {
647  SetItemText(item, m_columnMap["y"], wxEmptyString);
648  SetItemText(item, m_columnMap["p"], wxEmptyString);
649  SetItemText(item, m_columnMap["r"], wxEmptyString);
650  SetItemText(item, m_columnMap["TrX"], wxEmptyString);
651  SetItemText(item, m_columnMap["TrY"], wxEmptyString);
652  SetItemText(item, m_columnMap["TrZ"], wxEmptyString);
653  SetItemText(item, m_columnMap["Tpy"], wxEmptyString);
654  SetItemText(item, m_columnMap["Tpp"], wxEmptyString);
655  SetItemText(item, m_columnMap["cam_trans"], wxEmptyString);
656  };
657 
659  {
660  SetItemText(item, m_columnMap["projection"], getProjectionString(img));
661  SetItemText(item, m_columnMap["response"], getResponseString(img));
662  }
663  else
664  {
665  SetItemText(item, m_columnMap["projection"], wxEmptyString);
666  SetItemText(item, m_columnMap["response"], wxEmptyString);
667  };
668 
669  if (m_groupMode == GROUP_LENS && (img.HFOVisLinked() || haveSingleChild))
670  {
672  }
673  else
674  {
675  SetItemText(item, m_columnMap["v"], wxEmptyString);
676  };
677 
678  if (m_groupMode == GROUP_LENS && (img.RadialDistortionisLinked() || haveSingleChild))
679  {
680  std::vector<double> dist=img.getRadialDistortion();
684  }
685  else
686  {
687  SetItemText(item, m_columnMap["a"], wxEmptyString);
688  SetItemText(item, m_columnMap["b"], wxEmptyString);
689  SetItemText(item, m_columnMap["c"], wxEmptyString);
690  };
691 
692  if (m_groupMode == GROUP_LENS && (img.RadialDistortionCenterShiftisLinked() || haveSingleChild))
693  {
694  hugin_utils::FDiff2D p=img.getRadialDistortionCenterShift();
697  }
698  else
699  {
700  SetItemText(item, m_columnMap["d"], wxEmptyString);
701  SetItemText(item, m_columnMap["e"], wxEmptyString);
702  };
703 
704  if (m_groupMode == GROUP_LENS && (img.ShearisLinked() || haveSingleChild))
705  {
706  hugin_utils::FDiff2D p=img.getShear();
709  }
710  else
711  {
712  SetItemText(item, m_columnMap["g"], wxEmptyString);
713  SetItemText(item, m_columnMap["t"], wxEmptyString);
714  };
715 
716  if (m_groupMode == GROUP_LENS && (img.ExposureValueisLinked() || haveSingleChild))
717  {
718  SetItemText(item, m_columnMap["Eev"], hugin_utils::doubleTowxString(img.getExposureValue(), m_pixelDigits));
719  }
720  else
721  {
722  SetItemText(item, m_columnMap["Eev"], wxEmptyString);
723  };
724 
725  if (m_groupMode == GROUP_LENS && (img.WhiteBalanceRedisLinked() || haveSingleChild))
726  {
727  SetItemText(item, m_columnMap["Er"], hugin_utils::doubleTowxString(img.getWhiteBalanceRed(), m_pixelDigits+1));
728  }
729  else
730  {
731  SetItemText(item, m_columnMap["Er"], wxEmptyString);
732  };
733 
734  if (m_groupMode == GROUP_LENS && (img.WhiteBalanceBlueisLinked() || haveSingleChild))
735  {
736  SetItemText(item, m_columnMap["Eb"], hugin_utils::doubleTowxString(img.getWhiteBalanceBlue(), m_pixelDigits+1));
737  }
738  else
739  {
740  SetItemText(item, m_columnMap["Eb"], wxEmptyString);
741  };
742 
743  if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCoeffisLinked() || haveSingleChild))
744  {
745  std::vector<double> dist=img.getRadialVigCorrCoeff();
749  }
750  else
751  {
752  SetItemText(item, m_columnMap["Vb"], wxEmptyString);
753  SetItemText(item, m_columnMap["Vc"], wxEmptyString);
754  SetItemText(item, m_columnMap["Vd"], wxEmptyString);
755  };
756 
757  if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCenterShiftisLinked() || haveSingleChild))
758  {
759  hugin_utils::FDiff2D p=img.getRadialVigCorrCenterShift();
762  }
763  else
764  {
765  SetItemText(item, m_columnMap["Vx"], wxEmptyString);
766  SetItemText(item, m_columnMap["Vy"], wxEmptyString);
767  };
768 
769  if (m_groupMode == GROUP_LENS && (img.getResponseType() == HuginBase::SrcPanoImage::RESPONSE_EMOR && (img.EMoRParamsisLinked()) || haveSingleChild))
770  {
771  std::vector<float> vec=img.getEMoRParams();
777  }
778  else
779  {
780  SetItemText(item, m_columnMap["Ra"], wxEmptyString);
781  SetItemText(item, m_columnMap["Rb"], wxEmptyString);
782  SetItemText(item, m_columnMap["Rc"], wxEmptyString);
783  SetItemText(item, m_columnMap["Rd"], wxEmptyString);
784  SetItemText(item, m_columnMap["Re"], wxEmptyString);
785  };
786  };
787 };
788 
789 void ImagesTreeCtrl::UpdateGroup(wxTreeItemId parent, const HuginBase::UIntSet imgs, HuginBase::UIntSet& changed)
790 {
791  size_t nrItems=GetChildrenCount(parent,false);
792  bool forceUpdate=false;
793  if(nrItems!=imgs.size())
794  {
795  forceUpdate=true;
796  if(nrItems<imgs.size())
797  {
798  for(size_t i=nrItems;i<imgs.size();i++)
799  {
800  AppendItem(parent,wxEmptyString,-1,-1,new ImagesTreeData(-1));
801  };
802  }
803  else
804  {
805  while(GetChildrenCount(parent,false)>imgs.size())
806  {
807  wxTreeItemIdValue cookie;
808  wxTreeItemId item=GetLastChild(parent,cookie);
809  Delete(item);
810  };
811  };
812  };
813  //now update values
814  wxTreeItemIdValue cookie;
815  wxTreeItemId item=GetFirstChild(parent,cookie);
816  HuginBase::UIntSet::const_iterator it=imgs.begin();
817  while(item.IsOk())
818  {
819  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
820  if(it==imgs.end())
821  {
822  break;
823  };
824  bool needsUpdate=false;
825  if(data->GetImgNr()!=*it)
826  {
827  data->SetImgNr(*it);
828  needsUpdate=true;
829  }
830  else
831  {
832  if(set_contains(changed,*it))
833  {
834  needsUpdate=true;
835  };
836  };
837  if(needsUpdate || forceUpdate)
838  {
839  UpdateImageText(item);
840  changed.erase(*it);
841  };
842  item=GetNextChild(parent, cookie);
843  ++it;
844  };
845 };
846 
848 {
850  wxTreeItemIdValue cookie;
851  wxTreeItemId item=GetFirstChild(m_root, cookie);
852  while(item.IsOk())
853  {
854  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
855  HuginBase::UIntSet imgNrs;
856  if(data->IsGroup())
857  {
858  wxTreeItemIdValue childCookie;
859  wxTreeItemId child=GetFirstChild(item, childCookie);
860  while(child.IsOk())
861  {
862  data=static_cast<ImagesTreeData*>(GetItemData(child));
863  imgNrs.insert(data->GetImgNr());
864  child=GetNextChild(item, childCookie);
865  };
866  }
867  else
868  {
869  imgNrs.insert(data->GetImgNr());
870  };
871  if(!imgNrs.empty())
872  {
873  for(size_t i=0;i<GetColumnCount();i++)
874  {
876  {
877  if (GetItemText(item, i).IsEmpty())
878  {
879  // item with no text can have no checkbox
880  // this can happen with linked variables
881  SetItemImage(item, i, -1);
882  }
883  else
884  {
885  bool opt=false;
886  for(HuginBase::UIntSet::const_iterator it=imgNrs.begin(); it!=imgNrs.end() && !opt;++it)
887  {
888  if(m_columnVector[i]=="cam_trans")
889  {
890  opt=set_contains(optVec[*it], "TrX") &&
891  set_contains(optVec[*it], "TrY") &&
892  set_contains(optVec[*it], "TrZ") &&
893  set_contains(optVec[*it], "Tpy") &&
894  set_contains(optVec[*it], "Tpp");
895  }
896  else
897  {
898  opt=set_contains(optVec[*it], m_columnVector[i]);
899  };
900  };
901  SetItemImage(item, i, opt ? 1 : 0);
902  };
903  };
904  };
905  };
906  item=GetNext(item);
907  };
908 };
909 
911 {
912  wxArrayTreeItemIds selected;
913  HuginBase::UIntSet imgs;
914  if(GetSelections (selected)>0)
915  {
916  for(size_t i=0;i<selected.size();i++)
917  {
918  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(selected[i]));
919  if(data->IsGroup())
920  {
921  wxTreeItemIdValue cookie;
922  wxTreeItemId item=GetFirstChild(selected[i],cookie);
923  while(item.IsOk())
924  {
925  data=static_cast<ImagesTreeData*>(GetItemData(item));
926  imgs.insert(data->GetImgNr());
927  item=GetNextChild(selected[i], cookie);
928  };
929  }
930  else
931  {
932  imgs.insert(data->GetImgNr());
933  };
934  };
935  }
936  return imgs;
937 }
938 
939 void ImagesTreeCtrl::MarkActiveImages(const bool markActive)
940 {
941  m_markDisabledImages = markActive;
942  UpdateItemFont();
943 };
944 
945 void ImagesTreeCtrl::OnColumnWidthChange( wxListEvent & e )
946 {
947  if(m_configClassName != wxT(""))
948  {
949  int colNum = e.GetColumn();
950  wxConfigBase::Get()->Write( m_configClassName+wxString::Format(wxT("/ColumnWidth%d"),colNum), GetColumnWidth(colNum) );
951  }
952 }
953 
955 {
956  m_guiLevel=newSetting;
957  //update visible column
959 };
960 
962 {
963  //create bitmaps for different checkboxes state
964  wxRendererNative& renderer = wxRendererNative::Get();
965  const wxSize checkBoxSize = renderer.GetCheckBoxSize(this);
966  wxImageList* checkboxImageList = new wxImageList(checkBoxSize.GetWidth(), checkBoxSize.GetHeight(), true, 0);
967  wxBitmap checkBoxImage(checkBoxSize, 32);
968  wxMemoryDC dc(checkBoxImage);
969  // unchecked checkbox
970  dc.Clear();
971  renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize));
972  dc.SelectObject(wxNullBitmap);
973  checkboxImageList->Add(checkBoxImage);
974  // checked checkbox
975  dc.SelectObject(checkBoxImage);
976  dc.Clear();
977  renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize), wxCONTROL_CHECKED);
978  dc.SelectObject(wxNullBitmap);
979  checkboxImageList->Add(checkBoxImage);
980  // mouse over unchecked checkbox
981  dc.SelectObject(checkBoxImage);
982  dc.Clear();
983  renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize), wxCONTROL_CURRENT);
984  dc.SelectObject(wxNullBitmap);
985  checkboxImageList->Add(checkBoxImage);
986  // mouse over checked checkbox
987  dc.SelectObject(checkBoxImage);
988  dc.Clear();
989  renderer.DrawCheckBox(this, dc, wxRect(checkBoxSize), wxCONTROL_CHECKED | wxCONTROL_CURRENT);
990  dc.SelectObject(wxNullBitmap);
991  checkboxImageList->Add(checkBoxImage);
992 
993  AssignImageList(checkboxImageList);
994 }
995 
997 {
998  m_optimizerMode=true;
999  // connnect events with handlers
1000  Bind(wxEVT_MOTION, &ImagesTreeCtrl::OnMouseMove, this);
1001  Bind(wxEVT_LEFT_DOWN, &ImagesTreeCtrl::OnLeftDown, this);
1002  // build image list with check box images
1004  // activate edit mode
1005  for(HuginBase::UIntSet::const_iterator it=m_editableColumns.begin(); it!=m_editableColumns.end(); ++it)
1006  {
1007  if(m_columnVector[*it]!="cam_trans")
1008  {
1009  SetColumnEditable(*it,true);
1010  };
1011  };
1012 }
1013 
1014 #if wxCHECK_VERSION(3,1,3)
1015 void ImagesTreeCtrl::OnDpiChanged(wxDPIChangedEvent& e)
1016 {
1017  // dpi has changed, we need to update the images of the checkboxes
1018  if (m_optimizerMode)
1019  {
1021  Refresh();
1022  };
1023 }
1024 #endif
1025 
1027 {
1028  if(newGroup!=m_groupMode)
1029  {
1030  m_groupMode=newGroup;
1031  if(m_groupMode==GROUP_NONE)
1032  {
1033  SetWindowStyle(GetWindowStyle() | wxTR_NO_LINES);
1034  }
1035  else
1036  {
1037  SetWindowStyle(GetWindowStyle() & ~wxTR_NO_LINES);
1038  };
1040  HuginBase::UIntSet imgs;
1041  if(m_pano->getNrOfImages()>0)
1042  {
1043  fill_set(imgs,0,m_pano->getNrOfImages()-1);
1044  };
1046  // reset already modified tag
1047  m_needsUpdate = true;
1048  ExpandAll(m_root);
1049  };
1050 };
1051 
1053 {
1054  m_displayMode=newMode;
1055 
1062 
1071 
1081 
1091 
1106 
1107  Refresh();
1108 };
1109 
1110 void ImagesTreeCtrl::OnContextMenu(wxTreeEvent & e)
1111 {
1112  m_selectedColumn=e.GetInt();
1113  wxMenu menu;
1114  bool allowMenuExtension=true;
1115  if(e.GetItem().IsOk())
1116  {
1117  //click on item
1119  {
1120  bool emptyText=GetItemText(e.GetItem(),m_selectedColumn).IsEmpty();
1121  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
1122  bool varIsLinkable = false;
1123  if (m_groupMode == GROUP_LENS)
1124  {
1125  varIsLinkable = m_variableVector[m_selectedColumn] != HuginBase::ImageVariableGroup::IVE_Yaw &&
1127  }
1128  else
1129  {
1130  if (m_groupMode == GROUP_STACK)
1131  {
1132  varIsLinkable = m_variableVector[m_selectedColumn] == HuginBase::ImageVariableGroup::IVE_Yaw;
1133  }
1134  };
1135  if(varIsLinkable)
1136  {
1137  if(data->IsGroup())
1138  {
1139  if(emptyText)
1140  {
1141  menu.Append(ID_LINK,_("Link"));
1142  }
1143  else
1144  {
1145  menu.Append(ID_UNLINK, _("Unlink"));
1146  };
1147  }
1148  else
1149  {
1150  if(emptyText)
1151  {
1152  menu.Append(ID_UNLINK,_("Unlink"));
1153  }
1154  else
1155  {
1156  menu.Append(ID_LINK, _("Link"));
1157  };
1158  };
1159  menu.AppendSeparator();
1160  };
1161  if(m_optimizerMode)
1162  {
1163  if(data->IsGroup() == emptyText)
1164  {
1165  if(m_groupMode==GROUP_LENS && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Yaw)
1166  {
1167  menu.Append(ID_SELECT_LENS_STACK, _("Select all for current lens"));
1168  menu.Append(ID_UNSELECT_LENS_STACK, _("Unselect all for current lens"));
1169  };
1170  if(m_groupMode==GROUP_STACK && m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw)
1171  {
1172  menu.Append(ID_SELECT_LENS_STACK, _("Select all for current stack"));
1173  menu.Append(ID_UNSELECT_LENS_STACK, _("Unselect all for current stack"));
1174  };
1175  };
1176  if(m_columnVector[m_selectedColumn]!="cam_trans")
1177  {
1178  menu.Append(ID_SELECT_ALL, _("Select all"));
1179  };
1180  menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
1181  menu.AppendSeparator();
1182  }
1183  };
1184  menu.Append(ID_EDIT, _("Edit image variables..."));
1186  {
1187  const HuginBase::UIntSet selectedImages = GetSelectedImages();
1188  if (selectedImages.size() == 1)
1189  {
1190  if (m_pano->getImage(*selectedImages.begin()).getActive())
1191  {
1192  menu.Append(ID_DEACTIVATE_IMAGE, _("Deactivate image"));
1193  }
1194  else
1195  {
1196  menu.Append(ID_ACTIVATE_IMAGE, _("Activate image"));
1197  };
1198  }
1199  else
1200  {
1201  menu.Append(ID_ACTIVATE_IMAGE, _("Activate images"));
1202  menu.Append(ID_DEACTIVATE_IMAGE, _("Deactivate images"));
1203  };
1204  };
1205  }
1206  else
1207  {
1208  if(m_optimizerMode && set_contains(m_editableColumns, e.GetInt()))
1209  {
1210  if(m_columnVector[m_selectedColumn]!="cam_trans")
1211  {
1212  menu.Append(ID_SELECT_ALL, _("Select all"));
1213  };
1214  menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
1215  allowMenuExtension=false;
1216  }
1217  };
1218  if(allowMenuExtension)
1219  {
1220  if(menu.GetMenuItemCount()>0)
1221  {
1222  menu.AppendSeparator();
1223  };
1224  int id=ID_OPERATION_START;
1225  m_menuOperation.clear();
1227  wxMenu* subMenu=new wxMenu();
1229  if(subMenu->GetMenuItemCount()>0)
1230  {
1231  menu.Append(-1,_("Lens"), subMenu);
1232  }
1233  else
1234  {
1235  delete subMenu;
1236  };
1238  {
1239  subMenu=new wxMenu();
1241  if(subMenu->GetMenuItemCount()>0)
1242  {
1243  menu.Append(-1,_("Stacks"), subMenu);
1244  }
1245  else
1246  {
1247  delete subMenu;
1248  };
1249  };
1250  subMenu=new wxMenu();
1252  if(subMenu->GetMenuItemCount()>0)
1253  {
1254  menu.Append(-1, _("Control points"), subMenu);
1255  }
1256  else
1257  {
1258  delete subMenu;
1259  };
1260  subMenu=new wxMenu();
1262  if(subMenu->GetMenuItemCount()>0)
1263  {
1264  menu.Append(-1, _("Reset"), subMenu);
1265  }
1266  else
1267  {
1268  delete subMenu;
1269  };
1270  };
1271  if(menu.GetMenuItemCount()>0)
1272  {
1273  PopupMenu(&menu);
1274  };
1275  e.Skip();
1276 };
1277 
1279 {
1281  for(size_t i=0; i<operations->size(); i++)
1282  {
1283  if((*operations)[i]->IsEnabled(*m_pano, imgs, m_guiLevel))
1284  {
1285  menu->Append(id, (*operations)[i]->GetLabel());
1286  m_menuOperation[id]=(*operations)[i];
1287  id++;
1288  }
1289  };
1290 }
1291 
1293 {
1294  const wxColour normalColour = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
1295  const wxColour disabledColour = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
1297  {
1298  wxTreeItemIdValue cookie;
1299  wxTreeItemId item = GetFirstChild(m_root, cookie);
1300  while (item.IsOk())
1301  {
1302  ImagesTreeData* itemData = static_cast<ImagesTreeData*>(GetItemData(item));
1303  bool isActive = true;
1304  if (itemData->IsGroup())
1305  {
1306  wxTreeItemIdValue childCookie;
1307  wxTreeItemId child = GetFirstChild(item, childCookie);
1308  while (child.IsOk())
1309  {
1310  ImagesTreeData* childItemData = static_cast<ImagesTreeData*>(GetItemData(child));
1311  isActive = m_pano->getImage(childItemData->GetImgNr()).getActive();
1312  if (isActive)
1313  {
1314  break;
1315  };
1316  child = GetNextChild(item, childCookie);
1317  };
1318  }
1319  else
1320  {
1321  isActive = m_pano->getImage(itemData->GetImgNr()).getActive();
1322  };
1323  if (isActive)
1324  {
1325  SetItemTextColour(item, normalColour);
1326  }
1327  else
1328  {
1329  SetItemTextColour(item, disabledColour);
1330  };
1331  if(itemData->IsGroup())
1332  {
1333  wxTreeItemIdValue childCookie;
1334  wxTreeItemId child = GetFirstChild(item, childCookie);
1335  while (child.IsOk())
1336  {
1337  ImagesTreeData* childItemData = static_cast<ImagesTreeData*>(GetItemData(child));
1338  if (m_pano->getImage(childItemData->GetImgNr()).getActive())
1339  {
1340  SetItemTextColour(child, normalColour);
1341  }
1342  else
1343  {
1344  SetItemTextColour(child, disabledColour);
1345  };
1346  child = GetNextChild(item, childCookie);
1347  };
1348  };
1349  item = GetNextChild(m_root, cookie);
1350  };
1351  }
1352  else
1353  {
1354  wxTreeItemIdValue cookie;
1355  wxTreeItemId item = GetFirstChild(m_root, cookie);
1356  while (item.IsOk())
1357  {
1358  ImagesTreeData* itemData=static_cast<ImagesTreeData*>(GetItemData(item));
1359  SetItemTextColour(item, normalColour);
1360  if (itemData->IsGroup())
1361  {
1362  wxTreeItemIdValue childCookie;
1363  wxTreeItemId child = GetFirstChild(item, childCookie);
1364  while (child.IsOk())
1365  {
1366  SetItemTextColour(child, normalColour);
1367  child = GetNextChild(item, childCookie);
1368  };
1369  };
1370  item = GetNextChild(m_root, cookie);
1371  };
1372  };
1373 };
1374 
1376 {
1377  m_selectedColumn=e.GetColumn();
1378  wxMenu menu;
1380  {
1381  menu.Append(ID_SELECT_ALL, _("Select all"));
1382  menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
1383  PopupMenu(&menu);
1384  };
1385  e.Skip();
1386 }
1387 void ImagesTreeCtrl::OnActivateImage(wxCommandEvent & e)
1388 {
1389  HuginBase::UIntSet activeImages = m_pano->getActiveImages();
1390  const HuginBase::UIntSet selectedImages = GetSelectedImages();
1391  std::copy(selectedImages.begin(), selectedImages.end(), std::inserter(activeImages, activeImages.end()));
1393  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
1394  );
1395 };
1396 
1397 void ImagesTreeCtrl::OnDeactivateImage(wxCommandEvent & e)
1398 {
1399  HuginBase::UIntSet activeImages = m_pano->getActiveImages();
1400  const HuginBase::UIntSet selectedImages = GetSelectedImages();
1401  HuginBase::UIntSet newActiveImages;
1402  std::set_difference(activeImages.begin(), activeImages.end(), selectedImages.begin(), selectedImages.end(), std::inserter(newActiveImages, newActiveImages.end()));
1404  new PanoCommand::SetActiveImagesCmd(*m_pano, newActiveImages)
1405  );
1406 };
1407 
1409 {
1411  if(!images.empty() && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Filename)
1412  {
1413  std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
1414  variables.insert(m_variableVector[m_selectedColumn]);
1415  if(m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw)
1416  {
1417  variables.insert(HuginBase::ImageVariableGroup::IVE_Pitch);
1418  variables.insert(HuginBase::ImageVariableGroup::IVE_Roll);
1419  variables.insert(HuginBase::ImageVariableGroup::IVE_X);
1420  variables.insert(HuginBase::ImageVariableGroup::IVE_Y);
1421  variables.insert(HuginBase::ImageVariableGroup::IVE_Z);
1422  variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw);
1423  variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch);
1424  };
1425  if(m_groupMode==GROUP_LENS)
1426  {
1429  );
1430  }
1431  else
1432  {
1435  );
1436  };
1437  };
1438 };
1439 
1441 {
1442  UnLinkImageVariables(true);
1443 };
1444 
1446 {
1447  UnLinkImageVariables(false);
1448 };
1449 
1451 {
1453  if(!imgs.empty())
1454  {
1455  ImageVariableDialog dlg(this, m_pano, imgs);
1456  dlg.SetGuiLevel(m_guiLevel);
1457  switch(m_displayMode)
1458  {
1459  case DISPLAY_LENS:
1460  dlg.SelectTab(1);
1461  break;
1462  case DISPLAY_PHOTOMETRICS:
1465  if(m_selectedColumn==m_columnMap["response"] ||
1466  m_selectedColumn==m_columnMap["Ra"] ||
1467  m_selectedColumn==m_columnMap["Rb"] ||
1468  m_selectedColumn==m_columnMap["Rc"] ||
1469  m_selectedColumn==m_columnMap["Rd"] ||
1470  m_selectedColumn==m_columnMap["Re"] )
1471  {
1472  dlg.SelectTab(3);
1473  }
1474  else
1475  {
1476  dlg.SelectTab(2);
1477  };
1478  break;
1479  default:
1480  break;
1481  };
1482  dlg.ShowModal();
1483  };
1484 };
1485 
1486 void ImagesTreeCtrl::OnBeginDrag(wxTreeEvent &e)
1487 {
1488  const bool ctrlPressed=wxGetKeyState(WXK_COMMAND);
1489  if(m_pano->getNrOfImages()>0 && !m_dragging)
1490  {
1492  if(!m_draggingImages.empty())
1493  {
1494  if((m_groupMode==GROUP_NONE && m_draggingImages.size()==1 && !ctrlPressed) ||
1496  {
1497  e.Allow();
1498  SetCursor(wxCURSOR_HAND);
1499  m_dragging=true;
1500  };
1501  };
1502  };
1503 };
1504 
1505 void ImagesTreeCtrl::OnLeftUp(wxMouseEvent &e)
1506 {
1507  //we can't use wxEVT_TREE_END_DRAG because this event is fire several times, e.g. when
1508  // the mouse leaves the area of the tree
1509  // so we are listing to left mouse up, as described in documentation
1510  if(m_dragging)
1511  {
1512  SetCursor(wxCURSOR_ARROW);
1513  m_dragging=false;
1514  wxTreeItemId item=HitTest(e.GetPosition());
1515  if(m_groupMode==GROUP_NONE)
1516  {
1517  size_t img1=*m_draggingImages.begin();
1518  size_t img2=-1;
1519  if(item.IsOk())
1520  {
1521  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
1522  img2=data->GetImgNr();
1523  }
1524  else
1525  {
1526  //we are checking the points above, if we find then
1527  // an item, the user drop it below the last item, if not
1528  // the drop happened right beside the item
1529  wxPoint pos(e.GetPosition());
1530  pos.y-=10;
1531  while(pos.y>0)
1532  {
1533  item=HitTest(pos);
1534  if(item.IsOk())
1535  {
1536  img2=m_pano->getNrOfImages()-1;
1537  break;
1538  };
1539  pos.y-=10;
1540  };
1541  };
1542  if(img2!=-1)
1543  {
1544  if(img1!=img2)
1545  {
1547  new PanoCommand::MoveImageCmd(*m_pano, img1, img2)
1548  );
1549  // now update drag images groups in fast preview window, this information is not stored in Panorama class
1551  if (!images.empty() && images.size() < m_pano->getNrOfImages())
1552  {
1553  std::vector<bool> imgList(m_pano->getNrOfImages(), false);
1554  for (auto& i : images)
1555  {
1556  imgList[i] = true;
1557  };
1558  const bool moveImageChecked = imgList[img1];
1559  imgList.erase(imgList.begin() + img1);
1560  if (img2 < imgList.size())
1561  {
1562  imgList.insert(imgList.begin() + img2, moveImageChecked);
1563  }
1564  else
1565  {
1566  imgList.push_back(moveImageChecked);
1567  };
1568  images.clear();
1569  for (size_t i = 0; i < imgList.size(); ++i)
1570  {
1571  if (imgList[i])
1572  {
1573  images.insert(i);
1574  };
1575  };
1576  MainFrame::Get()->getGLPreview()->SetDragGroupImages(images, true);
1577  };
1578  };
1579  };
1580  }
1581  else
1582  {
1583  //dragging to stack/lenses
1584  if(item.IsOk())
1585  {
1586  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
1587  long groupNr=-1;
1588  if(data->IsGroup())
1589  {
1590  groupNr=data->GetGroupNr();
1591  }
1592  else
1593  {
1594  item=GetItemParent(item);
1595  if(item.IsOk())
1596  {
1597  data=static_cast<ImagesTreeData*>(GetItemData(item));
1598  groupNr=data->GetGroupNr();
1599  };
1600  };
1601  if(groupNr>=0)
1602  {
1603  if(m_groupMode==GROUP_LENS)
1604  {
1607  );
1608  }
1609  else
1610  {
1613  );
1614  };
1615  };
1616  }
1617  else // item not ok, drop not on existing item, create new lens/stack
1618  {
1619  if(m_groupMode==GROUP_LENS)
1620  {
1623  );
1624  }
1625  else
1626  {
1629  );
1630  }
1631  };
1632  }
1633  m_draggingImages.clear();
1634  }
1635  else
1636  {
1637  if (m_optimizerMode && m_leftDownItem.IsOk())
1638  {
1639  int flags;
1640  int col;
1641  wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
1642  // check if left up is on the same item as left down
1643  if (item.IsOk() && item == m_leftDownItem && col == m_leftDownColumn && (flags & wxTREE_HITTEST_ONITEMICON))
1644  {
1645  HuginBase::UIntSet imgs;
1646  const bool markSelected = IsSelected(m_leftDownItem);
1647  if (markSelected)
1648  {
1649  // if the user clicked on one of the selected pass the selection to all selected images
1650  imgs = GetSelectedImages();
1651  }
1652  else
1653  {
1654  // the user clicked on a non-selected images, work only on this image
1655  // or all images of the clicked lens/stack
1657  if (data->IsGroup())
1658  {
1659  wxTreeItemIdValue cookie;
1660  wxTreeItemId childItem = GetFirstChild(m_leftDownItem, cookie);
1661  while (childItem.IsOk())
1662  {
1663  data = static_cast<ImagesTreeData*>(GetItemData(childItem));
1664  imgs.insert(data->GetImgNr());
1665  childItem = GetNextChild(m_leftDownItem, cookie);
1666  };
1667  }
1668  else
1669  {
1670  imgs.insert(data->GetImgNr());
1671  };
1672  };
1674  std::set<std::string> var;
1675  if (m_columnVector[m_leftDownColumn] == "cam_trans")
1676  {
1677  var.insert("TrX");
1678  var.insert("TrY");
1679  var.insert("TrZ");
1680  var.insert("Tpy");
1681  var.insert("Tpp");
1682  }
1683  else
1684  {
1685  var.insert(m_columnVector[m_leftDownColumn]);
1686  if (m_columnVector[m_leftDownColumn] == "Tpy" || m_columnVector[m_leftDownColumn] == "Tpp")
1687  {
1688  var.insert("Tpy");
1689  var.insert("Tpp");
1690  };
1691  if (m_columnVector[m_leftDownColumn] == "Vb" || m_columnVector[m_leftDownColumn] == "Vc" || m_columnVector[m_leftDownColumn] == "Vd")
1692  {
1693  var.insert("Vb");
1694  var.insert("Vc");
1695  var.insert("Vd");
1696  };
1697  if (m_columnVector[m_leftDownColumn] == "Vx" || m_columnVector[m_leftDownColumn] == "Vy")
1698  {
1699  var.insert("Vx");
1700  var.insert("Vy");
1701  };
1702  if (m_columnVector[m_leftDownColumn] == "Ra" || m_columnVector[m_leftDownColumn] == "Rb" || m_columnVector[m_leftDownColumn] == "Rc" ||
1703  m_columnVector[m_leftDownColumn] == "Rd" || m_columnVector[m_leftDownColumn] == "Re")
1704  {
1705  var.insert("Ra");
1706  var.insert("Rb");
1707  var.insert("Rc");
1708  var.insert("Rd");
1709  var.insert("Re");
1710  };
1711  };
1712  bool deactivate = false;
1713  if (markSelected)
1714  {
1715  // check which state the clicked image have
1716  deactivate = GetItemImage(m_leftDownItem, m_leftDownColumn) & 1;
1717  }
1718  else
1719  {
1720  for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
1721  {
1722  //search, if image variable is marked for optimise for at least one image of group
1723  for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end() && !deactivate; ++imgIt)
1724  {
1725  if (set_contains(optVec[*imgIt], *varIt))
1726  {
1727  deactivate = true;
1728  };
1729  };
1730  };
1731  };
1732  // now deactivate or activate the image variable for optimisation
1733  if (deactivate)
1734  {
1735  for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
1736  {
1737  for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end(); ++imgIt)
1738  {
1739  optVec[*imgIt].erase(*varIt);
1740  };
1741  }
1742  }
1743  else
1744  {
1745  for (std::set<std::string>::const_iterator varIt = var.begin(); varIt != var.end(); ++varIt)
1746  {
1747  for (HuginBase::UIntSet::const_iterator imgIt = imgs.begin(); imgIt != imgs.end(); ++imgIt)
1748  {
1749  optVec[*imgIt].insert(*varIt);
1750  };
1751  };
1752  };
1755  );
1756  m_leftDownItem.Unset();
1757  return;
1758  };
1759  };
1760  if (m_leftDownItem.IsOk())
1761  {
1762  m_leftDownItem.Unset();
1763  };
1764  e.Skip();
1765  };
1766 };
1767 
1768 void ImagesTreeCtrl::OnLeftDown(wxMouseEvent &e)
1769 {
1770  if (!m_dragging)
1771  {
1772  if (e.LeftDown())
1773  {
1774  // force end editing
1775  EndEdit(false);
1776  // find where user clicked
1777  int flags;
1778  int col;
1779  wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
1780  if (item.IsOk() && (flags & wxTREE_HITTEST_ONITEMICON))
1781  {
1782  if (set_contains(m_editableColumns, col))
1783  {
1784  if (!GetItemText(item, col).IsEmpty())
1785  {
1786  // store for later and stop processing this event further
1787  m_leftDownItem = item;
1788  m_leftDownColumn = col;
1789  return;
1790  };
1791  };
1792  };
1793  };
1794  };
1795  e.Skip();
1796 };
1797 
1798 void ImagesTreeCtrl::OnMouseMove(wxMouseEvent &e)
1799 {
1800  int flags;
1801  int col;
1802  wxTreeItemId item = HitTest(e.GetPosition(), flags, col);
1803  if (item.IsOk() && (flags & wxTREE_HITTEST_ONITEMICON))
1804  {
1805  // mouse moved over optimizer checkbox
1806  int imgNr = GetItemImage(item, col);
1807  if (imgNr >= 0 && imgNr < 2)
1808  {
1809  // update checkbox image and store position for later
1810  SetItemImage(item, col, imgNr + 2);
1811  m_lastCurrentItem = item;
1812  m_lastCurrentCol = col;
1813  };
1814  }
1815  else
1816  {
1817  // mouse moved from checkbox away, so update images
1818  if (m_lastCurrentItem.IsOk())
1819  {
1821  if (imgNr > 1)
1822  {
1824  };
1825  m_lastCurrentItem.Unset();
1826  };
1827  };
1828  e.Skip();
1829 };
1830 
1831 void ImagesTreeCtrl::SelectAllParameters(bool select, bool allImages)
1832 {
1833  std::set<std::string> imgVars;
1834  std::string var=m_columnVector[m_selectedColumn];
1835  if(var=="cam_trans")
1836  {
1837  imgVars.insert("TrX");
1838  imgVars.insert("TrY");
1839  imgVars.insert("TrZ");
1840  imgVars.insert("Tpy");
1841  imgVars.insert("Tpp");
1842  }
1843  else
1844  {
1845  imgVars.insert(var);
1846  if(var=="Vb" || var=="Vc" || var=="Vd")
1847  {
1848  imgVars.insert("Vb");
1849  imgVars.insert("Vc");
1850  imgVars.insert("Vd");
1851  };
1852  if(var=="Vx" || var=="Vy")
1853  {
1854  imgVars.insert("Vx");
1855  imgVars.insert("Vy");
1856  };
1857  if(var=="Ra" || var=="Rb" || var=="Rc" || var=="Rd" || var=="Re")
1858  {
1859  imgVars.insert("Ra");
1860  imgVars.insert("Rb");
1861  imgVars.insert("Rc");
1862  imgVars.insert("Rd");
1863  imgVars.insert("Re");
1864  };
1865 
1866  };
1867 
1868  HuginBase::UIntSet imgs;
1869  if(allImages)
1870  {
1871  fill_set(imgs, 0, m_pano->getNrOfImages()-1);
1872  }
1873  else
1874  {
1875  wxArrayTreeItemIds selectedItem;
1876  if(GetSelections(selectedItem)>0)
1877  {
1878  for(size_t i=0;i<selectedItem.size();i++)
1879  {
1880  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(selectedItem[i]));
1881  wxTreeItemId startItem;
1882  if(data->IsGroup())
1883  {
1884  startItem=selectedItem[i];
1885  }
1886  else
1887  {
1888  startItem=GetItemParent(selectedItem[i]);
1889  };
1890  wxTreeItemIdValue cookie;
1891  wxTreeItemId item=GetFirstChild(startItem,cookie);
1892  while(item.IsOk())
1893  {
1894  data=static_cast<ImagesTreeData*>(GetItemData(item));
1895  imgs.insert(data->GetImgNr());
1896  item=GetNextChild(startItem, cookie);
1897  };
1898  };
1899  };
1900  };
1901 
1903  for(HuginBase::UIntSet::iterator img=imgs.begin(); img!=imgs.end(); ++img)
1904  {
1905  for(std::set<std::string>::const_iterator it=imgVars.begin(); it!=imgVars.end(); ++it)
1906  {
1907  if(select)
1908  {
1909  if((*it=="y" || *it=="p" || *it=="r" || *it=="TrX" || *it=="TrY" || *it=="TrZ" || *it=="Tpy" || *it=="Tpp") &&
1911  {
1912  optVec[*img].erase(*it);
1913  continue;
1914  };
1915  if(*it=="Eev" && (*img==m_pano->getOptions().colorReferenceImage || m_pano->getImage(*img).ExposureValueisLinkedWith(m_pano->getImage(m_pano->getOptions().colorReferenceImage))))
1916  {
1917  optVec[*img].erase(*it);
1918  continue;
1919  };
1920  if (*it == "Er" && (*img == m_pano->getOptions().colorReferenceImage || m_pano->getImage(*img).WhiteBalanceRedisLinkedWith(m_pano->getImage(m_pano->getOptions().colorReferenceImage))))
1921  {
1922  optVec[*img].erase(*it);
1923  continue;
1924  };
1925  if (*it == "Eb" && (*img == m_pano->getOptions().colorReferenceImage || m_pano->getImage(*img).WhiteBalanceBlueisLinkedWith(m_pano->getImage(m_pano->getOptions().colorReferenceImage))))
1926  {
1927  optVec[*img].erase(*it);
1928  continue;
1929  };
1930  optVec[*img].insert(*it);
1931  }
1932  else
1933  {
1934  optVec[*img].erase(*it);
1935  };
1936  };
1937  };
1940  );
1941 };
1942 
1943 void ImagesTreeCtrl::OnSelectAll(wxCommandEvent &e)
1944 {
1945  SelectAllParameters(true, true);
1946 };
1947 
1948 void ImagesTreeCtrl::OnUnselectAll(wxCommandEvent &e)
1949 {
1950  SelectAllParameters(false, true);
1951 };
1952 
1953 void ImagesTreeCtrl::OnSelectLensStack(wxCommandEvent &e)
1954 {
1955  SelectAllParameters(true, false);
1956 };
1957 
1959 {
1960  SelectAllParameters(false, false);
1961 };
1962 
1963 void ImagesTreeCtrl::OnChar(wxTreeEvent &e)
1964 {
1965  switch(e.GetKeyCode())
1966  {
1967  case WXK_INSERT:
1968  {
1969  wxCommandEvent ev(wxEVT_COMMAND_MENU_SELECTED, XRCID("action_add_images"));
1970  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
1971  break;
1972  };
1973  case WXK_DELETE:
1974  {
1976  if(!imgs.empty())
1977  {
1978  // remove all marked images from cache
1979  for (auto& img : imgs)
1980  {
1981  ImageCache::getInstance().removeImage(m_pano->getImage(img).getFilename());
1982  };
1983  // now remove images from panorama object
1986  );
1987  };
1988  break;
1989  };
1990 #if defined __WXMAC__
1991  case 'A':
1992  case 'a':
1993  // check for cmd+A -> select all
1994  if (e.GetExtraLong() == wxMOD_CMD)
1995  {
1996  SelectAll();
1997  };
1998  break;
1999 #endif
2000  case 1: //Ctrl+A
2001  {
2002  SelectAll();
2003  break;
2004  }
2005  default:
2006  e.Skip();
2007  };
2008 };
2009 
2010 void ImagesTreeCtrl::OnBeginEdit(wxTreeEvent &e)
2011 {
2012  m_editOldString=GetItemText(e.GetItem(), e.GetInt());
2013  if(m_editOldString.IsEmpty())
2014  {
2015  e.Veto();
2016  }
2017  else
2018  {
2019  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
2020  if(data->IsGroup())
2021  {
2022  wxTreeItemIdValue cookie;
2023  wxTreeItemId item=GetFirstChild(e.GetItem(), cookie);
2024  data=static_cast<ImagesTreeData*>(GetItemData(item));
2025  };
2026  m_editVal=m_pano->getImage(data->GetImgNr()).getVar(m_columnVector[e.GetInt()]);
2027  SetItemText(e.GetItem(), e.GetInt(), hugin_utils::doubleTowxString(m_editVal));
2028  e.Allow();
2029  };
2030 };
2031 
2032 void ImagesTreeCtrl::OnEndEdit(wxTreeEvent &e)
2033 {
2034  if(e.IsEditCancelled())
2035  {
2036  //restore old string
2037  SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
2038  Refresh();
2039  }
2040  else
2041  {
2042  double val;
2043  if(!hugin_utils::str2double(e.GetLabel(),val))
2044  {
2045  //restore old string
2046  SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
2047  Refresh();
2048  e.Veto();
2049  }
2050  else
2051  {
2052  //only update if value was changed
2053  if(val!=m_editVal)
2054  {
2055  ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
2056  if(data->IsGroup())
2057  {
2058  wxTreeItemIdValue cookie;
2059  wxTreeItemId item=GetFirstChild(e.GetItem(), cookie);
2060  data=static_cast<ImagesTreeData*>(GetItemData(item));
2061  };
2062  HuginBase::UIntSet imgs;
2063  imgs.insert(data->GetImgNr());
2064  if(m_columnVector[e.GetInt()]=="v")
2065  {
2066  if(m_pano->getImage(data->GetImgNr()).getProjection()==HuginBase::SrcPanoImage::FISHEYE_ORTHOGRAPHIC && val>190)
2067  {
2068  if(wxMessageBox(
2069  wxString::Format(_("You have given a field of view of %.2f degrees.\n But the orthographic projection is limited to a field of view of 180 degress.\nDo you want still use that high value?"), val),
2070 #ifdef __WXMSW__
2071  _("Hugin"),
2072 #else
2073  wxT(""),
2074 #endif
2075  wxICON_EXCLAMATION | wxYES_NO)==wxNO)
2076  {
2077  //restore old string
2078  SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
2079  Refresh();
2080  e.Veto();
2081  e.Skip();
2082  return;
2083  };
2084  };
2085  };
2086  HuginBase::Variable var(m_columnVector[e.GetInt()], val);
2088  new PanoCommand::SetVariableCmd(*m_pano, imgs, var)
2089  );
2090  //we need to veto the event otherwise the internal
2091  //function does update the text to the full number
2092  e.Veto();
2093  }
2094  else
2095  {
2096  //restore old string
2097  SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
2098  Refresh();
2099  };
2100  };
2101  };
2102  e.Skip();
2103 };
2104 
2105 void ImagesTreeCtrl::OnExecuteOperation(wxCommandEvent & e)
2106 {
2109  if(cmd!=NULL)
2110  {
2112  };
2113 };
2114 
2115 void ImagesTreeCtrl::OnLeftDblClick(wxMouseEvent &e)
2116 {
2117  if(!m_optimizerMode)
2118  {
2119  int flags;
2120  int col;
2121  wxTreeItemId item=HitTest(e.GetPosition(), flags, col);
2122  m_selectedColumn=col;
2123  wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, ID_EDIT);
2124  GetEventHandler()->AddPendingEvent(commandEvent);
2125  };
2126  e.Skip();
2127 };
2128 
2129 IMPLEMENT_DYNAMIC_CLASS(ImagesTreeCtrl, wxTreeListCtrl)
2130 
2132  : wxTreeListCtrlXmlHandler()
2133 {
2134 }
2135 
2137 {
2138  XRC_MAKE_INSTANCE(cp, ImagesTreeCtrl)
2139 
2140  cp->Create(m_parentAsWindow,
2141  GetID(),
2142  GetPosition(), GetSize(),
2143  GetStyle(wxT("style")),
2144  GetName());
2145 
2146  SetupWindow( cp);
2147 
2148  return cp;
2149 }
2150 
2152 {
2153  return IsOfClass(node, wxT("ImagesTreeList"));
2154 }
2155 
2156 IMPLEMENT_DYNAMIC_CLASS(ImagesTreeCtrlXmlHandler, wxTreeListCtrlXmlHandler)
2157 
2158 
HuginBase::UIntSet GetDragGroupImages()
ImagesTreeCtrl()
general constructor
Definition: ImagesTree.cpp:100
Base class for all panorama commands.
Definition: Command.h:38
void Refresh(bool erase=TRUE, const wxRect *rect=NULL)
std::map< std::string, size_t > m_columnMap
map for easier access to column information
Definition: ImagesTree.h:190
static const std::set< ConstImageVariableGroup::ImageVariableEnum > & getLensVariables()
Get the set of lens image variables.
void OnChar(wxTreeEvent &e)
event handler for key events
GroupMode m_groupMode
the active group mode
Definition: ImagesTree.h:172
std::vector< UIntSet > getHDRStacks(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output stacks
Definition: LayerStacks.cpp:35
implementation of huginApp Class
declaration of functions to handle stacks and layers
void SetGroupMode(GroupMode newMode)
sets the group mode to given mode
std::vector< UIntSet > UIntSetVector
Definition: PanoramaData.h:56
std::vector< UIntSet > getExposureLayers(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output exposure layers
Definition: LayerStacks.cpp:96
void OnHeaderContextMenu(wxListEvent &e)
event handler for context menu on header
size_t GetChildrenCount(const wxTreeItemId &item, bool recursively=true)
move image from position1 to position2
Definition: PanoCommand.h:361
virtual PanoCommand::PanoCommand * GetCommand(wxWindow *parent, HuginBase::Panorama &pano, HuginBase::UIntSet images, GuiLevel guiLevel)
returns the appropriate PanoCommand::PanoCommand to be inserted into GlobalCmdHistory, checks if operation is enabled
unsigned int getPartNumber(unsigned int imageNr) const
Get a part number from an image number.
Change the linking of some variables across parts of an ImageVariableGroup containing some specified ...
Definition: PanoCommand.h:524
virtual wxObject * DoCreateResource()
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
void OnEndEdit(wxTreeEvent &e)
event handler for ending editing, updates the Panorama with modified value
void OnLeftDown(wxMouseEvent &e)
event handler for left mouse down, handles toggle of optimizer variables
void OnExecuteOperation(wxCommandEvent &e)
menu event handler for PanoOperation (context menu items)
void OnLeftUp(wxMouseEvent &e)
event handler for left up, handles end of dragging and updates of optimizer variables states ...
DisplayMode m_displayMode
the active display mode
Definition: ImagesTree.h:188
void SetGuiLevel(GuiLevel newLevel)
sets the GuiLevel
declaration of main image tree control
void SetColumnWidth(int column, int width)
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
ImageVariableGroup & getStacks()
Get the ImageVariableGroup representing the group of stack variables.
bool m_dragging
true, if dragging
Definition: ImagesTree.h:204
void UpdateGroup(wxTreeItemId parent, const HuginBase::UIntSet imgs, HuginBase::UIntSet &changed)
updates the given group, updates number of images and the images itself
Definition: ImagesTree.cpp:789
#define DEBUG_TRACE(msg)
Definition: utils.h:67
std::vector< HuginBase::ImageVariableGroup::ImageVariableEnum > m_variableVector
vector for easier access to linking information
Definition: ImagesTree.h:196
Somewhere to specify what variables belong to what.
wxTreeItemId AppendItem(const wxTreeItemId &parent, const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
void OnUnlinkImageVariables(wxCommandEvent &e)
event handler for unlinking image variables
wxTreeItemId m_root
pointer to root item, not shown
Definition: ImagesTree.h:213
void SetColumnShown(int column, bool shown=true)
some helper classes for graphes
wxTreeItemData * GetItemData(const wxTreeItemId &item) const
void EndEdit(bool isCancelled)
wxTreeItemId AddRoot(const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
void SetImgNr(long newImgNr)
Definition: ImagesTree.cpp:91
virtual void panoramaChanged(HuginBase::Panorama &pano)
receives notification about panorama changes
Definition: ImagesTree.cpp:236
wxString doubleTowxString(double d, int digits)
Definition: wxPlatform.cpp:31
void SelectTab(size_t i)
selects the tab with index i
void DeleteChildren(const wxTreeItemId &item)
a variable has a value and a name.
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
simple class that forward the drop to the mainframe
Definition: MainFrame.h:65
END_EVENT_TABLE()
include file for the hugin project
void AssignImageList(wxImageList *imageList)
void SetColumnEditable(int column, bool edit=true)
wxTreeItemId GetLastChild(const wxTreeItemId &item, wxTreeItemIdValue &cookie) const
wxTreeItemId GetItemParent(const wxTreeItemId &item) const
long m_leftDownColumn
Definition: ImagesTree.h:220
wxTreeItemId GetFirstChild(const wxTreeItemId &item, wxTreeItemIdValue &cookie) const
bool m_markDisabledImages
true, if disabled images should be marked with other font color
Definition: ImagesTree.h:186
void OnDeactivateImage(wxCommandEvent &e)
event handler for deactivate image
wxTreeItemId HitTest(const wxPoint &point)
Definition: treelistctrl.h:490
void OnLeftDblClick(wxMouseEvent &e)
event handler for left double click
Declare the ImageVariableGroup and ImageVariableGroupObserver classes.
void Init(HuginBase::Panorama *pano)
initialization, connects all control with Panorama, register observer
Definition: ImagesTree.cpp:215
wxTreeItemId m_leftDownItem
stores where left mouse click happend
Definition: ImagesTree.h:219
long m_lastCurrentCol
Definition: ImagesTree.h:217
#define ADDCOLUMN(header, mapName, width, align, isEditable, IVE, tooltip)
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
void OnContextMenu(wxTreeEvent &e)
event handler to display context menu
DisplayMode
enumeration for display mode, limits the displayed columns
Definition: ImagesTree.h:49
wxString getResponseString(const HuginBase::SrcPanoImage &img)
Returns translated response type for given SrcPanoImage.
Definition: LensTools.cpp:125
void OnLinkImageVariables(wxCommandEvent &e)
event handler for linking image variables
bool m_needsUpdate
helper variable for update of output stacks/layers
Definition: ImagesTree.h:210
wxTreeItemId GetNext(const wxTreeItemId &item) const
void SetItemImage(const wxTreeItemId &item, int image, wxTreeItemIcon which=wxTreeItemIcon_Normal)
updates the optimize vector, aka all variables which should be optimized
Definition: PanoCommand.h:201
Model for a panorama.
Definition: Panorama.h:152
void MarkActiveImages(const bool markActive)
sets the flag, if active/disabled image should be marked with different colour
Definition: ImagesTree.cpp:939
empirical model of response
Definition: SrcPanoImage.h:100
UIntSetVector getPartsSet() const
return a vector which contains a HuginBase::UIntSet for each group with the corresponding images numb...
void OnBeginEdit(wxTreeEvent &e)
event handler for beginning editing
void UpdateImageText(wxTreeItemId item)
updates the information for the given image in tree
Definition: ImagesTree.cpp:370
wxString m_configClassName
Definition: ImagesTree.h:223
const OptimizeVector & getOptimizeVector() const
return the optimize settings stored inside panorama
Definition: Panorama.h:454
void SetDisplayMode(DisplayMode newMode)
sets the display mode to given mode
Make a new part in a ImageVariableGroup for a set of images, given the variables that make up the gro...
Definition: PanoCommand.h:591
Definition of dialog to edit image variables.
const long GetGroupNr() const
Definition: ImagesTree.cpp:92
bool IsSelected(const wxTreeItemId &item) const
void SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box=true)
void UnLinkImageVariables(bool linked)
helper procedure for link/unlink image variables
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
static MainFrame * Get()
hack.. kind of a pseudo singleton...
Definition: MainFrame.cpp:2181
std::vector< unsigned int > getCtrlPointsForImage(unsigned int imgNr) const
return all control points for a given image.
Definition: Panorama.cpp:83
GroupMode
enumeration for grouping mode
Definition: ImagesTree.h:40
ImagesTreeData(const long &nr)
Definition: ImagesTree.cpp:89
PanoOperationVector * GetLensesOperationVector()
returns list of PanoOperation for work with lenses
double m_editVal
value, which is currently edited
Definition: ImagesTree.h:206
Switch the part number of an image.
Definition: PanoCommand.h:506
PanoOperationVector * GetControlPointsOperationVector()
returns list of PanoOperation for work with control points
base class for different PanoOperations derived classes should overwrite protected PanoOperation::Get...
Definition: PanoOperation.h:39
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
ImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables.
void SetItemBold(const wxTreeItemId &item, bool bold=true)
void AddColumn(const wxString &text, int width=DEFAULT_COL_WIDTH, int flag=wxALIGN_LEFT, int image=-1, bool shown=true, bool edit=false, const wxString &tooltip=wxEmptyString)
Definition: treelistctrl.h:219
std::vector< std::string > m_columnVector
vector for easier access to column information
Definition: ImagesTree.h:192
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name=wxT("panel"))
creates the control
Definition: ImagesTree.cpp:112
void OnColumnWidthChange(wxListEvent &e)
event handler, when column width was changed, save into wxConfig
Definition: ImagesTree.cpp:945
wxTreeItemId GetNextChild(const wxTreeItemId &item, wxTreeItemIdValue &cookie) const
static GlobalCmdHist & getInstance()
HuginBase::Panorama * m_pano
Definition: ImagesTree.h:170
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
bool m_optimizerMode
true, if in optimizer mode
Definition: ImagesTree.h:184
wxTreeItemId m_lastCurrentItem
stores last item on which the mouse was hovering
Definition: ImagesTree.h:216
void SetGuiLevel(GuiLevel newSetting)
sets the GuiLevel of the control
Definition: ImagesTree.cpp:954
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
const bool IsGroup() const
Definition: ImagesTree.cpp:93
wxString GetExposureTime(const HuginBase::SrcPanoImage *img)
returns formatted exposure time
Definition: LensTools.cpp:554
update a single variable, possibly for a group of images
Definition: PanoCommand.h:236
HuginBase::UIntSet GetSelectedImages()
returns the selected images
Definition: ImagesTree.cpp:910
void OnEditImageVariables(wxCommandEvent &e)
event handler for showing image variables editing dialog
void SetItemTextColour(const wxTreeItemId &item, const wxColour &colour)
void OnSelectAll(wxCommandEvent &e)
event handler for select all optimizer variables
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
void OnSelectLensStack(wxCommandEvent &e)
event handler for select all optimizer variables for selected lens/stack
size_t m_selectedColumn
selected column
Definition: ImagesTree.h:200
include file for the hugin project
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
std::map< int, PanoOperation::PanoOperation * > m_menuOperation
map with current active context menu PanoOperation
Definition: ImagesTree.h:198
void OnBeginDrag(wxTreeEvent &e)
event handler when dragging begins, veto if dragging is not possible
wxString GetExifDateTime(const HuginBase::SrcPanoImage *img)
returns Exif DateTimeOriginal as formatted wxString
Definition: LensTools.cpp:503
the main images tree control, used on images and optimizer tabs
Definition: ImagesTree.h:36
GLPreviewFrame * getGLPreview()
Definition: MainFrame.cpp:2262
options wxIntPtr wxIntPtr sortData std::vector< PanoInfo > * data
void OnActivateImage(wxCommandEvent &e)
event handler for activate image
void OnMouseMove(wxMouseEvent &e)
event handler for mouse motion, handles focussing of check boxes
void GenerateSubMenu(wxMenu *menu, PanoOperation::PanoOperationVector *operations, int &id)
generates submenu for given PanoOperationVector
int GetItemImage(const wxTreeItemId &item, wxTreeItemIcon which=wxTreeItemIcon_Normal) const
GuiLevel m_guiLevel
stores the active GuiLevel
Definition: ImagesTree.h:182
wxString m_editOldString
wxString, as shown before editing started
Definition: ImagesTree.h:208
PanoOperationVector * GetResetOperationVector()
returns list of PanoOperation for resetting
void update()
Update part numbers for each variable group.
void SelectAllParameters(bool select, bool allImages)
select/unselect all variables in the active column true selects all, false unselect all true works ...
PanoOperationVector * GetImagesOperationVector()
returns list of PanoOperation for work with images
platform/compiler specific stuff.
size_t GetSelections(wxArrayTreeItemIds &) const
std::vector< std::set< std::string > > OptimizeVector
std::vector< PanoOperation * > PanoOperationVector
HuginBase::StandardImageVariableGroups * m_variable_groups
Definition: ImagesTree.h:175
void ExpandAll(const wxTreeItemId &item)
HuginBase::UIntSet m_draggingImages
UIntSet of dragging images.
Definition: ImagesTree.h:202
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
remove multiple images from a panorama
Definition: PanoCommand.h:94
GuiLevel
Definition: GuiLevel.h:31
void UpdateGroupText(wxTreeItemId item)
updates the information fot the given lens/stack in the tree
Definition: ImagesTree.cpp:594
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition: stl_utils.h:81
wxString GetFocalLength(const HuginBase::SrcPanoImage *img)
return focallength and focallength 35 mm as wxString
Definition: LensTools.cpp:519
static uint16_t flags
void UpdateItemFont()
update the font colour for all items
void OnUnselectLensStack(wxCommandEvent &e)
event handler for unselect all optimizer variables for selected lens/stack
std::size_t getNumberOfParts() const
get the number of parts.
All variables of a source image.
Definition: SrcPanoImage.h:194
PanoOperationVector * GetStacksOperationVector()
returns list of PanoOperation for stacks
wxString GetAperture(const HuginBase::SrcPanoImage *img)
returns formatted aperture value
Definition: LensTools.cpp:540
wxString GetItemText(const wxTreeItemId &item) const
Definition: treelistctrl.h:281
HuginBase::UIntSet m_editableColumns
set, which contains editable columns (all column which contains numeric image variables ...
Definition: ImagesTree.h:194
virtual bool CanHandle(wxXmlNode *node)
wxString getProjectionString(const HuginBase::SrcPanoImage &img)
Returns translated projection for given image.
Definition: LensTools.cpp:107
const long GetImgNr() const
Definition: ImagesTree.cpp:90
static const std::set< ConstImageVariableGroup::ImageVariableEnum > & getStackVariables()
Get the set of stack image variables.
void CreateColumns()
creates all columns and stores information in m_columnMap, m_columnVector, m_editableColumns and m_va...
Definition: ImagesTree.cpp:136
wxString GetIso(const HuginBase::SrcPanoImage *img)
returns formatted iso value
Definition: LensTools.cpp:591
void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &imgNr)
receive the update signal and update display accordingly
Definition: ImagesTree.cpp:256
void SetItemText(const wxTreeItemId &item, const wxString &text)
void Delete(const wxTreeItemId &item)
void OnUnselectAll(wxCommandEvent &e)
event handler for unselect all optimizer variables
void UpdateOptimizerVariables()
updates the display of the optimizer variables (set font)
Definition: ImagesTree.cpp:847
void CreateCheckboxImages()
create image list with necessary images of checkboxes
Definition: ImagesTree.cpp:961
int GetColumnWidth(int column) const
Dialog for editing image variables.
void SetOptimizerMode()
sets to control into optimizer mode
Definition: ImagesTree.cpp:996
virtual ~ImagesTreeCtrl(void)
destructor
Definition: ImagesTree.cpp:229