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

Generated on 24 Feb 2017 for Hugintrunk by  doxygen 1.4.7