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