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

Generated on 19 Nov 2017 for Hugintrunk by  doxygen 1.4.7