ImagesTree.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00010 /*  This program is free software; you can redistribute it and/or
00011  *  modify it under the terms of the GNU General Public
00012  *  License as published by the Free Software Foundation; either
00013  *  version 2 of the License, or (at your option) any later version.
00014  *
00015  *  This software is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  *  General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public
00021  *  License along with this software. If not, see
00022  *  <http://www.gnu.org/licenses/>.
00023  *
00024  */
00025 
00026 #include <config.h>
00027 #include "panoinc_WX.h"
00028 #include "panoinc.h"
00029 
00030 #include "base_wx/wxPlatform.h"
00031 #include "base_wx/LensTools.h"
00032 #include "hugin/ImagesTree.h"
00033 #include "base_wx/wxImageCache.h"
00034 #include "base_wx/platform.h"
00035 #include "hugin_base/algorithms/basic/LayerStacks.h"
00036 #include <panodata/ImageVariableGroup.h>
00037 #include <panodata/StandardImageVariableGroups.h>
00038 #include "base_wx/CommandHistory.h"
00039 #include "base_wx/PanoCommand.h"
00040 #include <hugin_utils/stl_utils.h>
00041 #include "hugin/ImageVariableDialog.h"
00042 #include "hugin/huginApp.h"
00043 
00044 enum
00045 {
00046     ID_LINK=wxID_HIGHEST+230,
00047     ID_UNLINK,
00048     ID_EDIT,
00049     ID_SELECT_ALL,
00050     ID_UNSELECT_ALL,
00051     ID_SELECT_LENS_STACK,
00052     ID_UNSELECT_LENS_STACK,
00053     ID_OPERATION_START=wxID_HIGHEST+300
00054 };
00055 
00056 BEGIN_EVENT_TABLE(ImagesTreeCtrl, wxTreeListCtrl)
00057     EVT_LIST_COL_END_DRAG(-1, ImagesTreeCtrl::OnColumnWidthChange)
00058     EVT_TREE_ITEM_MENU(-1, ImagesTreeCtrl::OnContextMenu)
00059     EVT_LIST_COL_RIGHT_CLICK(-1, ImagesTreeCtrl::OnHeaderContextMenu)
00060     EVT_MENU(ID_LINK, ImagesTreeCtrl::OnLinkImageVariables)
00061     EVT_MENU(ID_UNLINK, ImagesTreeCtrl::OnUnlinkImageVariables)
00062     EVT_MENU(ID_EDIT, ImagesTreeCtrl::OnEditImageVariables)
00063     EVT_MENU(ID_SELECT_ALL, ImagesTreeCtrl::OnSelectAll)
00064     EVT_MENU(ID_UNSELECT_ALL, ImagesTreeCtrl::OnUnselectAll)
00065     EVT_MENU(ID_SELECT_LENS_STACK, ImagesTreeCtrl::OnSelectLensStack)
00066     EVT_MENU(ID_UNSELECT_LENS_STACK, ImagesTreeCtrl::OnUnselectLensStack)
00067     EVT_MENU_RANGE(ID_OPERATION_START, ID_OPERATION_START+50, ImagesTreeCtrl::OnExecuteOperation)
00068     EVT_TREE_BEGIN_DRAG(-1, ImagesTreeCtrl::OnBeginDrag)
00069     EVT_LEFT_UP(ImagesTreeCtrl::OnEndDrag)
00070     EVT_LEFT_DOWN(ImagesTreeCtrl::OnLeftDown)
00071     EVT_LEFT_DCLICK(ImagesTreeCtrl::OnLeftDblClick)
00072     EVT_TREE_KEY_DOWN(-1, ImagesTreeCtrl::OnChar)
00073     EVT_TREE_BEGIN_LABEL_EDIT(-1, ImagesTreeCtrl::OnBeginEdit)
00074     EVT_TREE_END_LABEL_EDIT(-1, ImagesTreeCtrl::OnEndEdit)
00075 END_EVENT_TABLE()
00076 
00077 class ImagesTreeData : public wxTreeItemData
00078 {
00079 public:
00080     explicit ImagesTreeData(const long& nr) : m_nr(nr) { };
00081     const long GetImgNr() const { return m_nr;};
00082     void SetImgNr(long newImgNr) { m_nr=newImgNr;};
00083     const long GetGroupNr() const { return -(m_nr+1);};
00084     const bool IsGroup() const { return (m_nr<0); };
00085 
00086 private:
00087     long m_nr;
00088 };
00089 
00090 // Define a constructor for the Images Panel
00091 ImagesTreeCtrl::ImagesTreeCtrl()
00092 {
00093     m_pano = NULL;
00094     m_groupMode=GROUP_NONE;
00095     m_guiLevel=GUI_SIMPLE;
00096     m_dragging=false;
00097     m_displayMode=DISPLAY_GENERAL;
00098     m_optimizerMode=false;
00099     m_needsUpdate=true;
00100 }
00101 
00102 bool ImagesTreeCtrl::Create(wxWindow* parent, wxWindowID id,
00103                         const wxPoint& pos,
00104                         const wxSize& size,
00105                         long style,
00106                         const wxString& name)
00107 {
00108     DEBUG_TRACE("List");
00109     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) )
00110     {
00111         return false;
00112     }
00113 
00114     DEBUG_TRACE("Tree, adding columns");
00115     m_configClassName = wxT("/ImagesTree");
00116     CreateColumns();
00117     DEBUG_TRACE("");
00118     m_degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigits"),1);
00119     m_pixelDigits = wxConfigBase::Get()->Read(wxT("/General/PixelFractionalDigits"),1);
00120     m_distDigits = wxConfigBase::Get()->Read(wxT("/General/DistortionFractionalDigits"),3);
00121     //create root
00122     m_root=AddRoot(wxT("root"));
00123     return true;
00124 }
00125 
00126 void ImagesTreeCtrl::CreateColumns()
00127 {
00128     size_t counter=0;
00129 #define ADDCOLUMN(header, mapName, width, align, isEditable, IVE, tooltip) \
00130     AddColumn(header, width, align, -1, true, false, tooltip);\
00131     m_columnMap[mapName]=counter;\
00132     m_columnVector.push_back(mapName);\
00133     if(isEditable)\
00134     {\
00135         m_editableColumns.insert(counter);\
00136     };\
00137     m_variableVector.push_back(IVE);\
00138     counter++;
00139     ADDCOLUMN(wxT("#"), "imgNr", 35, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image number"))
00140     ADDCOLUMN(_("Filename"), "filename", 200, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Filename"))
00141     ADDCOLUMN(_("Width"), "width", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image width"))
00142     ADDCOLUMN(_("Height"), "height", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Image height"))
00143     ADDCOLUMN(_("Anchor"), "anchor", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Anchor image for position and/or exposure"))
00144     ADDCOLUMN(_("# Ctrl Pnts"), "cps", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Number of control points in this image"))
00145     ADDCOLUMN(_("Lens no."), "lensNr", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Assigned lens number"))
00146     ADDCOLUMN(_("Stack no."), "stackNr", 60, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Assigned stack number"))
00147 
00148     ADDCOLUMN(_("Maker"), "maker", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera maker"))
00149     ADDCOLUMN(_("Model"), "model", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera model"))
00150     ADDCOLUMN(_("Lens"), "lens", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Used lens"))
00151     ADDCOLUMN(_("Capture date"), "date", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Date, image was taken"))
00152     ADDCOLUMN(_("Focal length"), "focallength", 80, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Focal length"))
00153     ADDCOLUMN(_("Aperture"), "aperture", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Aperture"))
00154     ADDCOLUMN(_("Shutter Speed"), "time", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Shutter speed"))
00155     ADDCOLUMN(_("ISO"), "iso", 50, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("ISO speed"))
00156 
00157     ADDCOLUMN(_("Yaw (y)"), "y", 60, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Yaw"))
00158     ADDCOLUMN(_("Pitch (p)"), "p", 60, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Pitch"))
00159     ADDCOLUMN(_("Roll (r)"), "r", 60, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Roll"))
00160     ADDCOLUMN(wxT("X (TrX)"), "TrX", 60, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation X"))
00161     ADDCOLUMN(wxT("Y (TrY)"), "TrY", 60, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation Y"))
00162     ADDCOLUMN(wxT("Z (TrZ)"), "TrZ", 60, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation Z"))
00163     ADDCOLUMN(_("Plane yaw"), "Tpy", 60, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Translation remap plane yaw"))
00164     ADDCOLUMN(_("Plane pitch"), "Tpp", 60, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Translation remap plane pitch"))
00165     ADDCOLUMN(_("Camera translation"), "cam_trans", 60, wxALIGN_LEFT, true, HuginBase::ImageVariableGroup::IVE_Yaw, _("Camera translation"))
00166 
00167     ADDCOLUMN(_("Lens type (f)"), "projection", 100, wxALIGN_LEFT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Lens type (rectilinear, fisheye, equirectangular, ...)"))
00168     ADDCOLUMN(_("Hfov (v)"), "v", 80, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_HFOV, _("Horizontal field of view (v)"))
00169     ADDCOLUMN(wxT("a"), "a", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (a)"))
00170     ADDCOLUMN(wxT("b"), "b", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (b, barrel)"))
00171     ADDCOLUMN(wxT("c"), "c", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortion, _("Radial distortion (c)"))
00172     ADDCOLUMN(wxT("d"), "d", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortionCenterShift, _("Horizontal image center shift (d)"))
00173     ADDCOLUMN(wxT("e"), "e", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialDistortionCenterShift, _("Vertical image center shift (e)"))
00174     ADDCOLUMN(wxT("g"), "g", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Shear, _("Horizontal image shearing (g)"))
00175     ADDCOLUMN(wxT("t"), "t", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_Shear, _("Vertical image shearing (t)"))
00176 
00177     ADDCOLUMN(wxT("EV"), "Eev", 50, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_ExposureValue, _("Exposure value (Eev)"))
00178     ADDCOLUMN(wxT("Er"), "Er", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_WhiteBalanceRed, _("Red multiplier (Er)"))
00179     ADDCOLUMN(wxT("Eb"), "Eb", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_WhiteBalanceBlue, _("Blue multiplier (Eb)"))
00180     ADDCOLUMN(wxT("Vb"), "Vb", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
00181     ADDCOLUMN(wxT("Vc"), "Vc", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
00182     ADDCOLUMN(wxT("Vd"), "Vd", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, _("Vignetting (Vb, Vc, Vd)"))
00183     ADDCOLUMN(wxT("Vx"), "Vx", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift, _("Horizontal vignetting center shift (Vx)"))
00184     ADDCOLUMN(wxT("Vy"), "Vy", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift, _("Vertical vignetting center shift (Vy)"))
00185     ADDCOLUMN(_("Response type"), "response", 80, wxALIGN_RIGHT, false, HuginBase::ImageVariableGroup::IVE_Filename, _("Camera response type"))
00186     ADDCOLUMN(wxT("Ra"), "Ra", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00187     ADDCOLUMN(wxT("Rb"), "Rb", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00188     ADDCOLUMN(wxT("Rc"), "Rc", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00189     ADDCOLUMN(wxT("Rd"), "Rd", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00190     ADDCOLUMN(wxT("Re"), "Re", 40, wxALIGN_RIGHT, true, HuginBase::ImageVariableGroup::IVE_EMoRParams, _("Camera response parameter"))
00191 
00192     //empty column to have enough space on the right side
00193     AddColumn(wxEmptyString,10);
00194 
00195     //get saved width
00196     for ( int j=0; j < GetColumnCount() ; j++ )
00197     {
00198         // -1 is auto
00199         int width = wxConfigBase::Get()->Read(wxString::Format(m_configClassName+wxT("/ColumnWidth%d"), j ), -1);
00200         if(width != -1)
00201             SetColumnWidth(j, width);
00202     }
00203 };
00204 
00205 void ImagesTreeCtrl::Init(HuginBase::Panorama * panorama)
00206 {
00207     m_pano = panorama;
00208     m_pano->addObserver(this);
00209     
00211     m_variable_groups = new HuginBase::StandardImageVariableGroups(*m_pano);
00212     DEBUG_ASSERT(m_variable_groups);
00213     
00214 #ifdef __WXMAC__
00215     SetDropTarget(new PanoDropTarget(*m_pano, true));
00216 #endif
00217 }
00218 
00219 ImagesTreeCtrl::~ImagesTreeCtrl(void)
00220 {
00221     DEBUG_TRACE("");
00222     m_pano->removeObserver(this);
00223     delete m_variable_groups;
00224 };
00225 
00226 void ImagesTreeCtrl::panoramaChanged(HuginBase::Panorama & pano)
00227 {
00228     if(m_optimizerMode)
00229     {
00230         Freeze();
00231         UpdateOptimizerVariables();
00232         Thaw();
00233     };
00234     if(m_needsUpdate && (m_groupMode==GROUP_OUTPUTLAYERS || m_groupMode==GROUP_OUTPUTSTACK))
00235     {
00236         HuginBase::UIntSet imgs;
00237         fill_set(imgs, 0, pano.getNrOfImages()-1);
00238         panoramaImagesChanged(pano, imgs);
00239     };
00240     m_needsUpdate=true;
00241 };
00242 
00243 void ImagesTreeCtrl::panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
00244 {
00245     DEBUG_TRACE("");
00246 
00247     Freeze();
00248     HuginBase::UIntSet changedImgs(changed);
00249     // Make sure the part numbers are up to date before writing them to the table.
00250     size_t oldLensCount=m_variable_groups->getLenses().getNumberOfParts();
00251     size_t oldStackCount=m_variable_groups->getStacks().getNumberOfParts();
00252     m_variable_groups->update();
00253     //if the number of lenses or stacks have changed we need to update all images
00254     //because the changed images set contains only the list of the changed imagges
00255     //but not these images where the stack or lens number has changed because
00256     //an images has been inserted
00257     if(pano.getNrOfImages()>0)
00258     {
00259         if(m_variable_groups->getLenses().getNumberOfParts()!=oldLensCount ||
00260             m_variable_groups->getStacks().getNumberOfParts()!=oldStackCount)
00261         {
00262             fill_set(changedImgs, 0, pano.getNrOfImages()-1);
00263         };
00264     };
00265     if(m_optimizerMode)
00266     {
00267         if(m_groupMode==GROUP_NONE && m_pano->getNrOfImages()>m_variable_groups->getStacks().getNumberOfParts())
00268         {
00269             SetGroupMode(GROUP_STACK);
00270         };
00271         if(m_groupMode==GROUP_STACK && m_pano->getNrOfImages()==m_variable_groups->getStacks().getNumberOfParts())
00272         {
00273             SetGroupMode(GROUP_NONE);
00274         };
00275     };
00276     if(m_groupMode==GROUP_NONE)
00277     {
00278         HuginBase::UIntSet imgs;
00279         if(m_pano->getNrOfImages()>0)
00280         {
00281             fill_set(imgs,0,m_pano->getNrOfImages()-1);
00282         };
00283         UpdateGroup(m_root,imgs,changedImgs);
00284     }
00285     else
00286     {
00287         HuginBase::UIntSetVector imageGroups;
00288         switch (m_groupMode)
00289         {
00290             case GROUP_LENS:
00291                 imageGroups = m_variable_groups->getLenses().getPartsSet();
00292                 break;
00293             case GROUP_STACK:
00294                 imageGroups = m_variable_groups->getStacks().getPartsSet();
00295                 break;
00296             case GROUP_OUTPUTSTACK:
00297                 imageGroups=getHDRStacks(*m_pano,m_pano->getActiveImages(), m_pano->getOptions());
00298                 break;
00299             case GROUP_OUTPUTLAYERS:
00300                 imageGroups=getExposureLayers(*m_pano,m_pano->getActiveImages(), m_pano->getOptions());
00301                 break;
00302         };
00303 
00304         size_t nrItems=GetChildrenCount(m_root,false);
00305         if(nrItems!=imageGroups.size())
00306         {
00307             if(nrItems<imageGroups.size())
00308             {
00309                 for(size_t i=nrItems;i<imageGroups.size();i++)
00310                 {
00311                     AppendItem(m_root,wxEmptyString,-1,-1,new ImagesTreeData(-(long)i-1));
00312                 };
00313             }
00314             else
00315             {
00316                 while(GetChildrenCount(m_root,false)>imageGroups.size())
00317                 {
00318                     wxTreeItemIdValue cookie;
00319                     wxTreeItemId item=GetLastChild(m_root,cookie);
00320                     Delete(item);
00321                 };
00322             };
00323         };
00324 
00325         wxTreeItemIdValue cookie;
00326         wxTreeItemId item=GetFirstChild(m_root, cookie);
00327         size_t i=0;
00328         while(item.IsOk())
00329         {
00330             UpdateGroup(item,imageGroups[i++],changedImgs);
00331             UpdateGroupText(item);
00332             item=GetNextChild(m_root, cookie);
00333         };
00334     };
00335 
00336     Thaw();
00337     m_needsUpdate = false;
00338 
00339     // HACK! need to notify clients anyway... send dummy event..
00340     // lets hope our clients query for the selected images with GetSelected()
00341     // and do not try to interpret the event.
00342     wxListEvent e;
00343     e.SetEventType(wxEVT_COMMAND_LIST_ITEM_SELECTED);
00344     e.m_itemIndex = -1;
00345     GetEventHandler()->ProcessEvent(e);
00346 }
00347 
00348 void ImagesTreeCtrl::UpdateImageText(wxTreeItemId item)
00349 {
00350     ImagesTreeData* itemData=static_cast<ImagesTreeData*>(GetItemData(item));
00351     // NAMEisLinked returns always false, if the lens or stacks contains only a single image
00352     // so add a special handling for this case
00353     bool isSingleImage = false;
00354     if (m_groupMode != GROUP_NONE)
00355     {
00356         isSingleImage = (GetChildrenCount(GetItemParent(item)) == 1);
00357     };
00358     wxString s;
00359     const size_t imgNr=itemData->GetImgNr();
00360     const HuginBase::SrcPanoImage & img = m_pano->getImage(imgNr);
00361     wxFileName fn(wxString (img.getFilename().c_str(), HUGIN_CONV_FILENAME));
00362 
00363     s << imgNr;
00364     SetItemText(item, m_columnMap["imgNr"], s);
00365     s.Clear();
00366     SetItemText(item, m_columnMap["filename"], fn.GetFullName() );
00367     SetItemText(item, m_columnMap["width"], wxString::Format(wxT("%d"), img.getSize().width()));
00368     SetItemText(item, m_columnMap["height"], wxString::Format(wxT("%d"), img.getSize().height()));
00369 
00370     wxChar flags[] = wxT("--");
00371     if (m_pano->getOptions().optimizeReferenceImage == imgNr)
00372     {
00373         flags[0]='A';
00374     }
00375     if (m_pano->getOptions().colorReferenceImage == imgNr)
00376     {
00377         flags[1]='C';
00378     }
00379     SetItemText(item, m_columnMap["anchor"], wxString(flags, wxConvLocal));
00380     std::vector<unsigned int> cps = m_pano->getCtrlPointsForImage(imgNr);
00381     s << cps.size();
00382     SetItemText(item, m_columnMap["cps"], s);
00383     s.Clear();
00384     const unsigned int stackNumber = m_variable_groups->getStacks().getPartNumber(imgNr);
00385     SetItemText(item, m_columnMap["stackNr"], wxString::Format(wxT("%u"), stackNumber));
00386     const unsigned int lensNr=m_variable_groups->getLenses().getPartNumber(imgNr);
00387     SetItemText(item, m_columnMap["lensNr"], wxString::Format(wxT("%u"), lensNr));
00388 
00389     SetItemText(item, m_columnMap["maker"], wxString(img.getExifMake().c_str(), wxConvLocal));
00390     SetItemText(item, m_columnMap["model"], wxString(img.getExifModel().c_str(), wxConvLocal));
00391     SetItemText(item, m_columnMap["lens"], wxString(img.getExifLens().c_str(), wxConvLocal));
00392     struct tm exifdatetime;
00393     if(img.getExifDateTime(&exifdatetime)==0)
00394     {
00395         wxDateTime s_datetime=wxDateTime(exifdatetime);
00396         s=s_datetime.Format();
00397     }
00398     else
00399     {
00400         s = wxString(img.getExifDate().c_str(),wxConvLocal);
00401     }
00402     SetItemText(item, m_columnMap["date"], s);
00403 
00404     if(img.getExifFocalLength()>0.0)
00405     {
00406         if(img.getExifFocalLength35()>0.0)
00407         {
00408             s = wxString::Format(wxT("%0.1f mm (%0.0f mm)"),img.getExifFocalLength(),img.getExifFocalLength35());
00409         }
00410         else
00411         {
00412             s = wxString::Format(wxT("%0.1f mm"),img.getExifFocalLength());
00413         };
00414     }
00415     else
00416     {
00417         s = wxEmptyString;
00418     };
00419     SetItemText(item, m_columnMap["focallength"], s);
00420 
00421     if(img.getExifAperture()>0)
00422     {
00423         s=wxString::Format(wxT("F%.1f"),img.getExifAperture());
00424     }
00425     else
00426     {
00427         s=wxEmptyString;
00428     };
00429     SetItemText(item, m_columnMap["aperture"], s);
00430 
00431     if(img.getExifExposureTime()>0.5)
00432     {
00433         if(img.getExifExposureTime()>=1.0) 
00434         {
00435             if(img.getExifExposureTime()>=10.0) 
00436             {
00437                 s=wxString::Format(wxT("%3.0f s"),img.getExifExposureTime());
00438             }
00439             else
00440             {
00441                 s=wxString::Format(wxT("%1.1f s"),img.getExifExposureTime());
00442             }
00443         }
00444         else
00445         {
00446             s=wxString::Format(wxT("%1.2f s"),img.getExifExposureTime());
00447         }
00448     }
00449     else
00450     {
00451         if (img.getExifExposureTime() > 1e-9)
00452         {
00453             s=wxString::Format(wxT("1/%0.0f s"),1.0/img.getExifExposureTime());
00454         } 
00455         else
00456         {
00457             //Sanity
00458             s=wxT("");
00459         }
00460     }
00461     SetItemText(item, m_columnMap["time"], s);
00462 
00463     if(img.getExifISO()>0)
00464     {
00465         s=wxString::Format(wxT("%0.0f"),img.getExifISO());
00466     }
00467     else
00468     {
00469         s=wxEmptyString;
00470     };
00471     SetItemText(item, m_columnMap["iso"], s);
00472 
00473     if (m_groupMode == GROUP_STACK && (img.YawisLinked() || isSingleImage))
00474     {
00475         SetItemText(item, m_columnMap["y"], wxEmptyString);
00476         SetItemText(item, m_columnMap["p"], wxEmptyString);
00477         SetItemText(item, m_columnMap["r"], wxEmptyString);
00478         SetItemText(item, m_columnMap["TrX"], wxEmptyString);
00479         SetItemText(item, m_columnMap["TrY"], wxEmptyString);
00480         SetItemText(item, m_columnMap["TrZ"], wxEmptyString);
00481         SetItemText(item, m_columnMap["Tpy"], wxEmptyString);
00482         SetItemText(item, m_columnMap["Tpp"], wxEmptyString);
00483         SetItemText(item, m_columnMap["cam_trans"], wxEmptyString);
00484     }
00485     else
00486     {
00487         SetItemText(item, m_columnMap["y"], hugin_utils::doubleTowxString(img.getYaw(), m_degDigits));
00488         SetItemText(item, m_columnMap["p"], hugin_utils::doubleTowxString(img.getPitch(), m_degDigits));
00489         SetItemText(item, m_columnMap["r"], hugin_utils::doubleTowxString(img.getRoll(), m_degDigits));
00490         SetItemText(item, m_columnMap["TrX"], hugin_utils::doubleTowxString(img.getX(), m_degDigits));
00491         SetItemText(item, m_columnMap["TrY"], hugin_utils::doubleTowxString(img.getY(), m_degDigits));
00492         SetItemText(item, m_columnMap["TrZ"], hugin_utils::doubleTowxString(img.getZ(), m_degDigits));
00493         SetItemText(item, m_columnMap["Tpy"], hugin_utils::doubleTowxString(img.getTranslationPlaneYaw(), m_degDigits));
00494         SetItemText(item, m_columnMap["Tpp"], hugin_utils::doubleTowxString(img.getTranslationPlanePitch(), m_degDigits));
00495         wxString text=_("not active");
00496         if(img.getX()!=0.0 || img.getY()!=0.0 || img.getZ()!=0.0 || img.getTranslationPlaneYaw()!=0.0 || img.getTranslationPlanePitch()!=0.0)
00497         {
00498             text=_("active");
00499         };
00500         text.Prepend(wxT(" "));
00501         SetItemText(item, m_columnMap["cam_trans"], text);
00502     };
00503 
00504     if(m_groupMode==GROUP_LENS)
00505     {
00506         SetItemText(item, m_columnMap["projection"], wxEmptyString);
00507         SetItemText(item, m_columnMap["response"], wxEmptyString);
00508     }
00509     else
00510     {
00511         SetItemText(item, m_columnMap["projection"], getProjectionString(img));
00512         SetItemText(item, m_columnMap["response"], getResponseString(img));
00513     };
00514 
00515     if (m_groupMode == GROUP_LENS && (img.HFOVisLinked() || isSingleImage))
00516     {
00517         SetItemText(item, m_columnMap["v"], wxEmptyString);
00518     }
00519     else
00520     {
00521         SetItemText(item, m_columnMap["v"], hugin_utils::doubleTowxString(img.getHFOV(), m_degDigits));
00522     };
00523 
00524     if (m_groupMode == GROUP_LENS && (img.RadialDistortionisLinked() || isSingleImage))
00525     {
00526         SetItemText(item, m_columnMap["a"], wxEmptyString);
00527         SetItemText(item, m_columnMap["b"], wxEmptyString);
00528         SetItemText(item, m_columnMap["c"], wxEmptyString);
00529     }
00530     else
00531     {
00532         std::vector<double> dist=img.getRadialDistortion();
00533         SetItemText(item, m_columnMap["a"], hugin_utils::doubleTowxString(dist[0],m_distDigits));
00534         SetItemText(item, m_columnMap["b"], hugin_utils::doubleTowxString(dist[1],m_distDigits));
00535         SetItemText(item, m_columnMap["c"], hugin_utils::doubleTowxString(dist[2],m_distDigits));
00536     };
00537 
00538     if (m_groupMode == GROUP_LENS && (img.RadialDistortionCenterShiftisLinked() || isSingleImage))
00539     {
00540         SetItemText(item, m_columnMap["d"], wxEmptyString);
00541         SetItemText(item, m_columnMap["e"], wxEmptyString);
00542     }
00543     else
00544     {
00545         hugin_utils::FDiff2D p=img.getRadialDistortionCenterShift();
00546         SetItemText(item, m_columnMap["d"], hugin_utils::doubleTowxString(p.x,m_pixelDigits));
00547         SetItemText(item, m_columnMap["e"], hugin_utils::doubleTowxString(p.y,m_pixelDigits));
00548     };
00549 
00550     if (m_groupMode == GROUP_LENS && (img.ShearisLinked() || isSingleImage))
00551     {
00552         SetItemText(item, m_columnMap["g"], wxEmptyString);
00553         SetItemText(item, m_columnMap["t"], wxEmptyString);
00554     }
00555     else
00556     {
00557         hugin_utils::FDiff2D p=img.getShear();
00558         SetItemText(item, m_columnMap["g"], hugin_utils::doubleTowxString(p.x,m_distDigits));
00559         SetItemText(item, m_columnMap["t"], hugin_utils::doubleTowxString(p.y,m_distDigits));
00560     };
00561 
00562     if (m_groupMode == GROUP_LENS && (img.ExposureValueisLinked() || isSingleImage))
00563     {
00564         SetItemText(item, m_columnMap["Eev"], wxEmptyString);
00565     }
00566     else
00567     {
00568         SetItemText(item, m_columnMap["Eev"], hugin_utils::doubleTowxString(img.getExposureValue(), m_pixelDigits));
00569     };
00570 
00571     if (m_groupMode == GROUP_LENS && (img.WhiteBalanceRedisLinked() || isSingleImage))
00572     {
00573         SetItemText(item, m_columnMap["Er"], wxEmptyString);
00574     }
00575     else
00576     {
00577         SetItemText(item, m_columnMap["Er"], hugin_utils::doubleTowxString(img.getWhiteBalanceRed(), m_pixelDigits+1));
00578     };
00579 
00580     if (m_groupMode == GROUP_LENS && (img.WhiteBalanceBlueisLinked() || isSingleImage))
00581     {
00582         SetItemText(item, m_columnMap["Eb"], wxEmptyString);
00583     }
00584     else
00585     {
00586         SetItemText(item, m_columnMap["Eb"], hugin_utils::doubleTowxString(img.getWhiteBalanceBlue(), m_pixelDigits+1));
00587     };
00588 
00589     if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCoeffisLinked() || isSingleImage))
00590     {
00591         SetItemText(item, m_columnMap["Vb"], wxEmptyString);
00592         SetItemText(item, m_columnMap["Vc"], wxEmptyString);
00593         SetItemText(item, m_columnMap["Vd"], wxEmptyString);
00594     }
00595     else
00596     {
00597         std::vector<double> dist=img.getRadialVigCorrCoeff();
00598         SetItemText(item, m_columnMap["Vb"], hugin_utils::doubleTowxString(dist[1],m_distDigits));
00599         SetItemText(item, m_columnMap["Vc"], hugin_utils::doubleTowxString(dist[2],m_distDigits));
00600         SetItemText(item, m_columnMap["Vd"], hugin_utils::doubleTowxString(dist[3],m_distDigits));
00601     };
00602 
00603     if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCenterShiftisLinked() || isSingleImage))
00604     {
00605         SetItemText(item, m_columnMap["Vx"], wxEmptyString);
00606         SetItemText(item, m_columnMap["Vy"], wxEmptyString);
00607     }
00608     else
00609     {
00610         hugin_utils::FDiff2D p=img.getRadialVigCorrCenterShift();
00611         SetItemText(item, m_columnMap["Vx"], hugin_utils::doubleTowxString(p.x,m_distDigits));
00612         SetItemText(item, m_columnMap["Vy"], hugin_utils::doubleTowxString(p.y,m_distDigits));
00613     };
00614 
00615     if (m_groupMode == GROUP_LENS && (img.EMoRParamsisLinked() || isSingleImage))
00616     {
00617         SetItemText(item, m_columnMap["Ra"], wxEmptyString);
00618         SetItemText(item, m_columnMap["Rb"], wxEmptyString);
00619         SetItemText(item, m_columnMap["Rc"], wxEmptyString);
00620         SetItemText(item, m_columnMap["Rd"], wxEmptyString);
00621         SetItemText(item, m_columnMap["Re"], wxEmptyString);
00622     }
00623     else
00624     {
00625         std::vector<float> vec=img.getEMoRParams();
00626         SetItemText(item, m_columnMap["Ra"], hugin_utils::doubleTowxString(vec[0],m_distDigits));
00627         SetItemText(item, m_columnMap["Rb"], hugin_utils::doubleTowxString(vec[1],m_distDigits));
00628         SetItemText(item, m_columnMap["Rc"], hugin_utils::doubleTowxString(vec[2],m_distDigits));
00629         SetItemText(item, m_columnMap["Rd"], hugin_utils::doubleTowxString(vec[3],m_distDigits));
00630         SetItemText(item, m_columnMap["Re"], hugin_utils::doubleTowxString(vec[4],m_distDigits));
00631     };
00632 };
00633 
00634 void ImagesTreeCtrl::UpdateGroupText(wxTreeItemId item)
00635 {
00636     ImagesTreeData* itemData=static_cast<ImagesTreeData*>(GetItemData(item));
00637     switch(m_groupMode)
00638     {
00639         case GROUP_LENS:
00640             SetItemText(item, 1, wxString::Format(_("Lens %ld"),itemData->GetGroupNr()));
00641             break;
00642         case GROUP_STACK:
00643             SetItemText(item, 1, wxString::Format(_("Stack %ld"),itemData->GetGroupNr()));
00644             break;
00645         case GROUP_OUTPUTSTACK:
00646             SetItemText(item, 1, wxString::Format(_("Output stack %ld"),itemData->GetGroupNr()));
00647             break;
00648         case GROUP_OUTPUTLAYERS:
00649             SetItemText(item, 1, wxString::Format(_("Output exposure layer %ld"),itemData->GetGroupNr()));
00650             break;
00651     };
00652     SetItemBold(item,1,true);
00653     wxTreeItemIdValue cookie;
00654     wxTreeItemId childItem=GetFirstChild(item,cookie);
00655     // NAMEisLinked returns always false, if the lens or stacks contains only a single image
00656     // so add a special handling for this case
00657     bool haveSingleChild = false;
00658     if (m_groupMode != GROUP_NONE)
00659     {
00660         haveSingleChild = (GetChildrenCount(item, false) == 1);
00661     };
00662     if(childItem.IsOk())
00663     {
00664         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(childItem));
00665         const HuginBase::SrcPanoImage& img=m_pano->getImage(data->GetImgNr());
00666 
00667         if (m_groupMode == GROUP_STACK && (img.YawisLinked() || haveSingleChild))
00668         {
00669             SetItemText(item, m_columnMap["y"], hugin_utils::doubleTowxString(img.getYaw(), m_degDigits));
00670             SetItemText(item, m_columnMap["p"], hugin_utils::doubleTowxString(img.getPitch(), m_degDigits));
00671             SetItemText(item, m_columnMap["r"], hugin_utils::doubleTowxString(img.getRoll(), m_degDigits));
00672             SetItemText(item, m_columnMap["TrX"], hugin_utils::doubleTowxString(img.getX(), m_degDigits));
00673             SetItemText(item, m_columnMap["TrY"], hugin_utils::doubleTowxString(img.getY(), m_degDigits));
00674             SetItemText(item, m_columnMap["TrZ"], hugin_utils::doubleTowxString(img.getZ(), m_degDigits));
00675             SetItemText(item, m_columnMap["Tpy"], hugin_utils::doubleTowxString(img.getTranslationPlaneYaw(), m_degDigits));
00676             SetItemText(item, m_columnMap["Tpp"], hugin_utils::doubleTowxString(img.getTranslationPlanePitch(), m_degDigits));
00677             wxString text=_("not active");
00678             if(img.getX()!=0.0 || img.getY()!=0.0 || img.getZ()!=0.0 || img.getTranslationPlaneYaw()!=0.0 || img.getTranslationPlanePitch()!=0.0)
00679             {
00680                 text=_("active");
00681             };
00682             text.Prepend(wxT(" "));
00683             SetItemText(item, m_columnMap["cam_trans"], text);
00684         }
00685         else
00686         {
00687             SetItemText(item, m_columnMap["y"], wxEmptyString);
00688             SetItemText(item, m_columnMap["p"], wxEmptyString);
00689             SetItemText(item, m_columnMap["r"], wxEmptyString);
00690             SetItemText(item, m_columnMap["TrX"], wxEmptyString);
00691             SetItemText(item, m_columnMap["TrY"], wxEmptyString);
00692             SetItemText(item, m_columnMap["TrZ"], wxEmptyString);
00693             SetItemText(item, m_columnMap["Tpy"], wxEmptyString);
00694             SetItemText(item, m_columnMap["Tpp"], wxEmptyString);
00695             SetItemText(item, m_columnMap["cam_trans"], wxEmptyString);
00696         };
00697 
00698         if(m_groupMode==GROUP_LENS)
00699         {
00700             SetItemText(item, m_columnMap["projection"], getProjectionString(img));
00701             SetItemText(item, m_columnMap["response"], getResponseString(img));
00702         }
00703         else
00704         {
00705             SetItemText(item, m_columnMap["projection"], wxEmptyString);
00706             SetItemText(item, m_columnMap["response"], wxEmptyString);
00707         };
00708 
00709         if (m_groupMode == GROUP_LENS && (img.HFOVisLinked() || haveSingleChild))
00710         {
00711             SetItemText(item, m_columnMap["v"], hugin_utils::doubleTowxString(img.getHFOV(), m_degDigits));
00712         }
00713         else
00714         {
00715             SetItemText(item, m_columnMap["v"], wxEmptyString);
00716         };
00717 
00718         if (m_groupMode == GROUP_LENS && (img.RadialDistortionisLinked() || haveSingleChild))
00719         {
00720             std::vector<double> dist=img.getRadialDistortion();
00721             SetItemText(item, m_columnMap["a"], hugin_utils::doubleTowxString(dist[0],m_distDigits));
00722             SetItemText(item, m_columnMap["b"], hugin_utils::doubleTowxString(dist[1],m_distDigits));
00723             SetItemText(item, m_columnMap["c"], hugin_utils::doubleTowxString(dist[2],m_distDigits));
00724         }
00725         else
00726         {
00727             SetItemText(item, m_columnMap["a"], wxEmptyString);
00728             SetItemText(item, m_columnMap["b"], wxEmptyString);
00729             SetItemText(item, m_columnMap["c"], wxEmptyString);
00730         };
00731 
00732         if (m_groupMode == GROUP_LENS && (img.RadialDistortionCenterShiftisLinked() || haveSingleChild))
00733         {
00734             hugin_utils::FDiff2D p=img.getRadialDistortionCenterShift();
00735             SetItemText(item, m_columnMap["d"], hugin_utils::doubleTowxString(p.x,m_pixelDigits));
00736             SetItemText(item, m_columnMap["e"], hugin_utils::doubleTowxString(p.y,m_pixelDigits));
00737         }
00738         else
00739         {
00740             SetItemText(item, m_columnMap["d"], wxEmptyString);
00741             SetItemText(item, m_columnMap["e"], wxEmptyString);
00742         };
00743 
00744         if (m_groupMode == GROUP_LENS && (img.ShearisLinked() || haveSingleChild))
00745         {
00746             hugin_utils::FDiff2D p=img.getShear();
00747             SetItemText(item, m_columnMap["g"], hugin_utils::doubleTowxString(p.x,m_distDigits));
00748             SetItemText(item, m_columnMap["t"], hugin_utils::doubleTowxString(p.y,m_distDigits));
00749         }
00750         else
00751         {
00752             SetItemText(item, m_columnMap["g"], wxEmptyString);
00753             SetItemText(item, m_columnMap["t"], wxEmptyString);
00754         };
00755 
00756         if (m_groupMode == GROUP_LENS && (img.ExposureValueisLinked() || haveSingleChild))
00757         {
00758             SetItemText(item, m_columnMap["Eev"], hugin_utils::doubleTowxString(img.getExposureValue(), m_pixelDigits));
00759         }
00760         else
00761         {
00762             SetItemText(item, m_columnMap["Eev"], wxEmptyString);
00763         };
00764 
00765         if (m_groupMode == GROUP_LENS && (img.WhiteBalanceRedisLinked() || haveSingleChild))
00766         {
00767             SetItemText(item, m_columnMap["Er"], hugin_utils::doubleTowxString(img.getWhiteBalanceRed(), m_pixelDigits+1));
00768         }
00769         else
00770         {
00771             SetItemText(item, m_columnMap["Er"], wxEmptyString);
00772         };
00773 
00774         if (m_groupMode == GROUP_LENS && (img.WhiteBalanceBlueisLinked() || haveSingleChild))
00775         {
00776             SetItemText(item, m_columnMap["Eb"], hugin_utils::doubleTowxString(img.getWhiteBalanceBlue(), m_pixelDigits+1));
00777         }
00778         else
00779         {
00780             SetItemText(item, m_columnMap["Eb"], wxEmptyString);
00781         };
00782 
00783         if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCoeffisLinked() || haveSingleChild))
00784         {
00785             std::vector<double> dist=img.getRadialVigCorrCoeff();
00786             SetItemText(item, m_columnMap["Vb"], hugin_utils::doubleTowxString(dist[1],m_distDigits));
00787             SetItemText(item, m_columnMap["Vc"], hugin_utils::doubleTowxString(dist[2],m_distDigits));
00788             SetItemText(item, m_columnMap["Vd"], hugin_utils::doubleTowxString(dist[3],m_distDigits));
00789         }
00790         else
00791         {
00792             SetItemText(item, m_columnMap["Vb"], wxEmptyString);
00793             SetItemText(item, m_columnMap["Vc"], wxEmptyString);
00794             SetItemText(item, m_columnMap["Vd"], wxEmptyString);
00795         };
00796 
00797         if (m_groupMode == GROUP_LENS && (img.RadialVigCorrCenterShiftisLinked() || haveSingleChild))
00798         {
00799             hugin_utils::FDiff2D p=img.getRadialVigCorrCenterShift();
00800             SetItemText(item, m_columnMap["Vx"], hugin_utils::doubleTowxString(p.x,m_distDigits));
00801             SetItemText(item, m_columnMap["Vy"], hugin_utils::doubleTowxString(p.y,m_distDigits));
00802         }
00803         else
00804         {
00805             SetItemText(item, m_columnMap["Vx"], wxEmptyString);
00806             SetItemText(item, m_columnMap["Vy"], wxEmptyString);
00807         };
00808 
00809         if (m_groupMode == GROUP_LENS && (img.EMoRParamsisLinked() || haveSingleChild))
00810         {
00811             std::vector<float> vec=img.getEMoRParams();
00812             SetItemText(item, m_columnMap["Ra"], hugin_utils::doubleTowxString(vec[0],m_distDigits));
00813             SetItemText(item, m_columnMap["Rb"], hugin_utils::doubleTowxString(vec[1],m_distDigits));
00814             SetItemText(item, m_columnMap["Rc"], hugin_utils::doubleTowxString(vec[2],m_distDigits));
00815             SetItemText(item, m_columnMap["Rd"], hugin_utils::doubleTowxString(vec[3],m_distDigits));
00816             SetItemText(item, m_columnMap["Re"], hugin_utils::doubleTowxString(vec[4],m_distDigits));
00817         }
00818         else
00819         {
00820             SetItemText(item, m_columnMap["Ra"], wxEmptyString);
00821             SetItemText(item, m_columnMap["Rb"], wxEmptyString);
00822             SetItemText(item, m_columnMap["Rc"], wxEmptyString);
00823             SetItemText(item, m_columnMap["Rd"], wxEmptyString);
00824             SetItemText(item, m_columnMap["Re"], wxEmptyString);
00825         };
00826     };
00827 };
00828 
00829 void ImagesTreeCtrl::UpdateGroup(wxTreeItemId parent, const HuginBase::UIntSet imgs, HuginBase::UIntSet& changed)
00830 {
00831     size_t nrItems=GetChildrenCount(parent,false);
00832     bool forceUpdate=false;
00833     if(nrItems!=imgs.size())
00834     {
00835         forceUpdate=true;
00836         if(nrItems<imgs.size())
00837         {
00838             for(size_t i=nrItems;i<imgs.size();i++)
00839             {
00840                 AppendItem(parent,wxEmptyString,-1,-1,new ImagesTreeData(-1));
00841             };
00842         }
00843         else
00844         {
00845             while(GetChildrenCount(parent,false)>imgs.size())
00846             {
00847                 wxTreeItemIdValue cookie;
00848                 wxTreeItemId item=GetLastChild(parent,cookie);
00849                 Delete(item);
00850             };
00851         };
00852     };
00853     //now update values
00854     wxTreeItemIdValue cookie;
00855     wxTreeItemId item=GetFirstChild(parent,cookie);
00856     HuginBase::UIntSet::const_iterator it=imgs.begin();
00857     while(item.IsOk())
00858     {
00859         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
00860         if(it==imgs.end())
00861         {
00862             break;
00863         };
00864         bool needsUpdate=false;
00865         if(data->GetImgNr()!=*it)
00866         {
00867             data->SetImgNr(*it);
00868             needsUpdate=true;
00869         }
00870         else
00871         {
00872             if(set_contains(changed,*it))
00873             {
00874                 needsUpdate=true;
00875             };
00876         };
00877         if(needsUpdate || forceUpdate)
00878         {
00879             UpdateImageText(item);
00880             changed.erase(*it);
00881         };
00882         item=GetNextChild(parent, cookie);
00883         ++it;
00884     };
00885 };
00886 
00887 void ImagesTreeCtrl::UpdateOptimizerVariables()
00888 {
00889     HuginBase::OptimizeVector optVec=m_pano->getOptimizeVector();
00890     wxFont font1=GetItemFont(m_root);
00891     wxFont font2(font1);
00892     font2.SetUnderlined(true);
00893     font2.SetWeight(wxFONTWEIGHT_BOLD);
00894     wxTreeItemIdValue cookie;
00895     wxTreeItemId item=GetFirstChild(m_root, cookie);
00896     while(item.IsOk())
00897     {
00898         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
00899         HuginBase::UIntSet imgNrs;
00900         if(data->IsGroup())
00901         {
00902             wxTreeItemIdValue childCookie;
00903             wxTreeItemId child=GetFirstChild(item, childCookie);
00904             while(child.IsOk())
00905             {
00906                 data=static_cast<ImagesTreeData*>(GetItemData(child));
00907                 imgNrs.insert(data->GetImgNr());
00908                 child=GetNextChild(item, childCookie);
00909             };
00910         }
00911         else
00912         {
00913             imgNrs.insert(data->GetImgNr());
00914         };
00915         if(imgNrs.size()>0)
00916         {
00917             for(size_t i=0;i<GetColumnCount();i++)
00918             {
00919                 if(set_contains(m_editableColumns,i))
00920                 {
00921                     bool opt=false;
00922                     for(HuginBase::UIntSet::const_iterator it=imgNrs.begin(); it!=imgNrs.end() && !opt;++it)
00923                     {
00924                         if(m_columnVector[i]=="cam_trans")
00925                         {
00926                             opt=set_contains(optVec[*it], "TrX") &&
00927                                 set_contains(optVec[*it], "TrY") &&
00928                                 set_contains(optVec[*it], "TrZ") &&
00929                                 set_contains(optVec[*it], "Tpy") &&
00930                                 set_contains(optVec[*it], "Tpp");
00931                         }
00932                         else
00933                         {
00934                             opt=set_contains(optVec[*it], m_columnVector[i]);
00935                         };
00936                     };
00937                     if(opt)
00938                     {
00939                         SetItemFont(item,i,font2);
00940                     }
00941                     else
00942                     {
00943                         SetItemFont(item,i,font1);
00944                     };
00945                 };
00946             };
00947         };
00948         item=GetNext(item);
00949     };
00950 };
00951 
00952 HuginBase::UIntSet ImagesTreeCtrl::GetSelectedImages()
00953 {
00954     wxArrayTreeItemIds selected;
00955     HuginBase::UIntSet imgs;
00956     if(GetSelections (selected)>0)
00957     {
00958         for(size_t i=0;i<selected.size();i++)
00959         {
00960             ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(selected[i]));
00961             if(data->IsGroup())
00962             {
00963                 wxTreeItemIdValue cookie;
00964                 wxTreeItemId item=GetFirstChild(selected[i],cookie);
00965                 while(item.IsOk())
00966                 {
00967                     data=static_cast<ImagesTreeData*>(GetItemData(item));
00968                     imgs.insert(data->GetImgNr());
00969                     item=GetNextChild(selected[i], cookie);
00970                 };
00971             }
00972             else
00973             {
00974                 imgs.insert(data->GetImgNr());
00975             };
00976         };
00977     }
00978     return imgs;
00979 };
00980 
00981 void ImagesTreeCtrl::OnColumnWidthChange( wxListEvent & e )
00982 {
00983     if(m_configClassName != wxT(""))
00984     {
00985         int colNum = e.GetColumn();
00986         wxConfigBase::Get()->Write( m_configClassName+wxString::Format(wxT("/ColumnWidth%d"),colNum), GetColumnWidth(colNum) );
00987     }
00988 }
00989 
00990 void ImagesTreeCtrl::SetGuiLevel(GuiLevel newSetting)
00991 {
00992     m_guiLevel=newSetting;
00993     //update visible column
00994     SetDisplayMode(m_displayMode);
00995 };
00996 
00997 void ImagesTreeCtrl::SetOptimizerMode()
00998 {
00999     m_optimizerMode=true;
01000     for(HuginBase::UIntSet::const_iterator it=m_editableColumns.begin(); it!=m_editableColumns.end(); ++it)
01001     {
01002         if(m_columnVector[*it]!="cam_trans")
01003         {
01004             SetColumnEditable(*it,true);
01005         };
01006     };
01007 };
01008 
01009 void ImagesTreeCtrl::SetGroupMode(GroupMode newGroup)
01010 {
01011     if(newGroup!=m_groupMode)
01012     {
01013         m_groupMode=newGroup;
01014         if(m_groupMode==GROUP_NONE)
01015         {
01016             SetWindowStyle(GetWindowStyle() | wxTR_NO_LINES);
01017         }
01018         else
01019         {
01020             SetWindowStyle(GetWindowStyle() & ~wxTR_NO_LINES);
01021         };
01022         DeleteChildren(m_root);
01023         HuginBase::UIntSet imgs;
01024         if(m_pano->getNrOfImages()>0)
01025         {
01026             fill_set(imgs,0,m_pano->getNrOfImages()-1);
01027         };
01028         panoramaImagesChanged(*m_pano,imgs);
01029         ExpandAll(m_root);
01030     };
01031 };
01032 
01033 void ImagesTreeCtrl::SetDisplayMode(DisplayMode newMode)
01034 {
01035     m_displayMode=newMode;
01036 
01037     SetColumnShown(m_columnMap["width"], m_displayMode==DISPLAY_GENERAL);
01038     SetColumnShown(m_columnMap["height"], m_displayMode==DISPLAY_GENERAL);
01039     SetColumnShown(m_columnMap["anchor"], m_displayMode==DISPLAY_GENERAL);
01040     SetColumnShown(m_columnMap["cps"], m_displayMode==DISPLAY_GENERAL);
01041     SetColumnShown(m_columnMap["lensNr"], m_displayMode==DISPLAY_GENERAL);
01042     SetColumnShown(m_columnMap["stackNr"], m_displayMode==DISPLAY_GENERAL && m_guiLevel>=GUI_ADVANCED);
01043 
01044     SetColumnShown(m_columnMap["maker"], m_displayMode==DISPLAY_EXIF);
01045     SetColumnShown(m_columnMap["model"], m_displayMode==DISPLAY_EXIF);
01046     SetColumnShown(m_columnMap["lens"], m_displayMode==DISPLAY_EXIF);
01047     SetColumnShown(m_columnMap["date"], m_displayMode==DISPLAY_EXIF);
01048     SetColumnShown(m_columnMap["focallength"], m_displayMode==DISPLAY_EXIF);
01049     SetColumnShown(m_columnMap["aperture"], m_displayMode==DISPLAY_EXIF);
01050     SetColumnShown(m_columnMap["time"], m_displayMode==DISPLAY_EXIF);
01051     SetColumnShown(m_columnMap["iso"], m_displayMode==DISPLAY_EXIF);
01052 
01053     SetColumnShown(m_columnMap["y"], m_displayMode==DISPLAY_POSITION);
01054     SetColumnShown(m_columnMap["p"], m_displayMode==DISPLAY_POSITION);
01055     SetColumnShown(m_columnMap["r"], m_displayMode==DISPLAY_POSITION);
01056     SetColumnShown(m_columnMap["TrX"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01057     SetColumnShown(m_columnMap["TrY"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01058     SetColumnShown(m_columnMap["TrZ"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01059     SetColumnShown(m_columnMap["Tpy"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01060     SetColumnShown(m_columnMap["Tpp"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01061     SetColumnShown(m_columnMap["cam_trans"], m_displayMode==DISPLAY_POSITION && m_guiLevel==GUI_EXPERT);
01062 
01063     SetColumnShown(m_columnMap["projection"], m_displayMode==DISPLAY_LENS);
01064     SetColumnShown(m_columnMap["v"], m_displayMode==DISPLAY_LENS);
01065     SetColumnShown(m_columnMap["a"], m_displayMode==DISPLAY_LENS);
01066     SetColumnShown(m_columnMap["b"], m_displayMode==DISPLAY_LENS);
01067     SetColumnShown(m_columnMap["c"], m_displayMode==DISPLAY_LENS);
01068     SetColumnShown(m_columnMap["d"], m_displayMode==DISPLAY_LENS);
01069     SetColumnShown(m_columnMap["e"], m_displayMode==DISPLAY_LENS);
01070     SetColumnShown(m_columnMap["g"], m_displayMode==DISPLAY_LENS && m_guiLevel>=GUI_EXPERT);
01071     SetColumnShown(m_columnMap["t"], m_displayMode==DISPLAY_LENS && m_guiLevel>=GUI_EXPERT);
01072 
01073     SetColumnShown(m_columnMap["Eev"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_IMAGES);
01074     SetColumnShown(m_columnMap["Er"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_IMAGES);
01075     SetColumnShown(m_columnMap["Eb"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_IMAGES);
01076     SetColumnShown(m_columnMap["Vb"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01077     SetColumnShown(m_columnMap["Vc"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01078     SetColumnShown(m_columnMap["Vd"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01079     SetColumnShown(m_columnMap["Vx"], (m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES) && m_guiLevel>=GUI_ADVANCED);
01080     SetColumnShown(m_columnMap["Vy"], (m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES) && m_guiLevel>=GUI_ADVANCED);
01081     SetColumnShown(m_columnMap["response"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01082     SetColumnShown(m_columnMap["Ra"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01083     SetColumnShown(m_columnMap["Rb"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01084     SetColumnShown(m_columnMap["Rc"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01085     SetColumnShown(m_columnMap["Rd"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01086     SetColumnShown(m_columnMap["Re"], m_displayMode==DISPLAY_PHOTOMETRICS || m_displayMode==DISPLAY_PHOTOMETRICS_LENSES);
01087 
01088     Refresh();
01089 };
01090 
01091 void ImagesTreeCtrl::OnContextMenu(wxTreeEvent & e)
01092 {
01093     m_selectedColumn=e.GetInt();
01094     wxMenu menu;
01095     bool allowMenuExtension=true;
01096     if(e.GetItem().IsOk())
01097     {
01098         //click on item
01099         if(set_contains(m_editableColumns,m_selectedColumn))
01100         {
01101             bool emptyText=GetItemText(e.GetItem(),m_selectedColumn).IsEmpty();
01102             ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
01103             if((m_groupMode==GROUP_LENS && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Yaw) ||
01104                (m_groupMode==GROUP_STACK && m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw) )
01105             {
01106                 if(data->IsGroup())
01107                 {
01108                     if(emptyText)
01109                     {
01110                         menu.Append(ID_LINK,_("Link"));
01111                     }
01112                     else
01113                     {
01114                         menu.Append(ID_UNLINK, _("Unlink"));
01115                     };
01116                 }
01117                 else
01118                 {
01119                     if(emptyText)
01120                     {
01121                         menu.Append(ID_UNLINK,_("Unlink"));
01122                     }
01123                     else
01124                     {
01125                         menu.Append(ID_LINK, _("Link"));
01126                     };
01127                 };
01128                 menu.AppendSeparator();
01129             };
01130             if(m_optimizerMode)
01131             {
01132                 if(data->IsGroup() == emptyText)
01133                 {
01134                     if(m_groupMode==GROUP_LENS && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Yaw)
01135                     {
01136                         menu.Append(ID_SELECT_LENS_STACK, _("Select all for current lens"));
01137                         menu.Append(ID_UNSELECT_LENS_STACK, _("Unselect all for current lens"));
01138                     };
01139                     if(m_groupMode==GROUP_STACK && m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw)
01140                     {
01141                         menu.Append(ID_SELECT_LENS_STACK, _("Select all for current stack"));
01142                         menu.Append(ID_UNSELECT_LENS_STACK, _("Unselect all for current stack"));
01143                     };
01144                 };
01145                 if(m_columnVector[m_selectedColumn]!="cam_trans")
01146                 {
01147                     menu.Append(ID_SELECT_ALL, _("Select all"));
01148                 };
01149                 menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
01150                 menu.AppendSeparator();
01151             }
01152         };
01153         menu.Append(ID_EDIT, _("Edit image variables..."));
01154     }
01155     else
01156     {
01157         if(m_optimizerMode && set_contains(m_editableColumns, e.GetInt()))
01158         {
01159             if(m_columnVector[m_selectedColumn]!="cam_trans")
01160             {
01161                 menu.Append(ID_SELECT_ALL, _("Select all"));
01162             };
01163             menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
01164             allowMenuExtension=false;
01165         }
01166     };
01167     if(allowMenuExtension)
01168     {
01169         if(menu.GetMenuItemCount()>0)
01170         {
01171             menu.AppendSeparator();
01172         };
01173         int id=ID_OPERATION_START;
01174         m_menuOperation.clear();
01175         GenerateSubMenu(&menu, PanoOperation::GetImagesOperationVector(), id);
01176         wxMenu* subMenu=new wxMenu();
01177         GenerateSubMenu(subMenu, PanoOperation::GetLensesOperationVector(), id);
01178         if(subMenu->GetMenuItemCount()>0)
01179         {
01180             menu.Append(-1,_("Lens"), subMenu);
01181         }
01182         else
01183         {
01184             delete subMenu;
01185         };
01186         if(m_guiLevel>GUI_SIMPLE)
01187         {
01188             subMenu=new wxMenu();
01189             GenerateSubMenu(subMenu, PanoOperation::GetStacksOperationVector(), id);
01190             if(subMenu->GetMenuItemCount()>0)
01191             {
01192                 menu.Append(-1,_("Stacks"), subMenu);
01193             }
01194             else
01195             {
01196                 delete subMenu;
01197             };
01198         };
01199         subMenu=new wxMenu();
01200         GenerateSubMenu(subMenu, PanoOperation::GetControlPointsOperationVector(), id);
01201         if(subMenu->GetMenuItemCount()>0)
01202         {
01203             menu.Append(-1, _("Control points"), subMenu);
01204         }
01205         else
01206         {
01207             delete subMenu;
01208         };
01209         subMenu=new wxMenu();
01210         GenerateSubMenu(subMenu, PanoOperation::GetResetOperationVector(), id);
01211         if(subMenu->GetMenuItemCount()>0)
01212         {
01213             menu.Append(-1, _("Reset"), subMenu);
01214         }
01215         else
01216         {
01217             delete subMenu;
01218         };
01219     };
01220     if(menu.GetMenuItemCount()>0)
01221     {
01222         PopupMenu(&menu);
01223     };
01224     e.Skip();
01225 };
01226 
01227 void ImagesTreeCtrl::GenerateSubMenu(wxMenu* menu, PanoOperation::PanoOperationVector* operations, int& id)
01228 {
01229     HuginBase::UIntSet imgs=GetSelectedImages();
01230     for(size_t i=0; i<operations->size(); i++)
01231     {
01232         if((*operations)[i]->IsEnabled(*m_pano, imgs, m_guiLevel))
01233         {
01234             menu->Append(id, (*operations)[i]->GetLabel());
01235             m_menuOperation[id]=(*operations)[i];
01236             id++;
01237         }
01238     };
01239 };
01240 
01241 void ImagesTreeCtrl::OnHeaderContextMenu(wxListEvent & e)
01242 {
01243     m_selectedColumn=e.GetColumn();
01244     wxMenu menu;
01245     if(m_optimizerMode && set_contains(m_editableColumns, m_selectedColumn))
01246     {
01247         menu.Append(ID_SELECT_ALL, _("Select all"));
01248         menu.Append(ID_UNSELECT_ALL, _("Unselect all"));
01249         PopupMenu(&menu);
01250     };
01251     e.Skip();
01252 };
01253 
01254 void ImagesTreeCtrl::UnLinkImageVariables(bool linked)
01255 {
01256     HuginBase::UIntSet images=GetSelectedImages();
01257     if(images.size()>0 && m_variableVector[m_selectedColumn]!=HuginBase::ImageVariableGroup::IVE_Filename)
01258     {
01259         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
01260         variables.insert(m_variableVector[m_selectedColumn]);
01261         if(m_variableVector[m_selectedColumn]==HuginBase::ImageVariableGroup::IVE_Yaw)
01262         {
01263             variables.insert(HuginBase::ImageVariableGroup::IVE_Pitch);
01264             variables.insert(HuginBase::ImageVariableGroup::IVE_Roll);
01265             variables.insert(HuginBase::ImageVariableGroup::IVE_X);
01266             variables.insert(HuginBase::ImageVariableGroup::IVE_Y);
01267             variables.insert(HuginBase::ImageVariableGroup::IVE_Z);
01268             variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw);
01269             variables.insert(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch);
01270         };
01271         if(m_groupMode==GROUP_LENS)
01272         {
01273             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01274                 new PanoCommand::ChangePartImagesLinkingCmd(*m_pano, images, variables, linked, HuginBase::StandardImageVariableGroups::getLensVariables())
01275             );
01276         }
01277         else
01278         {
01279             PanoCommand::GlobalCmdHist::getInstance().addCommand(
01280                 new PanoCommand::ChangePartImagesLinkingCmd(*m_pano, images, variables, linked, HuginBase::StandardImageVariableGroups::getStackVariables())
01281             );
01282         };
01283     };
01284 };
01285 
01286 void ImagesTreeCtrl::OnLinkImageVariables(wxCommandEvent &e)
01287 {
01288     UnLinkImageVariables(true);
01289 };
01290 
01291 void ImagesTreeCtrl::OnUnlinkImageVariables(wxCommandEvent &e)
01292 {
01293     UnLinkImageVariables(false);
01294 };
01295 
01296 void ImagesTreeCtrl::OnEditImageVariables(wxCommandEvent &e)
01297 {
01298     HuginBase::UIntSet imgs=GetSelectedImages();
01299     if(imgs.size()>0)
01300     {
01301         ImageVariableDialog dlg(this, m_pano, imgs);
01302         dlg.SetGuiLevel(m_guiLevel);
01303         switch(m_displayMode)
01304         {
01305             case DISPLAY_LENS:
01306                 dlg.SelectTab(1);
01307                 break;
01308             case DISPLAY_PHOTOMETRICS:
01309             case DISPLAY_PHOTOMETRICS_IMAGES:
01310             case DISPLAY_PHOTOMETRICS_LENSES:
01311                 if(m_selectedColumn==m_columnMap["response"] ||
01312                     m_selectedColumn==m_columnMap["Ra"] ||
01313                     m_selectedColumn==m_columnMap["Rb"] ||
01314                     m_selectedColumn==m_columnMap["Rc"] ||
01315                     m_selectedColumn==m_columnMap["Rd"] ||
01316                     m_selectedColumn==m_columnMap["Re"] )
01317                 {
01318                     dlg.SelectTab(3);
01319                 }
01320                 else
01321                 {
01322                     dlg.SelectTab(2);
01323                 };
01324                 break;
01325             default:
01326                 break;
01327         };
01328         dlg.ShowModal();
01329     };
01330 };
01331 
01332 void ImagesTreeCtrl::OnBeginDrag(wxTreeEvent &e)
01333 {
01334 #if wxCHECK_VERSION(2,9,4)
01335     bool ctrlPressed=wxGetKeyState(WXK_COMMAND);
01336 #else
01337     bool ctrlPressed=wxGetKeyState(WXK_CONTROL);
01338 #endif
01339     if(m_pano->getNrOfImages()>0 && !m_dragging)
01340     {
01341         m_draggingImages=GetSelectedImages();
01342         if(m_draggingImages.size()>0)
01343         {
01344             if((m_groupMode==GROUP_NONE && m_draggingImages.size()==1 && !ctrlPressed) ||
01345                 m_groupMode==GROUP_LENS || m_groupMode==GROUP_STACK)
01346             {
01347                 e.Allow();
01348                 SetCursor(wxCURSOR_HAND);
01349                 m_dragging=true;
01350             };
01351         };
01352     };
01353 };
01354 
01355 void ImagesTreeCtrl::OnEndDrag(wxMouseEvent &e)
01356 {
01357     //we can't use wxEVT_TREE_END_DRAG because this event is fire several times, e.g. when
01358     // the mouse leaves the area of the tree
01359     // so we are listing to left mouse up, as described in documentation
01360     if(m_dragging)
01361     {
01362         SetCursor(wxCURSOR_ARROW);
01363         m_dragging=false;
01364         wxTreeItemId item=HitTest(e.GetPosition());
01365         if(m_groupMode==GROUP_NONE)
01366         {
01367             size_t img1=*m_draggingImages.begin();
01368             size_t img2=-1;
01369             if(item.IsOk())
01370             {
01371                 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
01372                 img2=data->GetImgNr();
01373             }
01374             else
01375             {
01376                 //we are checking the points above, if we find then
01377                 // an item, the user drop it below the last item, if not
01378                 // the drop happened right beside the item
01379                 wxPoint pos(e.GetPosition());
01380                 pos.y-=10;
01381                 while(pos.y>0)
01382                 {
01383                     item=HitTest(pos);
01384                     if(item.IsOk())
01385                     {
01386                         img2=m_pano->getNrOfImages()-1;
01387                         break;
01388                     };
01389                     pos.y-=10;
01390                 };
01391             };
01392             if(img2!=-1)
01393             {
01394                 if(img1!=img2)
01395                 {
01396                     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01397                         new PanoCommand::MoveImageCmd(*m_pano, img1, img2)
01398                     );
01399                 };
01400             };
01401         }
01402         else
01403         {
01404             //dragging to stack/lenses
01405             if(item.IsOk())
01406             {
01407                 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
01408                 long groupNr=-1;
01409                 if(data->IsGroup())
01410                 {
01411                     groupNr=data->GetGroupNr();
01412                 }
01413                 else
01414                 {
01415                     item=GetItemParent(item);
01416                     if(item.IsOk())
01417                     {
01418                         data=static_cast<ImagesTreeData*>(GetItemData(item));
01419                         groupNr=data->GetGroupNr();
01420                     };
01421                 };
01422                 if(groupNr>=0)
01423                 {
01424                     if(m_groupMode==GROUP_LENS)
01425                     {
01426                         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01427                             new PanoCommand::ChangePartNumberCmd(*m_pano, m_draggingImages, groupNr, HuginBase::StandardImageVariableGroups::getLensVariables())
01428                         );
01429                     }
01430                     else
01431                     {
01432                         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01433                             new PanoCommand::ChangePartNumberCmd(*m_pano, m_draggingImages, groupNr, HuginBase::StandardImageVariableGroups::getStackVariables())
01434                         );
01435                     };
01436                 };
01437             }
01438             else // item not ok, drop not on existing item, create new lens/stack
01439             {
01440                 if(m_groupMode==GROUP_LENS)
01441                 {
01442                     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01443                         new PanoCommand::NewPartCmd(*m_pano, m_draggingImages, HuginBase::StandardImageVariableGroups::getLensVariables())
01444                     );
01445                 }
01446                 else
01447                 {
01448                     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01449                         new PanoCommand::NewPartCmd(*m_pano, m_draggingImages, HuginBase::StandardImageVariableGroups::getStackVariables())
01450                     );
01451                 }
01452             };
01453         }
01454         m_draggingImages.clear();
01455     }
01456     else
01457     {
01458         e.Skip();
01459     };
01460 };
01461 
01462 void ImagesTreeCtrl::OnLeftDown(wxMouseEvent &e)
01463 {
01464     if(!m_dragging && m_optimizerMode)
01465     {
01466         if(e.LeftDown() && e.CmdDown())
01467         {
01468             int flags;
01469             int col;
01470             wxTreeItemId item=HitTest(e.GetPosition(),flags,col);
01471             if(item.IsOk())
01472             {
01473                 if(set_contains(m_editableColumns, col))
01474                 {
01475                     if(!GetItemText(item, col).IsEmpty())
01476                     {
01477                         HuginBase::UIntSet imgs;
01478                         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(item));
01479                         if(data->IsGroup())
01480                         {
01481                             wxTreeItemIdValue cookie;
01482                             wxTreeItemId childItem=GetFirstChild(item,cookie);
01483                             while(childItem.IsOk())
01484                             {
01485                                 data=static_cast<ImagesTreeData*>(GetItemData(childItem));
01486                                 imgs.insert(data->GetImgNr());
01487                                 childItem=GetNextChild(item, cookie);
01488                             };
01489                         }
01490                         else
01491                         {
01492                             imgs.insert(data->GetImgNr());
01493                         };
01494                         HuginBase::OptimizeVector optVec=m_pano->getOptimizeVector();
01495                         std::set<std::string> var;
01496                         if(m_columnVector[col]=="cam_trans")
01497                         {
01498                             var.insert("TrX");
01499                             var.insert("TrY");
01500                             var.insert("TrZ");
01501                             var.insert("Tpy");
01502                             var.insert("Tpp");
01503                         }
01504                         else
01505                         {
01506                             var.insert(m_columnVector[col]);
01507                             if(m_columnVector[col]=="Tpy" || m_columnVector[col]=="Tpp")
01508                             {
01509                                 var.insert("Tpy");
01510                                 var.insert("Tpp");
01511                             };
01512                             if(m_columnVector[col]=="Vb" || m_columnVector[col]=="Vc" || m_columnVector[col]=="Vd")
01513                             {
01514                                 var.insert("Vb");
01515                                 var.insert("Vc");
01516                                 var.insert("Vd");
01517                             };
01518                             if(m_columnVector[col]=="Vx" || m_columnVector[col]=="Vy")
01519                             {
01520                                 var.insert("Vx");
01521                                 var.insert("Vy");
01522                             };
01523                             if(m_columnVector[col]=="Ra" || m_columnVector[col]=="Rb" || m_columnVector[col]=="Rc" || 
01524                                m_columnVector[col]=="Rd" || m_columnVector[col]=="Re")
01525                             {
01526                                 var.insert("Ra");
01527                                 var.insert("Rb");
01528                                 var.insert("Rc");
01529                                 var.insert("Rd");
01530                                 var.insert("Re");
01531                             };
01532                         };
01533                         bool deactivate=false;
01534                         for(std::set<std::string>::const_iterator varIt=var.begin(); varIt!=var.end(); ++varIt)
01535                         {
01536                             //search, if image variable is marked for optimise for at least one image of group
01537                             for(HuginBase::UIntSet::const_iterator imgIt=imgs.begin(); imgIt!=imgs.end() && !deactivate; ++imgIt)
01538                             {
01539                                 if(set_contains(optVec[*imgIt], *varIt))
01540                                 {
01541                                     deactivate=true;
01542                                 };
01543                             };
01544                         };
01545                         // now deactivate or activate the image variable for optimisation
01546                         if(deactivate)
01547                         {
01548                             for(std::set<std::string>::const_iterator varIt=var.begin(); varIt!=var.end(); ++varIt)
01549                             {
01550                                 for(HuginBase::UIntSet::const_iterator imgIt=imgs.begin(); imgIt!=imgs.end(); ++imgIt)
01551                                 {
01552                                     optVec[*imgIt].erase(*varIt);
01553                                 };
01554                             }
01555                         }
01556                         else
01557                         {
01558                             for(std::set<std::string>::const_iterator varIt=var.begin(); varIt!=var.end(); ++varIt)
01559                             {
01560                                 for(HuginBase::UIntSet::const_iterator imgIt=imgs.begin(); imgIt!=imgs.end(); ++imgIt)
01561                                 {
01562                                     optVec[*imgIt].insert(*varIt);
01563                                 };
01564                             };
01565                         };
01566                         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01567                             new PanoCommand::UpdateOptimizeVectorCmd(*m_pano, optVec)
01568                         );
01569                         return;
01570                     };
01571                 };
01572             };
01573         };
01574     };
01575     e.Skip();
01576 };
01577 
01578 void ImagesTreeCtrl::SelectAllParameters(bool select, bool allImages)
01579 {
01580     std::set<std::string> imgVars;
01581     std::string var=m_columnVector[m_selectedColumn];
01582     if(var=="cam_trans")
01583     {
01584         imgVars.insert("TrX");
01585         imgVars.insert("TrY");
01586         imgVars.insert("TrZ");
01587         imgVars.insert("Tpy");
01588         imgVars.insert("Tpp");
01589     }
01590     else
01591     {
01592         imgVars.insert(var);
01593         if(var=="Vb" || var=="Vc" || var=="Vd")
01594         {
01595             imgVars.insert("Vb");
01596             imgVars.insert("Vc");
01597             imgVars.insert("Vd");
01598         };
01599         if(var=="Vx" || var=="Vy")
01600         {
01601             imgVars.insert("Vx");
01602             imgVars.insert("Vy");
01603         };
01604         if(var=="Ra" || var=="Rb" || var=="Rc" || var=="Rd" || var=="Re")
01605         {
01606             imgVars.insert("Ra");
01607             imgVars.insert("Rb");
01608             imgVars.insert("Rc");
01609             imgVars.insert("Rd");
01610             imgVars.insert("Re");
01611         };
01612 
01613     };
01614 
01615     HuginBase::UIntSet imgs;
01616     if(allImages)
01617     {
01618         fill_set(imgs, 0, m_pano->getNrOfImages()-1);
01619     }
01620     else
01621     {
01622         wxArrayTreeItemIds selectedItem;
01623         if(GetSelections(selectedItem)>0)
01624         {
01625             for(size_t i=0;i<selectedItem.size();i++)
01626             {
01627                 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(selectedItem[i]));
01628                 wxTreeItemId startItem;
01629                 if(data->IsGroup())
01630                 {
01631                     startItem=selectedItem[i];
01632                 }
01633                 else
01634                 {
01635                     startItem=GetItemParent(selectedItem[i]);
01636                 };
01637                 wxTreeItemIdValue cookie;
01638                 wxTreeItemId item=GetFirstChild(startItem,cookie);
01639                 while(item.IsOk())
01640                 {
01641                     data=static_cast<ImagesTreeData*>(GetItemData(item));
01642                     imgs.insert(data->GetImgNr());
01643                     item=GetNextChild(startItem, cookie);
01644                 };
01645             };
01646         };
01647     };
01648 
01649     HuginBase::OptimizeVector optVec = m_pano->getOptimizeVector();
01650     for(HuginBase::UIntSet::iterator img=imgs.begin(); img!=imgs.end(); ++img)
01651     {
01652         for(std::set<std::string>::const_iterator it=imgVars.begin(); it!=imgVars.end(); ++it)
01653         {
01654             if(select)
01655             {
01656                 if((*it=="y" || *it=="p" || *it=="r" || *it=="TrX" || *it=="TrY" || *it=="TrZ" || *it=="Tpy" || *it=="Tpp") && 
01657                     *img==m_pano->getOptions().optimizeReferenceImage)
01658                 {
01659                     optVec[*img].erase(*it);
01660                     continue;
01661                 };
01662                 if((*it=="Eev" || *it=="Er" || *it=="Eb") && *img==m_pano->getOptions().colorReferenceImage)
01663                 {
01664                     optVec[*img].erase(*it);
01665                     continue;
01666                 };
01667                 optVec[*img].insert(*it);
01668             }
01669             else
01670             {
01671                 optVec[*img].erase(*it);
01672             };
01673         };
01674     };
01675     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01676         new PanoCommand::UpdateOptimizeVectorCmd(*m_pano, optVec)
01677     );
01678 };
01679 
01680 void ImagesTreeCtrl::OnSelectAll(wxCommandEvent &e)
01681 {
01682     SelectAllParameters(true, true);
01683 };
01684 
01685 void ImagesTreeCtrl::OnUnselectAll(wxCommandEvent &e)
01686 {
01687     SelectAllParameters(false, true);
01688 };
01689 
01690 void ImagesTreeCtrl::OnSelectLensStack(wxCommandEvent &e)
01691 {
01692     SelectAllParameters(true, false);
01693 };
01694 
01695 void ImagesTreeCtrl::OnUnselectLensStack(wxCommandEvent &e)
01696 {
01697     SelectAllParameters(false, false);
01698 };
01699 
01700 void ImagesTreeCtrl::OnChar(wxTreeEvent &e)
01701 {
01702     switch(e.GetKeyCode())
01703     {
01704         case WXK_INSERT:
01705             {
01706                 wxCommandEvent ev(wxEVT_COMMAND_MENU_SELECTED, XRCID("action_add_images"));
01707                 MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
01708                 break;
01709             };
01710         case WXK_DELETE:
01711             {
01712                 HuginBase::UIntSet imgs=GetSelectedImages();
01713                 if(imgs.size()>0)
01714                 {
01715                     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01716                         new PanoCommand::RemoveImagesCmd(*m_pano, imgs)
01717                     );
01718                 };
01719                 break;
01720             };
01721         case 1: //Ctrl+A
01722             {
01723                 SelectAll();
01724                 break;
01725             }
01726         default:
01727             e.Skip();
01728     };
01729 };
01730 
01731 void ImagesTreeCtrl::OnBeginEdit(wxTreeEvent &e)
01732 {
01733     m_editOldString=GetItemText(e.GetItem(), e.GetInt());
01734     if(m_editOldString.IsEmpty())
01735     {
01736         e.Veto();
01737     }
01738     else
01739     {
01740         ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
01741         if(data->IsGroup())
01742         {
01743             wxTreeItemIdValue cookie;
01744             wxTreeItemId item=GetFirstChild(e.GetItem(), cookie);
01745             data=static_cast<ImagesTreeData*>(GetItemData(item));
01746         };
01747         m_editVal=m_pano->getImage(data->GetImgNr()).getVar(m_columnVector[e.GetInt()]);
01748         SetItemText(e.GetItem(), e.GetInt(), hugin_utils::doubleTowxString(m_editVal));
01749         e.Allow();
01750     };
01751 };
01752 
01753 void ImagesTreeCtrl::OnEndEdit(wxTreeEvent &e)
01754 {
01755     if(e.IsEditCancelled())
01756     {
01757         //restore old string
01758         SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
01759         Refresh();
01760     }
01761     else
01762     {
01763         double val;
01764         if(!hugin_utils::str2double(e.GetLabel(),val))
01765         {
01766             //restore old string
01767             SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
01768             Refresh();
01769             e.Veto();
01770         }
01771         else
01772         {
01773             //only update if value was changed
01774             if(val!=m_editVal)
01775             {
01776                 ImagesTreeData* data=static_cast<ImagesTreeData*>(GetItemData(e.GetItem()));
01777                 if(data->IsGroup())
01778                 {
01779                     wxTreeItemIdValue cookie;
01780                     wxTreeItemId item=GetFirstChild(e.GetItem(), cookie);
01781                     data=static_cast<ImagesTreeData*>(GetItemData(item));
01782                 };
01783                 HuginBase::UIntSet imgs;
01784                 imgs.insert(data->GetImgNr());
01785                 if(m_columnVector[e.GetInt()]=="v")
01786                 {
01787                     if(m_pano->getImage(data->GetImgNr()).getProjection()==HuginBase::SrcPanoImage::FISHEYE_ORTHOGRAPHIC && val>190)
01788                     {
01789                         if(wxMessageBox(
01790                             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),
01791 #ifdef __WXMSW__
01792                             _("Hugin"),
01793 #else
01794                             wxT(""),
01795 #endif
01796                             wxICON_EXCLAMATION | wxYES_NO)==wxNO)
01797                         {
01798                             //restore old string
01799                             SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
01800                             Refresh();
01801                             e.Veto();
01802                             e.Skip();
01803                             return;
01804                         };
01805                     };
01806                 };
01807                 HuginBase::Variable var(m_columnVector[e.GetInt()], val);
01808                 PanoCommand::GlobalCmdHist::getInstance().addCommand(
01809                     new PanoCommand::SetVariableCmd(*m_pano, imgs, var)
01810                 );
01811                 //we need to veto the event otherwise the internal
01812                 //function does update the text to the full number
01813                 e.Veto();
01814             }
01815             else
01816             {
01817                 //restore old string
01818                 SetItemText(e.GetItem(), e.GetInt(), m_editOldString);
01819                 Refresh();
01820             };
01821         };
01822     };
01823     e.Skip();
01824 };
01825 
01826 void ImagesTreeCtrl::OnExecuteOperation(wxCommandEvent & e)
01827 {
01828     PanoOperation::PanoOperation* op=m_menuOperation[e.GetId()];
01829     PanoCommand::PanoCommand* cmd=op->GetCommand(this,*m_pano, GetSelectedImages(), m_guiLevel);
01830     if(cmd!=NULL)
01831     {
01832         PanoCommand::GlobalCmdHist::getInstance().addCommand(cmd);
01833     };
01834 };
01835 
01836 void ImagesTreeCtrl::OnLeftDblClick(wxMouseEvent &e)
01837 {
01838     if(!m_optimizerMode)
01839     {
01840         int flags;
01841         int col;
01842         wxTreeItemId item=HitTest(e.GetPosition(), flags, col);
01843         m_selectedColumn=col;
01844         wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, ID_EDIT);
01845         GetEventHandler()->AddPendingEvent(commandEvent);
01846     };
01847     e.Skip();
01848 };
01849 
01850 IMPLEMENT_DYNAMIC_CLASS(ImagesTreeCtrl, wxTreeListCtrl)
01851 
01852 ImagesTreeCtrlXmlHandler::ImagesTreeCtrlXmlHandler()
01853     : wxTreeListCtrlXmlHandler()
01854 {
01855 }
01856 
01857 wxObject *ImagesTreeCtrlXmlHandler::DoCreateResource()
01858 {
01859     XRC_MAKE_INSTANCE(cp, ImagesTreeCtrl)
01860 
01861     cp->Create(m_parentAsWindow,
01862                GetID(),
01863                GetPosition(), GetSize(),
01864                GetStyle(wxT("style")),
01865                GetName());
01866 
01867     SetupWindow( cp);
01868 
01869     return cp;
01870 }
01871 
01872 bool ImagesTreeCtrlXmlHandler::CanHandle(wxXmlNode *node)
01873 {
01874     return IsOfClass(node, wxT("ImagesTreeList"));
01875 }
01876 
01877 IMPLEMENT_DYNAMIC_CLASS(ImagesTreeCtrlXmlHandler, wxTreeListCtrlXmlHandler)
01878 
01879       

Generated on 1 May 2016 for Hugintrunk by  doxygen 1.4.7